├── srv ├── external │ ├── data │ │ ├── API_BUSINESS_PARTNER-A_BusinessPartner.csv │ │ └── API_BUSINESS_PARTNER-A_BusinessPartnerAddress.csv │ ├── API_BUSINESS_PARTNER.js │ └── API_BUSINESS_PARTNER.csn ├── service.cds ├── ui-annotations.cds └── service.js ├── .gitmodules ├── app ├── BusinessPartners │ ├── .npmrc │ ├── webapp │ │ ├── Component.js │ │ ├── i18n │ │ │ └── i18n.properties │ │ ├── annotations │ │ │ └── annotation.xml │ │ ├── index.html │ │ ├── manifest.json │ │ └── localService │ │ │ └── metadata.xml │ ├── manifest.yml │ ├── ui5-deploy.yaml │ ├── ui5-local.yaml │ ├── package.json │ ├── README.md │ ├── xs-app.json │ ├── ui5.yaml │ ├── package-old.json │ ├── .vscode │ │ └── launch.json │ └── wdio.conf.js └── fiori.html ├── documentation └── images │ ├── bpNew.png │ ├── lock.png │ ├── name.png │ ├── GuiLogin.JPG │ ├── clickBP.png │ ├── editBP.png │ ├── person.png │ ├── searchBP.png │ ├── BPListView.JPG │ ├── bpUIStatus.png │ ├── bpaddress.png │ ├── editValue.png │ ├── BPtransaction.JPG │ ├── TAM-diagram.JPG │ ├── releasedLock.png │ ├── attachmentList.png │ ├── fioriLaunchpad.JPG │ ├── solutionDiagram.jpg │ └── solution-diagram-latest.png ├── db ├── csv │ ├── my.businessPartnerValidation-StatusValues.csv │ ├── my.businessPartnerValidation-Notifications.csv │ └── my.businessPartnerValidation-Addresses.csv └── schema.cds ├── tests ├── legacy │ ├── chai-serve.js │ └── chai-test.js ├── util │ └── config.js ├── ui │ ├── wdi5.md │ ├── services │ │ ├── mockData.js │ │ └── bpApi.js │ ├── mta.yaml │ └── specs │ │ └── test.spec.js ├── req.http ├── BusinessPartnerValidation.test.js ├── unit │ └── service.test.js └── integration │ └── BPValidation.test.js ├── .gitignore ├── mock-event.http-request ├── xs-security.json ├── .eslintrc ├── em.json ├── .github └── workflows │ └── node.js.yml ├── .reuse └── dep5 ├── package.json ├── mta.yaml ├── README.md ├── LICENSES └── Apache-2.0.txt └── LICENSE /srv/external/data/API_BUSINESS_PARTNER-A_BusinessPartner.csv: -------------------------------------------------------------------------------- 1 | BusinessPartner 2 | "17100001" -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "mock-srv"] 2 | path = mock-srv 3 | url = ../cloud-extension-ecc-business-process 4 | branch = mock 5 | -------------------------------------------------------------------------------- /app/BusinessPartners/.npmrc: -------------------------------------------------------------------------------- 1 | @ui5:registry=https://registry.npmjs.org 2 | save = true 3 | save-exact = true 4 | strict-ssl = false 5 | -------------------------------------------------------------------------------- /documentation/images/bpNew.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/cloud-extension-s4hana-business-process/HEAD/documentation/images/bpNew.png -------------------------------------------------------------------------------- /documentation/images/lock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/cloud-extension-s4hana-business-process/HEAD/documentation/images/lock.png -------------------------------------------------------------------------------- /documentation/images/name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/cloud-extension-s4hana-business-process/HEAD/documentation/images/name.png -------------------------------------------------------------------------------- /documentation/images/GuiLogin.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/cloud-extension-s4hana-business-process/HEAD/documentation/images/GuiLogin.JPG -------------------------------------------------------------------------------- /documentation/images/clickBP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/cloud-extension-s4hana-business-process/HEAD/documentation/images/clickBP.png -------------------------------------------------------------------------------- /documentation/images/editBP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/cloud-extension-s4hana-business-process/HEAD/documentation/images/editBP.png -------------------------------------------------------------------------------- /documentation/images/person.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/cloud-extension-s4hana-business-process/HEAD/documentation/images/person.png -------------------------------------------------------------------------------- /documentation/images/searchBP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/cloud-extension-s4hana-business-process/HEAD/documentation/images/searchBP.png -------------------------------------------------------------------------------- /documentation/images/BPListView.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/cloud-extension-s4hana-business-process/HEAD/documentation/images/BPListView.JPG -------------------------------------------------------------------------------- /documentation/images/bpUIStatus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/cloud-extension-s4hana-business-process/HEAD/documentation/images/bpUIStatus.png -------------------------------------------------------------------------------- /documentation/images/bpaddress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/cloud-extension-s4hana-business-process/HEAD/documentation/images/bpaddress.png -------------------------------------------------------------------------------- /documentation/images/editValue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/cloud-extension-s4hana-business-process/HEAD/documentation/images/editValue.png -------------------------------------------------------------------------------- /documentation/images/BPtransaction.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/cloud-extension-s4hana-business-process/HEAD/documentation/images/BPtransaction.JPG -------------------------------------------------------------------------------- /documentation/images/TAM-diagram.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/cloud-extension-s4hana-business-process/HEAD/documentation/images/TAM-diagram.JPG -------------------------------------------------------------------------------- /documentation/images/releasedLock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/cloud-extension-s4hana-business-process/HEAD/documentation/images/releasedLock.png -------------------------------------------------------------------------------- /documentation/images/attachmentList.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/cloud-extension-s4hana-business-process/HEAD/documentation/images/attachmentList.png -------------------------------------------------------------------------------- /documentation/images/fioriLaunchpad.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/cloud-extension-s4hana-business-process/HEAD/documentation/images/fioriLaunchpad.JPG -------------------------------------------------------------------------------- /documentation/images/solutionDiagram.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/cloud-extension-s4hana-business-process/HEAD/documentation/images/solutionDiagram.jpg -------------------------------------------------------------------------------- /documentation/images/solution-diagram-latest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/cloud-extension-s4hana-business-process/HEAD/documentation/images/solution-diagram-latest.png -------------------------------------------------------------------------------- /db/csv/my.businessPartnerValidation-StatusValues.csv: -------------------------------------------------------------------------------- 1 | code;value;criticality;updateCode 2 | N;NEW;3;false 3 | P;IN PROCESS;2;false 4 | INV;INVALID;1;false 5 | V;VERIFIED;4;true 6 | C;COMPLETED;5;true -------------------------------------------------------------------------------- /tests/legacy/chai-serve.js: -------------------------------------------------------------------------------- 1 | const cds = require("@sap/cds"); 2 | 3 | cds.exec("run", "--with-mocks", "--in-memory?"); 4 | 5 | module.exports = new Promise((resolve) => { 6 | cds.on('listening', () => { 7 | resolve(cds.app); 8 | }); 9 | }); -------------------------------------------------------------------------------- /srv/external/data/API_BUSINESS_PARTNER-A_BusinessPartnerAddress.csv: -------------------------------------------------------------------------------- 1 | BusinessPartner,AddressID,StreetName,CityName,Country,postalCode 2 | "17100001","124462","Dietmar-Hopp-Allee 162","Walldorf","DE","12345" 3 | "17100005","124465","whitefield 162","Bangalore","IN","560066" -------------------------------------------------------------------------------- /tests/util/config.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({path : "../../.env"}) 2 | 3 | module.exports = { 4 | "mock": { 5 | "url": process.env.mockUrl 6 | }, 7 | "bp_app": { 8 | "main": "", 9 | "auth": process.env.appAuth 10 | } 11 | } -------------------------------------------------------------------------------- /db/csv/my.businessPartnerValidation-Notifications.csv: -------------------------------------------------------------------------------- 1 | ID;businessPartnerId;businessPartnerName;verificationStatus_code 2 | 2c728381-72ce-4fdd-8293-8add71579666;17100001;TestData1;N 3 | ff0bc005-710c-4097-a687-64ef380498f4;17100002;TestData2;P 4 | 16f00c9c-323f-4ce4-876f-efaefe1c6f69;17100003;TestData3;P 5 | -------------------------------------------------------------------------------- /app/BusinessPartners/webapp/Component.js: -------------------------------------------------------------------------------- 1 | sap.ui.define(['sap/fe/core/AppComponent'], function(AppComponent) { 2 | 'use strict'; 3 | 4 | return AppComponent.extend('com.sap.bp.BusinessPartners.Component', { 5 | metadata: { 6 | manifest: 'json' 7 | } 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # CAP BusinessPartnerValidation 2 | _out 3 | *.db 4 | connection.properties 5 | default-*.json 6 | gen/ 7 | node_modules/ 8 | target/ 9 | 10 | # Web IDE, App Studio 11 | .che/ 12 | .gen/ 13 | 14 | # MTA 15 | *_mta_build_tmp 16 | *.mtar 17 | mta_archives/ 18 | 19 | # Other 20 | .DS_Store 21 | *.orig 22 | *.log 23 | -------------------------------------------------------------------------------- /app/BusinessPartners/webapp/i18n/i18n.properties: -------------------------------------------------------------------------------- 1 | # This is the resource bundle for businesspartners 2 | 3 | #Texts for manifest.json 4 | 5 | #XTIT: Application name 6 | appTitle=Business Partner Validation 7 | 8 | #YDES: Application description 9 | appDescription=fiori elements application for s4 extension business partner validation 10 | -------------------------------------------------------------------------------- /tests/ui/wdi5.md: -------------------------------------------------------------------------------- 1 | # About the test cases 2 | 1. Test cases are in the 'specs' folder 3 | 2. The package.json in 'app/BusinessPartners' has additional dependencies needed to run the tests along with a 'wdi5' script to start the test execution 4 | 2. Configuration for Webdriverio and wdi5 is in file 'wdio.conf.js', located in the same folder as the above package.json file 5 | -------------------------------------------------------------------------------- /app/BusinessPartners/manifest.yml: -------------------------------------------------------------------------------- 1 | --- 2 | applications: 3 | - name: BusinessPartnerValidation-ui 4 | path: . 5 | memory: 128M 6 | buildpack: nodejs_buildpack 7 | env: 8 | destinations: > 9 | [ 10 | {"name": "srv-binding", "url":, "forwardAuthToken": true} 11 | ] 12 | services: 13 | - BusinessPartnerValidation-xsuaa 14 | -------------------------------------------------------------------------------- /app/BusinessPartners/ui5-deploy.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://sap.github.io/ui5-tooling/schema/ui5.yaml.json 2 | specVersion: '2.4' 3 | metadata: 4 | name: com.sap.bp.BusinessPartners 5 | type: application 6 | resources: 7 | configuration: 8 | propertiesFileSourceEncoding: UTF-8 9 | builder: 10 | resources: 11 | excludes: 12 | - "/test/**" 13 | - "/localService/**" -------------------------------------------------------------------------------- /mock-event.http-request: -------------------------------------------------------------------------------- 1 | { 2 | "body": { 3 | "content": "eyJCdXNpbmVzc1BhcnRuZXIiOiIxNzEwMDAwNSIsIkJ1c2luZXNzUGFydG5lcklzQmxvY2tlZCI6ZmFsc2V9", 4 | "file": false, 5 | "fileSize": false 6 | }, 7 | "headers": { 8 | "content-type": "application/json" 9 | }, 10 | "method": "POST", 11 | "title": "New HTTP Request", 12 | "url": "http://localhost:4004/api-business-partner/A_BusinessPartner" 13 | } -------------------------------------------------------------------------------- /tests/req.http: -------------------------------------------------------------------------------- 1 | 2 | POST http://localhost:4004/api-business-partner/A_BusinessPartner 3 | Content-Type: application/json 4 | 5 | { 6 | "BusinessPartner":"17100005", 7 | "BusinessPartnerIsBlocked":true, 8 | "BusinessPartnerFullName": "first lastname" 9 | } 10 | ### 11 | PATCH http://localhost:4004/api-business-partner/A_BusinessPartner('17100005') 12 | Content-Type: application/json 13 | 14 | { 15 | "BusinessPartnerIsBlocked":false 16 | } -------------------------------------------------------------------------------- /xs-security.json: -------------------------------------------------------------------------------- 1 | { 2 | "xsappname": "BusinessPartnerValidation", 3 | "tenant-mode": "dedicated", 4 | "description": "Business Partner Validation Security Profile", 5 | "scopes": [ 6 | { 7 | "name": "uaa.user", 8 | "description": "UAA" 9 | } 10 | ], 11 | "role-templates": [ 12 | { 13 | "name": "Token_Exchange", 14 | "description": "UAA", 15 | "scope-references": [ 16 | "uaa.user" 17 | ] 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /db/csv/my.businessPartnerValidation-Addresses.csv: -------------------------------------------------------------------------------- 1 | ID;addressId;country;cityName;streetName;postalCode;notifications_ID;businessPartnerId 2 | 58040e66-1dcd-4ffb-ab10-fdce32028b79;"124462";"DE";"Walldorf";"Dietmar-Hopp-Allee 162";"560066";2c728381-72ce-4fdd-8293-8add71579666;17100001 3 | 64e718c9-ff99-47f1-8ca3-950c850777d4;"124463";"DE";"Walldorf";"some street";"123456";ff0bc005-710c-4097-a687-64ef380498f4;17100002 4 | 64e718c9-ff99-47f1-8ca3-950c850777e5;"124464";"DE";"Walldorf";"some street";"123456";16f00c9c-323f-4ce4-876f-efaefe1c6f69;17100003 5 | -------------------------------------------------------------------------------- /app/BusinessPartners/ui5-local.yaml: -------------------------------------------------------------------------------- 1 | specVersion: '1.0' 2 | metadata: 3 | name: businesspartners 4 | type: application 5 | ui5Theme: sap_fiori_3 6 | server: 7 | customMiddleware: 8 | - name: ui5-middleware-simpleproxy 9 | afterMiddleware: compression 10 | mountPath: [/sales, /resources, /test-resources] 11 | configuration: 12 | baseUri: http://localhost:4004 13 | ui5Local: true 14 | - name: ui5-app-reloader 15 | afterMiddleware: compression 16 | configuration: 17 | port: 35729 18 | path: webapp 19 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "eslint:recommended", 3 | "env": { 4 | "node": true, 5 | "es6": true, 6 | "jest": true 7 | }, 8 | "parserOptions": { 9 | "ecmaVersion": 2017 10 | }, 11 | "globals": { 12 | "SELECT": true, 13 | "INSERT": true, 14 | "UPDATE": true, 15 | "DELETE": true, 16 | "CREATE": true, 17 | "DROP": true, 18 | "cds": true 19 | }, 20 | "rules": { 21 | "no-console": "off", 22 | "require-atomic-updates": "off" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /em.json: -------------------------------------------------------------------------------- 1 | { 2 | "emname": "bpems", 3 | "namespace": "refapps/bpems/abc", 4 | "version": "1.1.0", 5 | "options": { 6 | "management": true, 7 | "messagingrest": true, 8 | "messaging": true 9 | }, 10 | "rules": { 11 | "queueRules": { 12 | "publishFilter": [ 13 | "${namespace}/*" 14 | ], 15 | "subscribeFilter": [ 16 | "${namespace}/*" 17 | ] 18 | }, 19 | "topicRules": { 20 | "publishFilter": [ 21 | "${namespace}/*" 22 | ], 23 | "subscribeFilter": [ 24 | "${namespace}/*" 25 | ] 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /srv/external/API_BUSINESS_PARTNER.js: -------------------------------------------------------------------------------- 1 | const cds = global.cds || require('@sap/cds') 2 | module.exports = async srv => { 3 | 4 | const messaging = await cds.connect.to('messaging') 5 | // Mock events for s4 6 | srv.after("CREATE", async data => { 7 | const payload = {KEY: [{BUSINESSPARTNER: data.BusinessPartner}]}; 8 | await messaging.emit("S4H/BO/BusinessPartner/Created", payload); 9 | console.log('<< event emitted', payload); 10 | }); 11 | 12 | srv.after("UPDATE", async data => { 13 | const payload = {KEY: [{BUSINESSPARTNER: data.BusinessPartner}]}; 14 | await messaging.emit("S4H/BO/BusinessPartner/Changed", payload); 15 | console.log('<< event emitted', payload); 16 | }); 17 | } -------------------------------------------------------------------------------- /app/BusinessPartners/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "business-partners", 3 | "version": "0.0.1", 4 | "private": true, 5 | "devDependencies": { 6 | "@ui5/cli": "1.13.0", 7 | "@sap/ui5-builder-webide-extension": "1.0.x", 8 | "ui5-task-zipper": "^0.3.1", 9 | "@wdio/local-runner": "8.16.12", 10 | "@wdio/mocha-framework": "8.16.12", 11 | "@wdio/spec-reporter": "8.16.12", 12 | "wdio-chromedriver-service": "8.1.1", 13 | "wdio-ui5-service": "2.0.0" 14 | }, 15 | "scripts": { 16 | "build": "ui5 build --clean-dest --include-task=generateManifestBundle generateCachebusterInfo", 17 | "wdi5": "wdio run ./wdio.conf.js" 18 | }, 19 | "ui5": { 20 | "dependencies": [ 21 | "ui5-task-zipper", 22 | "@sap/ui5-builder-webide-extension" 23 | ] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/ui/services/mockData.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | newBp : 3 | { 4 | "BusinessPartner": "555", 5 | "BusinessPartnerName": "Max Mustermann", 6 | "BusinessPartnerFullName": "Max Mustermann", 7 | "FirstName": "Max", 8 | "LastName": "Mustermann", 9 | "BusinessPartnerIsBlocked": true, 10 | "to_BusinessPartnerAddress": [{ 11 | "BusinessPartner": "555", 12 | "AddressID": "1", 13 | "StreetName": "Platz der Republik", 14 | "HouseNumber": "1", 15 | "PostalCode": "10557", 16 | "CityName": "Berlin", 17 | "Country": "DE" 18 | }] 19 | }, 20 | 21 | newAdr : 22 | { 23 | "Street" : "17 June Avenue", 24 | "PostalCode" : "28376" 25 | } 26 | } -------------------------------------------------------------------------------- /app/BusinessPartners/README.md: -------------------------------------------------------------------------------- 1 | # businesspartners 2 | 3 | fiori elements application for s4 extension business partner validation 4 | 5 | ## Starting the generated app 6 | 7 | - This app has been generated using the SAP Fiori tools - App Generator, as part of the SAP Fiori tools suite. In order to launch the generated app, simply run the following from the generated app root folder: 8 | 9 | ``` 10 | npm start 11 | ``` 12 | 13 | - Is it also possible to run the application using mock data that reflects the OData Service URL supplied during application generation. In order to run the application with Mock Data, run the following from the generated app root folder: 14 | 15 | ``` 16 | npm run start-mock 17 | ``` 18 | 19 | ### Pre-requisites: 20 | 21 | 1. Active NodeJS LTS (Long Term Support) version and associated supported NPM version. (See https://nodejs.org) 22 | -------------------------------------------------------------------------------- /app/BusinessPartners/xs-app.json: -------------------------------------------------------------------------------- 1 | { 2 | "welcomeFile": "/index.html", 3 | "authenticationMethod": "route", 4 | "routes": [ 5 | { 6 | "source": "^/odata/v4/sales/(.*)$", 7 | "target": "/odata/v4/sales/$1", 8 | "destination": "BusinessPartnerValidation-srv", 9 | "authenticationType": "xsuaa", 10 | "csrfProtection": false 11 | }, 12 | { 13 | "source": "^/resources/(.*)$", 14 | "target": "/resources/$1", 15 | "authenticationType": "none", 16 | "destination": "ui5" 17 | }, 18 | { 19 | "source": "^/test-resources/(.*)$", 20 | "target": "/test-resources/$1", 21 | "authenticationType": "none", 22 | "destination": "ui5" 23 | }, 24 | { 25 | "source": "^(.*)$", 26 | "target": "$1", 27 | "service": "html5-apps-repo-rt", 28 | "authenticationType": "xsuaa" 29 | } 30 | ] 31 | } -------------------------------------------------------------------------------- /db/schema.cds: -------------------------------------------------------------------------------- 1 | namespace my.businessPartnerValidation; 2 | using { managed, cuid } from '@sap/cds/common'; 3 | 4 | entity Notifications: managed, cuid { 5 | businessPartnerId: String; 6 | businessPartnerName: String; 7 | verificationStatus: Association to StatusValues; 8 | addresses: Composition of many Addresses on addresses.notifications=$self; 9 | } 10 | 11 | entity Addresses: cuid { 12 | notifications: Association to Notifications; 13 | addressId:String; 14 | country:String; 15 | cityName:String; 16 | streetName: String; 17 | postalCode: String; 18 | isModified: Boolean default false; 19 | businessPartnerId: String; 20 | } 21 | @cds.autoexpose 22 | entity StatusValues { 23 | key code: String ; 24 | value: String; 25 | criticality: Integer; 26 | updateCode:Boolean; 27 | } 28 | 29 | annotate Notifications with { 30 | businessPartnerId @title:'BusinessPartner ID' @readonly; 31 | verificationStatus @title:'Verfication Status'; 32 | } 33 | -------------------------------------------------------------------------------- /.github/workflows/node.js.yml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions 3 | 4 | name: Node.js CI 5 | 6 | on: 7 | push: 8 | branches: [ main ] 9 | pull_request: 10 | branches: [ main ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | strategy: 18 | matrix: 19 | node-version: [18.x] 20 | # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ 21 | 22 | steps: 23 | - uses: actions/checkout@v2 24 | - name: Use Node.js ${{ matrix.node-version }} 25 | uses: actions/setup-node@v2 26 | with: 27 | node-version: ${{ matrix.node-version }} 28 | - run: npm install 29 | - run: npm install @cap-js/sqlite 30 | - run: npm run-script test:unit 31 | - run: npm run-script test:integration 32 | -------------------------------------------------------------------------------- /tests/BusinessPartnerValidation.test.js: -------------------------------------------------------------------------------- 1 | const cds = require('@sap/cds'); 2 | 3 | describe('BusinessPartnerValidation: Odata Protocol level testing', () => { 4 | const app = require('express')(); 5 | const request = require('supertest')(app); 6 | 7 | beforeAll(async ()=> { 8 | await cds.deploy(__dirname + '../srv/service').to('sqlite: :memory:'); 9 | await cds.serve('Sales').from(__dirname + '../srv/service').in(app); 10 | }); 11 | 12 | it('Service $metadata document', async () => { 13 | const response = await request 14 | .get('/odata/v4/sales/$metadata') 15 | .expect('Content-Type', /^application\/xml/) 16 | .expect(200) 17 | }); 18 | }); 19 | 20 | describe('BusinessPartnerValidation: CDS service level Testing', () => { 21 | let srv, Notification; 22 | beforeAll(async () => { 23 | srv = await cds.serve('Sales').from(__dirname + '../srv/service'); 24 | Notification = srv.entities.Notification; 25 | expect(Notification).toBeDefined(); 26 | }); 27 | }); -------------------------------------------------------------------------------- /app/BusinessPartners/ui5.yaml: -------------------------------------------------------------------------------- 1 | specVersion: '1.0' 2 | metadata: 3 | name: businesspartners 4 | type: application 5 | ui5Version: 6 | ui5Theme: sap_fiori_3 7 | resources: 8 | configuration: 9 | propertiesFileSourceEncoding: UTF-8 10 | server: 11 | customMiddleware: 12 | - name: ui5-middleware-simpleproxy 13 | afterMiddleware: compression 14 | mountPath: [ /sales, /resources, /test-resources ] 15 | configuration: 16 | baseUri: http://localhost:4004 17 | ui5Uri: https://sapui5.hana.ondemand.com 18 | ui5Version: 19 | - name: ui5-app-reloader 20 | afterMiddleware: compression 21 | configuration: 22 | port: 35729 23 | path: webapp 24 | builder: 25 | customTasks: 26 | - name: webide-extension-task-updateManifestJson 27 | beforeTask: generateManifestBundle 28 | configuration: 29 | appFolder: webapp 30 | destDir: dist 31 | - name: ui5-task-zipper 32 | afterTask: generateCachebusterInfo 33 | configuration: 34 | archiveName: comsapbpBusinessPartners 35 | additionalFiles: 36 | - xs-app.json -------------------------------------------------------------------------------- /tests/ui/services/bpApi.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios'); 2 | const bP = require("./mockData").newBp 3 | const endPoint = require("../../util/config").mock 4 | 5 | class BpApiService { 6 | async postMethod(browser) { 7 | try { 8 | let response = await axios.post(`${endPoint.url}`, bP); 9 | return response; 10 | } 11 | 12 | catch(err) { 13 | console.log(`Status : ${err.response.data.error.code}`) 14 | console.log(`Error Message : ${err.response.data.error.message}`) 15 | await browser.closeWindow() 16 | process.exit(); 17 | } 18 | } 19 | 20 | async deleteMethod() { 21 | try{ 22 | let response = await axios.delete(`${endPoint.url}('${bP.BusinessPartner}')`) 23 | return response 24 | } 25 | 26 | catch(err){ 27 | console.log(`Status : ${err.response.data.error.code}`) 28 | console.log(`Error Message : ${err.response.data.error.message}`) 29 | await browser.closeWindow() 30 | process.exit(); 31 | } 32 | } 33 | } 34 | module.exports = new BpApiService(); -------------------------------------------------------------------------------- /app/BusinessPartners/package-old.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "businesspartners", 3 | "version": "0.0.1", 4 | "private": true, 5 | "sapux": true, 6 | "description": "fiori elements application for s4 extension business partner validation", 7 | "keywords": [ 8 | "ui5", 9 | "openui5", 10 | "sapui5" 11 | ], 12 | "main": "webapp/index.html", 13 | "scripts": { 14 | "deploy-config": "npx -p @sap/ux-ui5-tooling fiori add deploy-config cf", 15 | "build:cf": "ui5 build preload --clean-dest --config ui5-deploy.yaml --include-task=generateManifestBundle generateCachebusterInfo" 16 | }, 17 | 18 | "devDependencies": { 19 | "@ui5/cli": "^2.11.1", 20 | "@ui5/fs": "^2.0.6", 21 | "@ui5/logger": "^2.0.1", 22 | "@sap/ux-ui5-tooling": "1", 23 | "rimraf": "3.0.2", 24 | "@sap/ux-specification": "latest", 25 | "@sap/ui5-builder-webide-extension": "1.0.x", 26 | "ui5-task-zipper": "^0.3.1", 27 | "mbt": "^1.0.15" 28 | }, 29 | "ui5": { 30 | "dependencies": [ 31 | "@sap/ui5-builder-webide-extension", 32 | "ui5-task-zipper", 33 | "mbt" 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/BusinessPartners/webapp/annotations/annotation.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /srv/service.cds: -------------------------------------------------------------------------------- 1 | using my.businessPartnerValidation as my from '../db/schema'; 2 | using API_BUSINESS_PARTNER as BUPA_API from './external/API_BUSINESS_PARTNER'; 3 | namespace service.businessPartnerValidation; 4 | 5 | 6 | service SalesService @(requires:'authenticated-user') { 7 | @odata.draft.enabled 8 | entity Notifications as projection on my.Notifications; 9 | entity Addresses as projection on my.Addresses; 10 | 11 | @readonly entity BusinessPartnerAddress as projection on BUPA_API.A_BusinessPartnerAddress{ 12 | key BusinessPartner as businessPartnerId, 13 | AddressID as addressId, 14 | Country as country, 15 | CityName as cityName , 16 | StreetName as streetName, 17 | PostalCode as postalCode 18 | }; 19 | 20 | @readonly entity BusinessPartner as projection on BUPA_API.A_BusinessPartner{ 21 | key BusinessPartner as businessPartnerId, 22 | BusinessPartnerFullName as businessPartnerName, 23 | SearchTerm1 as searchTerm1, 24 | BusinessPartnerIsBlocked as businessPartnerIsBlocked 25 | }; 26 | 27 | event BusinessPartnerVerified { 28 | businessPartner: String; 29 | businessPartnerName: String; 30 | verificationStatus: String; 31 | addressId: String; 32 | streetName: String; 33 | postalCode: String; 34 | country: String; 35 | addressModified: String; 36 | } 37 | 38 | } 39 | 40 | 41 | -------------------------------------------------------------------------------- /app/BusinessPartners/webapp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{appTitle}} 8 | 9 | 24 | 25 | 26 | 34 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /app/BusinessPartners/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Start businesspartners", 6 | "type": "node", 7 | "request": "launch", 8 | "runtimeExecutable": "npm", 9 | "cwd": "/Users/i332371/git/node-webhook-queue/cloud-sdk-sample/CAP/BusinessPartnerValidation/app/businesspartners", 10 | "windows": { 11 | "runtimeExecutable": "npm.cmd" 12 | }, 13 | "runtimeArgs": [ 14 | "run-script", 15 | "start" 16 | ], 17 | "console": "integratedTerminal", 18 | "internalConsoleOptions": "neverOpen", 19 | "noDebug": true, 20 | "port": 9229, 21 | "env": { 22 | "DEBUG": "--inspect" 23 | } 24 | }, 25 | { 26 | "name": "Start businesspartners with UI5 Version", 27 | "type": "node", 28 | "request": "launch", 29 | "runtimeExecutable": "npm", 30 | "cwd": "/Users/i332371/git/node-webhook-queue/cloud-sdk-sample/CAP/BusinessPartnerValidation/app/businesspartners", 31 | "windows": { 32 | "runtimeExecutable": "npm.cmd" 33 | }, 34 | "runtimeArgs": [ 35 | "run-script", 36 | "start", 37 | "${input:UI5VersionV4}" 38 | ], 39 | "console": "integratedTerminal", 40 | "internalConsoleOptions": "neverOpen", 41 | "noDebug": true, 42 | "port": 9229, 43 | "env": { 44 | "DEBUG": "--inspect" 45 | } 46 | } 47 | ], 48 | "inputs": [ 49 | { 50 | "id": "UI5VersionV4", 51 | "type": "command", 52 | "command": "sap.ux.appGenerator.ui5VersionV4" 53 | } 54 | ] 55 | } -------------------------------------------------------------------------------- /.reuse/dep5: -------------------------------------------------------------------------------- 1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: cloud-extension-s4hana-business-process 3 | Upstream-Contact: indusankar89 4 | Source: https://github.com/SAP-samples/cloud-extension-s4hana-business-process 5 | Disclaimer: The code in this project may include calls to APIs ("API Calls") of 6 | SAP or third-party products or services developed outside of this project 7 | ("External Products"). 8 | "APIs" means application programming interfaces, as well as their respective 9 | specifications and implementing code that allows software to communicate with 10 | other software. 11 | API Calls to External Products are not licensed under the open source license 12 | that governs this project. The use of such API Calls and related External 13 | Products are subject to applicable additional agreements with the relevant 14 | provider of the External Products. In no event shall the open source license 15 | that governs this project grant any rights in or to any External Products,or 16 | alter, expand or supersede any terms of the applicable additional agreements. 17 | If you have a valid license agreement with SAP for the use of a particular SAP 18 | External Product, then you may make use of any API Calls included in this 19 | project's code for that SAP External Product, subject to the terms of such 20 | license agreement. If you do not have a valid license agreement for the use of 21 | a particular SAP External Product, then you may only make use of any API Calls 22 | in this project for that SAP External Product for your internal, non-productive 23 | and non-commercial test and evaluation of such API Calls. Nothing herein grants 24 | you any rights to use or access any SAP External Product, or provide any third 25 | parties the right to use of access any SAP External Product, through API Calls. 26 | 27 | Files: * 28 | Copyright: 2025 SAP SE or an SAP affiliate company and cloud-extension-s4hana-business-process contributors 29 | License: Apache-2.0 30 | -------------------------------------------------------------------------------- /app/fiori.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Cloud Extension S4HANA business Process 10 | 11 | 35 | 36 | 40 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "BusinessPartnerValidation", 3 | "version": "1.0.0", 4 | "description": "A simple CAP project.", 5 | "license": "ISC", 6 | "dependencies": { 7 | "@sap-cloud-sdk/http-client": "^3.2.0", 8 | "@sap-cloud-sdk/util": "^3.2.0", 9 | "@sap/cds": "^8", 10 | "@cap-js/hana": "^1", 11 | "@sap/xb-msg-amqp-v100": "^0.9.39", 12 | "@sap/xssec": "^4", 13 | "express": "^4", 14 | "grunt": "^1.5.3", 15 | "npm": "^8.11.0", 16 | "passport": "^0.6.0", 17 | "postcode-validator": "^3.1.1" 18 | }, 19 | "scripts": { 20 | "start": "npx cds-serve", 21 | "test": "npm run test:integration", 22 | "test:integration": "jest tests/integration/BPValidation.test.js", 23 | "test:unit": "jest tests/unit/service.test.js", 24 | "test:legacy": "mocha tests/legacy/chai-test.js --timeout 15000 --exit" 25 | }, 26 | "devDependencies": { 27 | "@cap-js/sqlite": "^1.1.0", 28 | "axios": "^0.21.1", 29 | "chai": "^4.3.4", 30 | "chai-http": "^4.3.0", 31 | "jest": "*", 32 | "mocha": "^9.2.1", 33 | "dotenv": "^16.3.1" 34 | }, 35 | "cds": { 36 | "features": { 37 | "kibana_formatter": true 38 | }, 39 | "hana": { 40 | "deploy-format": "hdbtable" 41 | }, 42 | "requires": { 43 | "messaging": { 44 | "kind": "local-messaging", 45 | "[production]": { 46 | "kind": "enterprise-messaging-shared", 47 | "queue": { 48 | "name": "refapps/bpems/abc/BusinessPartnerValidation-srv/1234" 49 | }, 50 | "publishPrefix": "$namespace/", 51 | "subscribePrefix": "$namespace/" 52 | } 53 | }, 54 | "[production]": { 55 | "db": { 56 | "kind": "hana", 57 | "model": [ 58 | "db", 59 | "srv" 60 | ] 61 | } 62 | }, 63 | "API_BUSINESS_PARTNER": { 64 | "kind": "odata-v2", 65 | "model": "srv/external/API_BUSINESS_PARTNER", 66 | "csrf": true, 67 | "csrfInBatch": true, 68 | "[production]": { 69 | "credentials": { 70 | "destination": "bupa", 71 | "requestTimeout": 18000000 72 | } 73 | } 74 | }, 75 | "uaa": { 76 | "kind": "xsuaa" 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /tests/unit/service.test.js: -------------------------------------------------------------------------------- 1 | const SalesService = require('../../srv/service.js'); 2 | 3 | 4 | describe("Unit Test suite for methods", () => { 5 | let salesService, bupaSrv, cdsSpy, LOG; 6 | 7 | beforeAll(() => { 8 | 9 | bupaSrv = jest.fn(); 10 | bupaSrv.run = jest.fn(); 11 | 12 | jest.spyOn(cds.ql, 'UPDATE').mockImplementation(() => { 13 | return { 14 | "set": jest.fn().mockImplementation(() => { 15 | return { 16 | "where": jest.fn() 17 | } 18 | }) 19 | } 20 | }) 21 | LOG = cds.log("Test cases") 22 | 23 | }) 24 | beforeEach(async () => { 25 | salesService = new SalesService(); 26 | }) 27 | 28 | afterEach(() => { 29 | jest.clearAllMocks(); 30 | }); 31 | 32 | it("bupaSrv .toBeCalled() once on emitEvent", async () => { 33 | 34 | const payload = { 35 | "businessPartnerId": "123", 36 | "addresses": [{ 37 | "addressId": "1", 38 | "isModified": false, 39 | }] 40 | } 41 | cdsSpy = jest.spyOn(cds, 'run').mockResolvedValue(payload) 42 | await salesService.emitEvent(bupaSrv, {}, LOG); 43 | expect(cdsSpy).toBeCalled() 44 | expect(bupaSrv.run).toBeCalled() 45 | }) 46 | 47 | it("bupaSrv .toBeCalled() twice on emitEvent", async () => { 48 | 49 | const payload = { 50 | "businessPartnerId": "123", 51 | "addressId": "1", 52 | "searchTerm1": "V", 53 | "streetName": "XX", 54 | "postalCode": "XX", 55 | "addresses": [{ 56 | "isModified": true 57 | }] 58 | } 59 | cdsSpy = jest.spyOn(cds, 'run').mockResolvedValue(payload) 60 | await salesService.emitEvent(bupaSrv, {}, LOG); 61 | expect(cdsSpy).toBeCalled() 62 | expect(bupaSrv.run).toHaveBeenCalledTimes(2) 63 | }) 64 | 65 | it("readMsg returns correct BUSINESSPARTNER for s/4Hana 2019", async () => { 66 | const msg = { data: { KEY: [{ BUSINESSPARTNER: "1234" }] } }; 67 | let bp = salesService.readMsg(msg) 68 | expect(bp).toBe("1234") 69 | }) 70 | 71 | it("readMsg returns correct BUSINESSPARTNER for s/4Hana 2020 and above", async () => { 72 | const msg = { data: { BusinessPartner: "1234" }, headers: { specversion: "1.0" } }; 73 | let bp = salesService.readMsg(msg) 74 | expect(bp).toBe("1234") 75 | }) 76 | 77 | it("validatePostcode returns true for correct postal code", async () => { 78 | const payload = { 79 | addressId: '124462', 80 | country: 'DE', 81 | cityName: 'Walldorf' 82 | } 83 | const cdsSpy = jest.spyOn(cds, 'run').mockResolvedValue(payload); 84 | const data = { 85 | postalCode: '99998', 86 | isModified: true 87 | } 88 | const isValidPinCode = await salesService.validatePostcode(data, LOG); 89 | expect(cdsSpy).toBeCalled(); 90 | expect(isValidPinCode).toBe(true) 91 | }) 92 | 93 | it("validatePostcode returns false for incorrect postal code", async () => { 94 | const payload = { 95 | addressId: '1234', 96 | country: 'DE', 97 | cityName: 'Walldorf' 98 | } 99 | const cdsSpy = jest.spyOn(cds, 'run').mockResolvedValue(payload); 100 | const data = { 101 | postalCode: '123456', 102 | isModified: true 103 | } 104 | const isValidPinCode = await salesService.validatePostcode(data, LOG); 105 | expect(cdsSpy).toBeCalled(); 106 | expect(isValidPinCode).toBe(false) 107 | }) 108 | }) -------------------------------------------------------------------------------- /srv/ui-annotations.cds: -------------------------------------------------------------------------------- 1 | 2 | using service.businessPartnerValidation.SalesService as my from './service'; 3 | 4 | annotate my.Addresses with @( 5 | UI: { 6 | HeaderInfo: { 7 | TypeName: 'Address', 8 | TypeNamePlural: 'Addresses', 9 | Title: { $Type: 'UI.DataField', Value: addressId } 10 | }, 11 | SelectionFields: [ identifier, title, availability, price], 12 | LineItem: [ 13 | {$Type: 'UI.DataField', Value: addressId, ![@HTML5.CssDefaults] : {width : '16.66%'}}, 14 | {$Type: 'UI.DataField', Value: businessPartnerId, ![@HTML5.CssDefaults] : {width : '16.66%'}}, 15 | {$Type: 'UI.DataField', Value: streetName,![@HTML5.CssDefaults] : {width : '16.66%'}}, 16 | {$Type: 'UI.DataField', Value: cityName,![@HTML5.CssDefaults] : {width : '16.66%'}}, 17 | {$Type: 'UI.DataField', Value: country,![@HTML5.CssDefaults] : {width : '16.66%'}}, 18 | {$Type: 'UI.DataField', Value: postalCode,![@HTML5.CssDefaults] : {width : '16.66%'}} 19 | ], 20 | HeaderFacets: [ 21 | {$Type: 'UI.ReferenceFacet', ID: 'BP', Target: '@UI.DataPoint#BP'}, 22 | {$Type: 'UI.ReferenceFacet', ID: 'Status', Target: '@UI.DataPoint#Status'} 23 | ], 24 | DataPoint#BP: {Value: businessPartnerId, Title: 'Business Partner ID'}, 25 | DataPoint#Status: {Value: notification.verificationStatus, Title: 'Verification Status'} 26 | } 27 | ); 28 | 29 | annotate my.Addresses with { 30 | addressId @( Common.Label : 'Address ID' ) @readonly; 31 | businessPartnerId @( Common.Label : 'Business Partner ID' ) @readonly; 32 | streetName @( Common.Label : 'Street Name' ); 33 | cityName @( Common.Label : 'City Name' ) @readonly; 34 | country @( Common.Label : 'Country' ) @readonly; 35 | postalCode @( Common.Label : 'Postal Code' ); 36 | } 37 | 38 | annotate my.Notifications with { 39 | businessPartnerId @( Common.Label : 'Business Partner ID' ); 40 | businessPartnerName @( Common.Label : 'Business Partner Name' ) @readonly; 41 | verificationStatus @( Common.Label : 'Verification Status' ); 42 | } 43 | 44 | annotate my.Notifications with @( 45 | UI:{ 46 | UpdateHidden: verificationStatus.updateCode, 47 | HeaderInfo: { 48 | TypeName: '{i18n>Notification}', 49 | TypeNamePlural: '{i18n>Notifications}', 50 | Title: { $Type: 'UI.DataField', Value: businessPartnerId } 51 | }, 52 | SelectionFields: [ businessPartnerId, businessPartnerName,verificationStatus_code], 53 | LineItem: [ 54 | {$Type: 'UI.DataField', Value: businessPartnerId, ![@HTML5.CssDefaults] : {width : '33.33%'}}, 55 | {$Type: 'UI.DataField', Value: businessPartnerName, ![@HTML5.CssDefaults] : {width : '33.33%'}}, 56 | {$Type: 'UI.DataField', Value: verificationStatus.value, Criticality: verificationStatus.criticality,![@HTML5.CssDefaults] : {width : '33.33%'}} 57 | 58 | ], 59 | HeaderFacets: [ 60 | {$Type: 'UI.ReferenceFacet', ID: 'HeaderBpStatus', Target: '@UI.DataPoint#BpName'}, 61 | {$Type : 'UI.ReferenceFacet', Target : '@UI.FieldGroup#Detail'} 62 | 63 | ], 64 | Facets: [ 65 | {$Type: 'UI.ReferenceFacet', Target: 'addresses/@UI.LineItem', Label: 'Address Facet'}, 66 | ], 67 | DataPoint#BpName: {Value: businessPartnerName, Title: 'Business Partner Name'}, 68 | FieldGroup #Detail : {Data : [ 69 | {$Type: 'UI.DataField', Value: verificationStatus_code, Title: 'Verification Status'} 70 | ]} 71 | } 72 | ); 73 | 74 | annotate my.Notifications @( 75 | Capabilities: { 76 | Insertable : false, 77 | Deletable : true, 78 | Updatable : true, 79 | }); 80 | 81 | annotate my.Addresses @( 82 | Capabilities: { 83 | Deletable : false, 84 | Insertable : false, 85 | }); 86 | 87 | annotate my.Notifications with { 88 | verificationStatus @( 89 | Common: { 90 | ValueList: {entity: 'StatusValues'}, 91 | ValueListWithFixedValues, 92 | FieldControl: #Mandatory 93 | } 94 | ); 95 | }; 96 | 97 | annotate my.StatusValues with { 98 | code @Common : { 99 | Text : value, 100 | TextArrangement : #TextOnly 101 | } @title : 'Code'; 102 | value @title: 'Verification Status'; 103 | }; 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /tests/legacy/chai-test.js: -------------------------------------------------------------------------------- 1 | const chai = require("chai"); 2 | const chaiHttp = require("chai-http"); 3 | const server = require("./chai-serve"); 4 | 5 | // Configure chai 6 | chai.use(chaiHttp); 7 | chai.should(); 8 | 9 | let app = null; 10 | 11 | before((done) => { 12 | server.then((result) => { 13 | app = result; 14 | done(); 15 | }); 16 | }); 17 | 18 | describe("Sanity Test", () => { 19 | describe("GET /sales/Notifications", () => { 20 | it("+ should return a list of notifications", (done) => { 21 | chai.request(app) 22 | .get("/sales/Notifications") 23 | .auth("test:test") 24 | .end((error, response) => { 25 | try { 26 | response.should.have.status(200); 27 | response.body.value.should.be.an("array").to.have.lengthOf(2); 28 | done(); 29 | } catch (error) { 30 | done(error); 31 | } 32 | }); 33 | }); 34 | }); 35 | 36 | describe("GET /api-business-partner/A_BusinessPartner", () => { 37 | it("+ should reach mock implementation", (done) => { 38 | chai.request(app) 39 | .get("/api-business-partner/A_BusinessPartner") 40 | .end((error, response) => { 41 | try { 42 | response.should.have.status(200); 43 | done(); 44 | } catch (error) { 45 | done(error); 46 | } 47 | }); 48 | }); 49 | }); 50 | }); 51 | 52 | describe("Business Partner Validation", () => { 53 | it("+ create new business partner", (done) => { 54 | const payload = { 55 | "BusinessPartner":"17100015", 56 | "BusinessPartnerIsBlocked":true, 57 | "BusinessPartnerFullName": "first lastname" 58 | } 59 | chai.request(app) 60 | .post("/api-business-partner/A_BusinessPartner") 61 | .send(payload) 62 | .end((error, response) => { 63 | try { 64 | response.should.have.status(201); 65 | done(); 66 | } catch (error) { 67 | done(error); 68 | } 69 | }); 70 | }); 71 | 72 | 73 | 74 | it("+ should return a list of new notifications", (done) => { 75 | chai.request(app) 76 | .get("/sales/Notifications?$filter=businessPartnerId eq '17100015'") 77 | .auth("test:test") 78 | .end((error, response) => { 79 | try { 80 | response.should.have.status(200); 81 | response.body.value.should.be.an("array").to.have.lengthOf(1); 82 | done(); 83 | } catch (error) { 84 | done(error); 85 | } 86 | }); 87 | }); 88 | 89 | 90 | describe("Draft Choreography", () => { 91 | 92 | it("+ set the Notification to draft", (done) => { 93 | chai.request(app) 94 | .post("/sales/Notifications(ID=2c728381-72ce-4fdd-8293-8add71579666,IsActiveEntity=true)/service.businessPartnerValidation.SalesService.draftEdit?$select=HasActiveEntity,HasDraftEntity,ID,IsActiveEntity,businessPartnerId,businessPartnerName,verificationStatus_code&$expand=DraftAdministrativeData($select=DraftUUID,InProcessByUser),verificationStatus($select=code,updateCode)") 95 | .send({"PreserveChanges":true}) 96 | .auth("test:test") 97 | .end((error, response) => { 98 | try { 99 | response.should.have.status(201); 100 | done(); 101 | } catch (error) { 102 | done(error); 103 | } 104 | }); 105 | }); 106 | it("+ patch the changes", (done) => { 107 | chai.request(app) 108 | .patch("/sales/Notifications(ID=2c728381-72ce-4fdd-8293-8add71579666,IsActiveEntity=false)") 109 | .send({"verificationStatus_code": "V"}) 110 | .auth("test:test") 111 | .end((error, response) => { 112 | try { 113 | response.should.have.status(200); 114 | done(); 115 | } catch (error) { 116 | done(error); 117 | } 118 | }); 119 | }); 120 | it("+ Side effects qualifier", (done) => { 121 | chai.request(app) 122 | .post("/sales/Notifications(ID=2c728381-72ce-4fdd-8293-8add71579666,IsActiveEntity=false)/service.businessPartnerValidation.SalesService.draftPrepare") 123 | .send({ "SideEffectsQualifier": "" }) 124 | .auth("test:test") 125 | .end((error, response) => { 126 | try { 127 | response.should.have.status(200); 128 | done(); 129 | } catch (error) { 130 | done(error); 131 | } 132 | }); 133 | }); 134 | it("+ Activate the draft", (done) => { 135 | chai.request(app) 136 | .post("/sales/Notifications(ID=2c728381-72ce-4fdd-8293-8add71579666,IsActiveEntity=false)/service.businessPartnerValidation.SalesService.draftActivate") 137 | .send({}) 138 | .auth("test:test") 139 | .end((error, response) => { 140 | try { 141 | response.should.have.status(201); 142 | done(); 143 | } catch (error) { 144 | done(error); 145 | } 146 | }); 147 | }); 148 | 149 | it("+ Test the verfication status", (done) => { 150 | chai.request(app) 151 | .get("/sales/Notifications(ID=2c728381-72ce-4fdd-8293-8add71579666,IsActiveEntity=true)") 152 | .auth("test:test") 153 | .end((error, response) => { 154 | try { 155 | response.should.have.status(200); 156 | response.body.verificationStatus_code.should.equal("V"); 157 | done(); 158 | } catch (error) { 159 | done(error); 160 | } 161 | }); 162 | }); 163 | 164 | }); 165 | 166 | 167 | 168 | }); -------------------------------------------------------------------------------- /mta.yaml: -------------------------------------------------------------------------------- 1 | _schema-version: "3.1" 2 | ID: BusinessPartnerValidation 3 | description: A simple CAP project. 4 | version: 1.0.0 5 | modules: 6 | - name: BusinessPartnerValidation-srv 7 | type: nodejs 8 | path: gen/srv 9 | properties: 10 | EXIT: 1 11 | requires: 12 | - name: BusinessPartnerValidation-db 13 | - name: BusinessPartnerValidation-xsuaa 14 | - name: BusinessPartnerValidation-dest 15 | - name: BusinessPartnerValidation-ems 16 | - name: BusinessPartnerValidation-cs 17 | - name: BusinessPartnerValidation-logs 18 | provides: 19 | - name: srv_api 20 | properties: 21 | srv-url: ${default-url} 22 | parameters: 23 | memory: 256MB 24 | - name: db 25 | type: hdb 26 | path: gen/db 27 | requires: 28 | - name: BusinessPartnerValidation-db 29 | parameters: 30 | app-name: BusinessPartnerValidation-db 31 | memory: 128MB 32 | - name: BusinessPartnerValidation-launchpad 33 | type: com.sap.application.content 34 | requires: 35 | - name: BusinessPartnerValidation-xsuaa 36 | parameters: 37 | service-key: 38 | name: BusinessPartnerValidation-xsuaa-key 39 | - name: BusinessPartnerValidation-html5-repo-host 40 | parameters: 41 | service-key: 42 | name: BusinessPartnerValidation-html5-repo-host-key 43 | - name: srv_api 44 | - name: BusinessPartnerValidation-dest 45 | parameters: 46 | content-target: true 47 | parameters: 48 | content: 49 | instance: 50 | destinations: 51 | - Authentication: OAuth2UserTokenExchange 52 | Name: BusinessPartnerValidation-srv 53 | TokenServiceInstanceName: BusinessPartnerValidation-xsuaa 54 | TokenServiceKeyName: BusinessPartnerValidation-xsuaa-key 55 | URL: ~{srv_api/srv-url} 56 | sap.cloud.service: com.sap.bp.BusinessPartners.one 57 | - Name: BusinessPartnerValidation-html5-repo-host 58 | ServiceInstanceName: BusinessPartnerValidation-html5-repo-host 59 | ServiceKeyName: BusinessPartnerValidation-html5-repo-host-key 60 | sap.cloud.service: com.sap.bp.BusinessPartners.one 61 | - Authentication: OAuth2UserTokenExchange 62 | Name: BusinessPartnerValidation-xsuaa 63 | ServiceInstanceName: BusinessPartnerValidation-xsuaa 64 | ServiceKeyName: BusinessPartnerValidation-xsuaa-key 65 | sap.cloud.service: com.sap.bp.BusinessPartners.one 66 | existing_destinations_policy: update 67 | build-parameters: 68 | no-source: true 69 | 70 | - name: BusinessPartnerValidation-app-content 71 | type: com.sap.application.content 72 | path: . 73 | requires: 74 | - name: BusinessPartnerValidation-html5-repo-host 75 | parameters: 76 | content-target: true 77 | build-parameters: 78 | build-result: resources 79 | requires: 80 | - artifacts: 81 | - comsapbpBusinessPartners.zip 82 | name: comsapbpBusinessPartners 83 | target-path: resources/ 84 | 85 | - name: comsapbpBusinessPartners 86 | type: html5 87 | path: app/BusinessPartners 88 | build-parameters: 89 | build-result: dist 90 | builder: custom 91 | commands: 92 | - npm install 93 | - npm run build 94 | supported-platforms: [] 95 | 96 | resources: 97 | - name: BusinessPartnerValidation-db 98 | type: com.sap.xs.hdi-container 99 | parameters: 100 | service: hana 101 | service-plan: hdi-shared 102 | properties: 103 | hdi-service-name: ${service-name} 104 | - name: BusinessPartnerValidation-xsuaa 105 | type: org.cloudfoundry.managed-service 106 | parameters: 107 | path: ./xs-security.json 108 | service: xsuaa 109 | service-plan: application 110 | - name: BusinessPartnerValidation-dest 111 | type: org.cloudfoundry.managed-service 112 | parameters: 113 | config: 114 | HTML5Runtime_enabled: true 115 | init_data: 116 | instance: 117 | destinations: 118 | - Authentication: NoAuthentication 119 | Name: ui5 120 | ProxyType: Internet 121 | Type: HTTP 122 | URL: https://ui5.sap.com 123 | existing_destinations_policy: update 124 | version: 1.0.0 125 | service: destination 126 | service-plan: lite 127 | - name: BusinessPartnerValidation-ems 128 | type: org.cloudfoundry.managed-service 129 | parameters: 130 | path: ./em.json 131 | service: enterprise-messaging 132 | service-plan: default 133 | - name: BusinessPartnerValidation-cs 134 | type: org.cloudfoundry.managed-service 135 | parameters: 136 | service: connectivity 137 | service-plan: lite 138 | - name: BusinessPartnerValidation-logs 139 | type: org.cloudfoundry.managed-service 140 | parameters: 141 | service: application-logs 142 | service-plan: lite 143 | 144 | - name: BusinessPartnerValidation-html5-repo-host 145 | type: org.cloudfoundry.managed-service 146 | parameters: 147 | service: html5-apps-repo 148 | service-plan: app-host 149 | parameters: 150 | deploy_mode: html5-repo 151 | enable-parallel-deployments: true 152 | build-parameters: 153 | before-all: 154 | - builder: custom 155 | commands: 156 | - npm install 157 | - npx -p @sap/cds-dk cds build --production 158 | -------------------------------------------------------------------------------- /tests/ui/mta.yaml: -------------------------------------------------------------------------------- 1 | _schema-version: "3.1" 2 | ID: BusinessPartnerValidationS4 3 | description: A simple CAP project. 4 | version: 1.0.0 5 | modules: 6 | - name: BusinessPartnerValidation-srv 7 | type: nodejs 8 | path: gen/srv 9 | properties: 10 | EXIT: 1 11 | requires: 12 | - name: BusinessPartnerValidation-db 13 | - name: BusinessPartnerValidation-xsuaa 14 | - name: BusinessPartnerValidation-dest 15 | - name: BusinessPartnerValidation-ems 16 | - name: BusinessPartnerValidation-cs 17 | - name: BusinessPartnerValidation-logs 18 | provides: 19 | - name: srv_api 20 | properties: 21 | srv-url: ${default-url} 22 | parameters: 23 | memory: 256MB 24 | - name: db 25 | type: hdb 26 | path: gen/db 27 | requires: 28 | - name: BusinessPartnerValidation-db 29 | parameters: 30 | app-name: BusinessPartnerValidation-db 31 | memory: 128MB 32 | - name: BusinessPartnerValidation-launchpad 33 | type: com.sap.application.content 34 | requires: 35 | - name: BusinessPartnerValidation-xsuaa 36 | parameters: 37 | service-key: 38 | name: BusinessPartnerValidation-xsuaa-key 39 | - name: BusinessPartnerValidation-html5-repo-host 40 | parameters: 41 | service-key: 42 | name: BusinessPartnerValidation-html5-repo-host-key 43 | - name: srv_api 44 | - name: BusinessPartnerValidation-dest 45 | parameters: 46 | content-target: true 47 | parameters: 48 | content: 49 | subaccount: 50 | destinations: 51 | - Authentication: OAuth2UserTokenExchange 52 | Name: BusinessPartnerValidation-srv 53 | TokenServiceInstanceName: BusinessPartnerValidation-xsuaa 54 | TokenServiceKeyName: BusinessPartnerValidation-xsuaa-key 55 | URL: ~{srv_api/srv-url} 56 | sap.cloud.service: com.sap.bp.BusinessPartners.one 57 | - Name: BusinessPartnerValidation-html5-repo-host 58 | ServiceInstanceName: BusinessPartnerValidation-html5-repo-host 59 | ServiceKeyName: BusinessPartnerValidation-html5-repo-host-key 60 | sap.cloud.service: com.sap.bp.BusinessPartners.one 61 | - Authentication: OAuth2UserTokenExchange 62 | Name: BusinessPartnerValidation-xsuaa 63 | ServiceInstanceName: BusinessPartnerValidation-xsuaa 64 | ServiceKeyName: BusinessPartnerValidation-xsuaa-key 65 | sap.cloud.service: com.sap.bp.BusinessPartners.one 66 | existing_destinations_policy: update 67 | build-parameters: 68 | no-source: true 69 | 70 | - name: BusinessPartnerValidation-app-content 71 | type: com.sap.application.content 72 | path: . 73 | requires: 74 | - name: BusinessPartnerValidation-html5-repo-host 75 | parameters: 76 | content-target: true 77 | build-parameters: 78 | build-result: resources 79 | requires: 80 | - artifacts: 81 | - comsapbpBusinessPartners.zip 82 | name: comsapbpBusinessPartners 83 | target-path: resources/ 84 | 85 | - name: comsapbpBusinessPartners 86 | type: html5 87 | path: app/BusinessPartners 88 | build-parameters: 89 | build-result: dist 90 | builder: custom 91 | commands: 92 | - npm install 93 | - npm run build 94 | supported-platforms: [] 95 | 96 | - name: mock-srv 97 | type: nodejs 98 | path: mock-srv 99 | parameters: 100 | buildpack: nodejs_buildpack 101 | memory: 256MB 102 | provides: 103 | - name: mock_api 104 | properties: 105 | url: ${default-url}/v2/api-business-partner 106 | build-parameters: 107 | builder: npm-ci 108 | requires: 109 | - name: BusinessPartnerValidation-ems 110 | 111 | resources: 112 | - name: BusinessPartnerValidation-db 113 | type: com.sap.xs.hdi-container 114 | parameters: 115 | service: hana 116 | service-plan: hdi-shared 117 | properties: 118 | hdi-service-name: ${service-name} 119 | - name: BusinessPartnerValidation-xsuaa 120 | type: org.cloudfoundry.managed-service 121 | parameters: 122 | path: ./xs-security.json 123 | service: xsuaa 124 | service-plan: application 125 | - name: BusinessPartnerValidation-dest 126 | type: org.cloudfoundry.managed-service 127 | requires: 128 | - name: mock_api 129 | parameters: 130 | config: 131 | init_data: 132 | subaccount: 133 | destinations: 134 | - Authentication: NoAuthentication 135 | Name: ui5 136 | ProxyType: Internet 137 | Type: HTTP 138 | URL: https://ui5.sap.com 139 | - Authentication: NoAuthentication 140 | Name: bupa 141 | ProxyType: Internet 142 | Type: HTTP 143 | URL: ~{mock_api/url} 144 | existing_destinations_policy: update 145 | version: 1.0.0 146 | service: destination 147 | service-plan: lite 148 | - name: BusinessPartnerValidation-ems 149 | type: org.cloudfoundry.managed-service 150 | parameters: 151 | path: ./em.json 152 | service: enterprise-messaging 153 | service-plan: default 154 | - name: BusinessPartnerValidation-cs 155 | type: org.cloudfoundry.managed-service 156 | parameters: 157 | service: connectivity 158 | service-plan: lite 159 | - name: BusinessPartnerValidation-logs 160 | type: org.cloudfoundry.managed-service 161 | parameters: 162 | service: application-logs 163 | service-plan: lite 164 | 165 | # HTML5 Repo Runtime 166 | #- name: BusinessPartnerValidation_html5_repo-runtime 167 | #parameters: 168 | # service-plan: app-runtime 169 | #service: html5-apps-repo 170 | #type: org.cloudfoundry.managed-service 171 | 172 | - name: BusinessPartnerValidation-html5-repo-host 173 | type: org.cloudfoundry.managed-service 174 | parameters: 175 | service: html5-apps-repo 176 | service-plan: app-host 177 | parameters: 178 | deploy_mode: html5-repo 179 | enable-parallel-deployments: true 180 | build-parameters: 181 | before-all: 182 | - builder: custom 183 | commands: 184 | - npm install 185 | - npx -p @sap/cds-dk cds build --production 186 | -------------------------------------------------------------------------------- /app/BusinessPartners/webapp/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "_version": "1.15.0", 3 | "sap.app": { 4 | "id": "com.sap.bp.BusinessPartners", 5 | "type": "application", 6 | "i18n": "i18n/i18n.properties", 7 | "applicationVersion": { 8 | "version": "1.0.1" 9 | }, 10 | "title": "{{appTitle}}", 11 | "description": "{{appDescription}}", 12 | "ach": "CA-UI5-FE", 13 | "dataSources": { 14 | "mainService": { 15 | "uri": "/odata/v4/sales/", 16 | "type": "OData", 17 | "settings": { 18 | "annotations": [ 19 | "annotation" 20 | ], 21 | "odataVersion": "4.0", 22 | "localUri": "localService/metadata.xml" 23 | } 24 | }, 25 | "annotation": { 26 | "type": "ODataAnnotation", 27 | "uri": "annotations/annotation.xml", 28 | "settings": { 29 | "localUri": "annotations/annotation.xml" 30 | } 31 | } 32 | }, 33 | "offline": false, 34 | "resources": "resources.json", 35 | "sourceTemplate": { 36 | "id": "ui5template.fiorielements.v4.lrop", 37 | "version": "1.0.0" 38 | }, 39 | "crossNavigation": { 40 | "inbounds": { 41 | "intent1": { 42 | "signature": { 43 | "parameters": {}, 44 | "additionalParameters": "allowed" 45 | }, 46 | "semanticObject": "partners", 47 | "action": "display", 48 | "title": "Business Partners", 49 | "subTitle": "Manage Business Partners", 50 | "icon": "sap-icon://project-definition-triangle" 51 | } 52 | } 53 | } 54 | }, 55 | "sap.cloud": { 56 | "public": true, 57 | "service": "com.sap.bp.BusinessPartners.one" 58 | }, 59 | "sap.ui": { 60 | "technology": "UI5", 61 | "icons": { 62 | "icon": "", 63 | "favIcon": "", 64 | "phone": "", 65 | "phone@2": "", 66 | "tablet": "", 67 | "tablet@2": "" 68 | }, 69 | "deviceTypes": { 70 | "desktop": true, 71 | "tablet": true, 72 | "phone": true 73 | } 74 | }, 75 | "sap.ui5": { 76 | "resources": { 77 | "js": [], 78 | "css": [] 79 | }, 80 | "dependencies": { 81 | "minUI5Version": "1.76.0", 82 | "libs": { 83 | "sap.fe.templates": {}, 84 | "sap.ui.fl": {} 85 | } 86 | }, 87 | "models": { 88 | "i18n": { 89 | "type": "sap.ui.model.resource.ResourceModel", 90 | "uri": "i18n/i18n.properties" 91 | }, 92 | "": { 93 | "dataSource": "mainService", 94 | "settings": { 95 | "synchronizationMode": "None", 96 | "operationMode": "Server", 97 | "autoExpandSelect": true, 98 | "earlyRequests": true 99 | } 100 | } 101 | }, 102 | "routing": { 103 | "routes": [{ 104 | "pattern": ":?query:", 105 | "name": "NotificationList", 106 | "target": [ 107 | "NotificationList" 108 | ] 109 | }, 110 | { 111 | "pattern": "Notifications({key})", 112 | "name": "NotificationObjectPage", 113 | "target": [ 114 | "NotificationObjectPage" 115 | ] 116 | }, 117 | { 118 | "pattern": "Notifications({key})/addresses({key2}):?query:", 119 | "name": "AddressObjectPage_address", 120 | "target": "AddressObjectPage_address" 121 | } 122 | ], 123 | "targets": { 124 | "NotificationList": { 125 | "type": "Component", 126 | "id": "NotificationList", 127 | "name": "sap.fe.templates.ListReport", 128 | "options": { 129 | "settings": { 130 | "entitySet": "Notifications", 131 | "variantManagement": "Page", 132 | "navigation": { 133 | "Notifications": { 134 | "detail": { 135 | "route": "NotificationObjectPage" 136 | } 137 | } 138 | } 139 | } 140 | } 141 | }, 142 | "NotificationObjectPage": { 143 | "type": "Component", 144 | "id": "NotificationObjectPage", 145 | "name": "sap.fe.templates.ObjectPage", 146 | "options": { 147 | "settings": { 148 | "entitySet": "Notifications", 149 | "navigation": {} 150 | } 151 | } 152 | }, 153 | "AddressObjectPage_address": { 154 | "type": "Component", 155 | "id": "AddressObjectPage_address", 156 | "name": "sap.fe.templates.ObjectPage", 157 | "options": { 158 | "settings": { 159 | "entitySet": "Addresses", 160 | "navigation": {} 161 | } 162 | } 163 | } 164 | }, 165 | "config": {} 166 | }, 167 | "contentDensities": { 168 | "compact": true, 169 | "cozy": true 170 | } 171 | }, 172 | "sap.platform.abap": { 173 | "_version": "1.1.0", 174 | "uri": "" 175 | }, 176 | "sap.platform.hcp": { 177 | "_version": "1.1.0", 178 | "uri": "" 179 | }, 180 | "sap.fiori": { 181 | "_version": "1.1.0", 182 | "registrationIds": [], 183 | "archeType": "transactional" 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /srv/service.js: -------------------------------------------------------------------------------- 1 | const cds = require('@sap/cds'); 2 | 3 | 4 | // module.exports = cds.service.impl(async (srv) => { 5 | class SalesService extends cds.ApplicationService { 6 | 7 | async init(){ 8 | 9 | const srv = this; 10 | const {BusinessPartnerAddress, Notifications, Addresses, BusinessPartner} = srv.entities; 11 | const bupaSrv = await cds.connect.to("API_BUSINESS_PARTNER"); 12 | const messaging = await cds.connect.to('messaging') 13 | const {postcodeValidator} = require('postcode-validator'); 14 | srv.LOG = cds.log("sales-service"); 15 | 16 | srv.on("READ", BusinessPartnerAddress, req => bupaSrv.run(req.query)) 17 | srv.on("READ", BusinessPartner, req => bupaSrv.run(req.query)) 18 | 19 | messaging.on(["S4H/BO/BusinessPartner/Created", "ce/sap/s4/beh/businesspartner/v1/BusinessPartner/Created/v1"], async msg => { 20 | 21 | srv.LOG.info("<< Create event caught", msg.data); 22 | let BUSINESSPARTNER = this.readMsg(msg); 23 | 24 | // ID has prefix 000 needs to be removed to read address 25 | srv.LOG.info(BUSINESSPARTNER); 26 | const bpEntity = await bupaSrv.run(SELECT.one(BusinessPartner).where({businessPartnerId: BUSINESSPARTNER})); 27 | if(!bpEntity){ 28 | srv.LOG.info(`BP doesn't exist in the given destination`); 29 | return; 30 | } 31 | const result = await cds.run(INSERT.into(Notifications).entries({businessPartnerId:BUSINESSPARTNER, verificationStatus_code:'N', businessPartnerName:bpEntity.businessPartnerName})); 32 | const address = await bupaSrv.run(SELECT.one(BusinessPartnerAddress).where({businessPartnerId: BUSINESSPARTNER})); 33 | // for the address to notification association - extra field 34 | 35 | console.log("Address entity here == ", address); 36 | if(address && address.addressId){ 37 | const notificationObj = await cds.run(SELECT.one(Notifications).columns("ID").where({businessPartnerId: BUSINESSPARTNER})); 38 | address.notifications_ID=notificationObj.ID; 39 | const res = await cds.run(INSERT.into(Addresses).entries(address)); 40 | srv.LOG.info("Address inserted"); 41 | } 42 | }); 43 | 44 | messaging.on(["S4H/BO/BusinessPartner/Changed", "ce/sap/s4/beh/businesspartner/v1/BusinessPartner/Changed/v1"], async msg => { 45 | srv.LOG.info(`<< Change event caught: ${JSON.stringify(msg.data)}`); 46 | let BUSINESSPARTNER = this.readMsg(msg); 47 | const bpIsAlive = await cds.run(SELECT.one(Notifications, (n) => n.verificationStatus_code).where({businessPartnerId: BUSINESSPARTNER})); 48 | if(bpIsAlive && bpIsAlive.verificationStatus_code == "V"){ 49 | const bpMarkVerified= await cds.run(UPDATE(Notifications).where({businessPartnerId: BUSINESSPARTNER}).set({verificationStatus_code:"C"})); 50 | srv.LOG.info("<< BP marked verified >> ", bpMarkVerified); 51 | } 52 | 53 | }); 54 | 55 | srv.after("UPDATE", "Notifications", (data) => { 56 | if(data.verificationStatus_code === "V" || data.verificationStatus_code === "INV") 57 | srv.emitEvent(bupaSrv, data, this.LOG); 58 | 59 | }); 60 | 61 | srv.before("SAVE", "Notifications", req => { 62 | if(req.data.verificationStatus_code == "C"){ 63 | req.error({code: '400', message: "Cannot mark as COMPLETED. Please change to VERIFIED", numericSeverity:2, target: 'verificationStatus_code'}); 64 | } 65 | }); 66 | 67 | srv.before("PATCH", "Addresses", req => { 68 | // To set whether address is Edited 69 | req.data.isModified = true; 70 | }); 71 | 72 | srv.after("PATCH", "Addresses", async (data, req) => { 73 | srv.LOG.info("Received address in PATCH", data); 74 | let isValidPinCode = true; 75 | if(data && data.postalCode){ 76 | isValidPinCode = await this.validatePostcode(data, this.LOG); 77 | } 78 | 79 | if(!isValidPinCode) { 80 | return req.error({ code: '400', message: "invalid postal code", numericSeverity: 2, target: 'postalCode' }); 81 | } 82 | }); 83 | 84 | await super.init() 85 | } 86 | 87 | readMsg(msg) { 88 | if (msg.headers && msg.headers.specversion == "1.0") { 89 | //> Fix for 2020 on-premise 90 | return (+(msg.data.BusinessPartner)).toString(); 91 | } 92 | else { 93 | return (+(msg.data.KEY[0].BUSINESSPARTNER)).toString(); 94 | } 95 | } 96 | 97 | async validatePostcode(data, LOG){ 98 | const {Addresses} = this.entities; 99 | const {postcodeValidator} = require('postcode-validator'); 100 | let isValidPinCode; 101 | if(data.postalCode){ 102 | const address = await cds.run(SELECT.one(Addresses).where({ ID: data.ID })); 103 | isValidPinCode = postcodeValidator(data.postalCode, address.country); 104 | LOG.info("isValidPinCode ",isValidPinCode); 105 | return isValidPinCode; 106 | } 107 | } 108 | 109 | async emitEvent(bupaSrv, result, LOG){ 110 | const {BusinessPartner, BusinessPartnerAddress, Notifications} = this.entities; 111 | const resultJoin = await cds.run( 112 | SELECT.one(Notifications, notification => { 113 | notification('*'), 114 | notification.addresses((addresses) => { 115 | addresses('*') 116 | }); 117 | }) 118 | .where({"ID": result.ID}) 119 | ) 120 | 121 | const addressResult = resultJoin.addresses[0]; 122 | const statusValues={"N":"NEW", "P":"PROCESS", "INV":"INVALID", "V":"VERIFIED"} 123 | 124 | if(addressResult && addressResult.isModified){ 125 | let payload = { 126 | streetName: addressResult.streetName, 127 | postalCode: addressResult.postalCode 128 | } 129 | 130 | LOG.info("<<< 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /app/BusinessPartners/wdio.conf.js: -------------------------------------------------------------------------------- 1 | require("dotenv").config({path : "../../.env"}) 2 | const endPoint = require("../../tests/util/config").bp_app 3 | exports.config = { 4 | 5 | // wdi5 Configuration 6 | wdi5: { 7 | logLevel: "verbose", 8 | waitForUI5Timeout: 80000 9 | }, 10 | 11 | // Specify Test Files 12 | specs: ["../../tests/ui/specs/*.js"], 13 | 14 | // Capabilities 15 | maxInstances: 10, 16 | 17 | capabilities: [ 18 | { 19 | maxInstances: 5, 20 | browserName: "chrome", 21 | acceptInsecureCerts: true, 22 | 'goog:chromeOptions': { 23 | args: [ '--headless', '--disable-dev-shm-usage', '--disable-gpu', '--no-sandbox', '--window-size=1920,1080'], 24 | }, 25 | "wdi5:authentication": { 26 | provider: "BTP" 27 | } 28 | }, 29 | ], 30 | 31 | automationProtocol: "devtools", 32 | 33 | // Test Configurations 34 | logLevel: "error", 35 | 36 | bail: 0, 37 | 38 | baseUrl: "", 39 | 40 | waitforTimeout: 100000, 41 | 42 | connectionRetryTimeout: 120000, 43 | 44 | connectionRetryCount: 3, 45 | 46 | // Test runner services 47 | services: ["ui5"], 48 | 49 | // Framework you want to run your specs with. 50 | framework: "mocha", 51 | 52 | reporters: ["spec"], 53 | 54 | 55 | mochaOpts: { 56 | ui: "bdd", 57 | timeout: 80000, 58 | }, 59 | 60 | // ===== 61 | // Hooks 62 | // ===== 63 | // WebdriverIO provides several hooks you can use to interfere with the test process in order to enhance 64 | // it and to build services around it. You can either apply a single function or an array of 65 | // methods to it. If one of them returns with a promise, WebdriverIO will wait until that promise got 66 | // resolved to continue. 67 | /** 68 | * Gets executed once before all workers get launched. 69 | * @param {Object} config wdio configuration object 70 | * @param {Array.} capabilities list of capabilities details 71 | */ 72 | // onPrepare: function (config, capabilities) { 73 | // }, 74 | /** 75 | * Gets executed before a worker process is spawned and can be used to initialise specific service 76 | * for that worker as well as modify runtime environments in an async fashion. 77 | * @param {String} cid capability id (e.g 0-0) 78 | * @param {[type]} caps object containing capabilities for session that will be spawn in the worker 79 | * @param {[type]} specs specs to be run in the worker process 80 | * @param {[type]} args object that will be merged with the main configuration once worker is initialized 81 | * @param {[type]} execArgv list of string arguments passed to the worker process 82 | */ 83 | // onWorkerStart: function (cid, caps, specs, args, execArgv) { 84 | // }, 85 | /** 86 | * Gets executed just after a worker process has exited. 87 | * @param {String} cid capability id (e.g 0-0) 88 | * @param {Number} exitCode 0 - success, 1 - fail 89 | * @param {[type]} specs specs to be run in the worker process 90 | * @param {Number} retries number of retries used 91 | */ 92 | // onWorkerEnd: function (cid, exitCode, specs, retries) { 93 | // }, 94 | /** 95 | * Gets executed just before initialising the webdriver session and test framework. It allows you 96 | * to manipulate configurations depending on the capability or spec. 97 | * @param {Object} config wdio configuration object 98 | * @param {Array.} capabilities list of capabilities details 99 | * @param {Array.} specs List of spec file paths that are to be run 100 | * @param {String} cid worker id (e.g. 0-0) 101 | */ 102 | // beforeSession: async function () { 103 | // }, 104 | /** 105 | * Gets executed before test execution begins. At this point you can access to all global 106 | * variables like `browser`. It is the perfect place to define custom commands. 107 | * @param {Array.} capabilities list of capabilities details 108 | * @param {Array.} specs List of spec file paths that are to be run 109 | * @param {Object} browser instance of created browser/device session 110 | */ 111 | 112 | //Login into the app and get to the main page 113 | before: async function (capabilities, specs, browser) { 114 | 115 | await browser.waitUntil(async() => { 116 | return((await browser.getUrl()) === endPoint.auth) 117 | }) 118 | await (await $("=Default Identity Provider")).click(); 119 | 120 | console.log("Logging in...") 121 | 122 | await browser.waitUntil(async() => { 123 | return((await browser.getUrl()) === browser.options.baseUrl) 124 | }) 125 | 126 | console.log("Log in successful") 127 | 128 | endPoint.main = browser.options.baseUrl.split("#")[0]+"#fe-lrop-v4"; 129 | 130 | const tile = await $("span=Business Partner Validation"); 131 | if(await tile.waitForDisplayed({ timeout: 20000 }) && await tile.waitForClickable({ timeout: 20000 })){ 132 | 133 | console.log("Navigating from Home Page") 134 | await tile.click(); 135 | 136 | await browser.waitUntil(async() => { 137 | return((await browser.getUrl()) === endPoint.main) 138 | }) 139 | console.log("Navigated to the main page ") 140 | } 141 | 142 | if (await browser.getUrl() !== endPoint.main){ 143 | console.log("Required page not loaded"); 144 | browser.closeWindow(); 145 | process.exit(); 146 | } 147 | } 148 | , 149 | /** 150 | * Runs before a WebdriverIO command gets executed. 151 | * @param {String} commandName hook command name 152 | * @param {Array} args arguments that command would receive 153 | */ 154 | // beforeCommand: function (commandName, args) { 155 | // }, 156 | /** 157 | * Hook that gets executed before the suite starts 158 | * @param {Object} suite suite details 159 | */ 160 | // beforeSuite: function (suite) { 161 | // }, 162 | /** 163 | * Function to be executed before a test (in Mocha/Jasmine) starts. 164 | */ 165 | // beforeTest: function (test, context) { 166 | // }, 167 | /** 168 | * Hook that gets executed _before_ a hook within the suite starts (e.g. runs before calling 169 | * beforeEach in Mocha) 170 | */ 171 | // beforeHook: function (test, context) { 172 | // }, 173 | /** 174 | * Hook that gets executed _after_ a hook within the suite starts (e.g. runs after calling 175 | * afterEach in Mocha) 176 | */ 177 | // afterHook: function (test, context, { error, result, duration, passed, retries }) { 178 | // }, 179 | /** 180 | * Function to be executed after a test (in Mocha/Jasmine only) 181 | * @param {Object} test test object 182 | * @param {Object} context scope object the test was executed with 183 | * @param {Error} result.error error object in case the test fails, otherwise `undefined` 184 | * @param {Any} result.result return object of test function 185 | * @param {Number} result.duration duration of test 186 | * @param {Boolean} result.passed true if test has passed, otherwise false 187 | * @param {Object} result.retries informations to spec related retries, e.g. `{ attempts: 0, limit: 0 }` 188 | */ 189 | // afterTest: function(test, context, { error, result, duration, passed, retries }) { 190 | // }, 191 | 192 | /** 193 | * Hook that gets executed after the suite has ended 194 | * @param {Object} suite suite details 195 | */ 196 | // afterSuite: function (suite) { 197 | // }, 198 | /** 199 | * Runs after a WebdriverIO command gets executed 200 | * @param {String} commandName hook command name 201 | * @param {Array} args arguments that command would receive 202 | * @param {Number} result 0 - command success, 1 - command error 203 | * @param {Object} error error object if any 204 | */ 205 | // afterCommand: function (commandName, args, result, error) { 206 | // }, 207 | /** 208 | * Gets executed after all tests are done. You still have access to all global variables from 209 | * the test. 210 | * @param {Number} result 0 - test pass, 1 - test fail 211 | * @param {Array.} capabilities list of capabilities details 212 | * @param {Array.} specs List of spec file paths that ran 213 | */ 214 | // after: function (result, capabilities, specs) { 215 | // }, 216 | /** 217 | * Gets executed right after terminating the webdriver session. 218 | * @param {Object} config wdio configuration object 219 | * @param {Array.} capabilities list of capabilities details 220 | * @param {Array.} specs List of spec file paths that ran 221 | */ 222 | // afterSession: function (config, capabilities, specs) { 223 | // }, 224 | /** 225 | * Gets executed after all workers got shut down and the process is about to exit. An error 226 | * thrown in the onComplete hook will result in the test run failing. 227 | * @param {Object} exitCode 0 - success, 1 - fail 228 | * @param {Object} config wdio configuration object 229 | * @param {Array.} capabilities list of capabilities details 230 | * @param {} results object containing test results 231 | */ 232 | // onComplete: function(exitCode, config, capabilities, results) { 233 | // }, 234 | /** 235 | * Gets executed when a refresh happens. 236 | * @param {String} oldSessionId session ID of the old session 237 | * @param {String} newSessionId session ID of the new session 238 | */ 239 | // onReload: function(oldSessionId, newSessionId) { 240 | // } 241 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Important Notice 2 | 3 | This public repository is read-only and no longer maintained. 4 | 5 | ![](https://img.shields.io/badge/STATUS-NOT%20CURRENTLY%20MAINTAINED-red.svg?longCache=true&style=flat) 6 | 7 | --- 8 | # SAP S/4HANA Extended Business Process Scenario 9 | [![REUSE status](https://api.reuse.software/badge/github.com/SAP-samples/cloud-extension-s4hana-business-process)](https://api.reuse.software/info/github.com/SAP-samples/cloud-extension-s4hana-business-process) 10 | ## Description 11 | The main intent of this scenario is to complement an existing business process in an SAP solution – currently SAP S/4HANA with additional business process steps. This involves adding major logic and/or additional data and goes beyond simple UI changes. 12 | 13 | This application showcases: 14 | 15 | - Building applications on SAP Business Technology Platform (BTP) using [SAP Cloud Application Programming Model(CAP)](https://cap.cloud.sap/docs/) 16 | - Consuming events from SAP S/4HANA on premise using [SAP Event Mesh](https://help.sap.com/viewer/bf82e6b26456494cbdd197057c09979f/Cloud/en-US/df532e8735eb4322b00bfc7e42f84e8d.html) 17 | - Consuming REST APIs from SAP S/4HANA on premise using SAP Business Technology Platform Connectivity Service 18 | 19 | ## Business Scenario 20 | 21 | A business scenario is used to showcase how to build a S/4 HANA on premise extension Application on SAP BTP. 22 | 23 | John who is an employee of Business Partner Validation Firm iCredible, which is a third-party vendor of ACME Corporation would like to get notifications whenever new Business Partners are added in the S/4HANA backend system of ACME Corporation. John would then be able to review the Business Partner details in his extension app. He would proceed to visit the Business Partner’s registered office and do some background verification. John would then proceed to update/validate the verification details into the extension app. Once the details are verified, the Business Partner gets activated in the S/4HANA system of ACME Corporation. 24 | 25 | - Custom extension application that works independently from S/4HANA. 26 | 27 | - Changes in S/4 communicated via events in real time to extension application. 28 | 29 | - Compute intensive processing available on demand (serverless environment). 30 | 31 | - Vendor personnel needs access to only custom app 32 | 33 | ## Architecture 34 | 35 | ### Solution Diagram 36 | 37 | ![solution diagram](./documentation/images/solution-diagram-latest.png) 38 | 39 | The Business Partner Validation application is developed using the SAP Cloud Application programming Model (CAP) and runs on the SAP BTP, Cloud Foundry runtime. It consumes platform services like SAP Event Mesh, SAP HANA and Connectivity. The events occuring in S/4 HANA on premise are inserted into the Event Mesh queue. The application running in Cloud Foundry is notified on events, consumes them from the queue and inserts the event data into the HANA database. The Business Partner Validation Application uses S/4 HANA REST API's to read additional Business Partner Data from the S/4 HANA system. 40 | 41 | ## Requirements 42 | * SAP S/4HANA on premise system. 43 | * SAP Business Technology Platform account 44 | 45 | ### For local development you would require the following: 46 | * [Node js](https://nodejs.org/en/download/) 47 | >Make sure you run the latest long-term support (LTS) version of Node.js with an even number like 16. Refrain from using odd versions, for which some modules with native parts will have no support and thus might even fail to install. In case of problems, see the [Troubleshooting guide](https://cap.cloud.sap/docs/advanced/troubleshooting#node-version) for CAP for more details. 48 | * [Cloud Foundry Command Line Interface (CLI)](https://github.com/cloudfoundry/cli#downloads) 49 | * [Visual Studio Code](https://cap.cloud.sap/docs/get-started/in-vscode) 50 | * [cds-dk](https://cap.cloud.sap/docs/get-started/) 51 | * [SQLite ](https://sqlite.org/download.html) 52 | * To build the multi target application, we need the [Cloud MTA Build tool](https://sap.github.io/cloud-mta-build-tool/), download the tool from [here](https://sap.github.io/cloud-mta-build-tool/download/) 53 | * For Windows system, install 'MAKE' from https://sap.github.io/cloud-mta-build-tool/makefile/ 54 | * [multiapps plugin](https://github.com/cloudfoundry-incubator/multiapps-cli-plugin) - `cf install-plugin multiapps` 55 | * mbt - `npm install -g mbt` 56 | 57 | ### Entitlements 58 | 59 | The application requires below set of SAP Business Technology Platform Entitlements/Quota 60 | 61 | | Service | Plan | Number of Instances | 62 | |-----------------------------------|------------|:-------------------:| 63 | | Event Mesh | default | 1 | 64 | | SAP HANA Schemas & HDI Containers | hdi-shared | 1 | 65 | | SAP HANA Cloud | hana | 1 | 66 | | Cloud Foundry runtime | | 1 | 67 | 68 | 69 | ## Configuration 70 | 71 | 72 | ### Step 1: Setup SAP BTP subaccount 73 | 74 | You can use [SAP BTP - Boosters](https://help.sap.com/viewer/DRAFT/65de2977205c403bbc107264b8eccf4b/Validation/en-US/fb1b56148f834749a2bf51127421610b.html) to setup the subaccount. Boosters Will create the subaccount with the required entitlements, subscriptions and assign the required roles to your user to run this application. Steps to run the booster are provided in [link](https://github.com/SAP-samples/cloud-extension-s4hana-business-process/blob/mission/mission/Prepare-Cloud-Platform/Booster.md). You can create subaccount manually also following [link](https://github.com/SAP-samples/cloud-extension-s4hana-business-process/blob/mission/mission/Prepare-Cloud-Platform/README.md) 75 | 76 | ### Step 2: [S/4HANA Enable OData Service for business partner](https://github.com/SAP-samples/cloud-extension-s4hana-business-process/blob/mission/mission/configure-oData-Service/README.md) 77 | 78 | ### Step 3: [Setup connectivity between S/4HANA system, SAP BTP](https://github.com/SAP-samples/cloud-extension-s4hana-business-process/blob/mission/mission/cloud-connector/README.md) 79 | 80 | ### Step 4: Build and deploy the CAP application 81 | 82 | #### Steps to deploy locally 83 | 84 | - Open terminal in VSCode 85 | - Run `npm install sqlite3 --save-dev` 86 | - Run `cds watch` 87 | 88 | #### Steps to deploy the application on Cloud Foundry 89 | 90 | 1. Build the application 91 | `mbt build -p=cf ` 92 | 2. Login to Cloud Foundry by typing the below commands on command prompt 93 | ``` 94 | cf api 95 | cf login -u -p 96 | ``` 97 | `api` - [URL of the Cloud Foundry landscape](https://help.sap.com/viewer/65de2977205c403bbc107264b8eccf4b/Cloud/en-US/350356d1dc314d3199dca15bd2ab9b0e.html) that you are trying to connect to. 98 | 99 | Select the org and space when prompted to. 100 | 101 | 3. Deploy the application 102 | 103 | Navigate to mta_archives folder and run the below command from CLI 104 | 105 | `cf deploy BusinessPartnerValidation_1.0.0.mtar` 106 | ### Step 5: [Configure event based communication between S/4HANA and Event Mesh](https://help.sap.com/viewer/810dfd34f2cc4f39aa8d946b5204fd9c/1809.000/en-US/fbb2a5980cb54110a96d381e136e0dd8.html) 107 | 108 | 109 | ## Demo script 110 | 111 | 1. Go to Launchpad and access the 'Business Partner Validation' application 112 | 113 | 114 | 2. Click on Business Partner Validation tile 115 | 116 | ![fiori tile](./documentation/images/fioriLaunchpad.JPG) 117 | 118 | 3. The list of BusinessPartners along with their verification status gets displayed. 119 | 120 | ![BP list](./documentation/images/BPListView.JPG) 121 | 122 | 4. Login to the S/4HANA on-premise system 123 | 124 | ![S/4HANA login](./documentation/images/GuiLogin.JPG) 125 | 126 | 5. Enter transaction code 'bp' 127 | 128 | ![bp transaction](./documentation/images/BPtransaction.JPG) 129 | 130 | 6. Click on Person 131 | 132 | ![person](./documentation/images/person.png) 133 | 134 | 7. Provide first name, last name for the business partner 135 | ![name](./documentation/images/name.png) 136 | 137 | 8. Provide the address 138 | ![address](./documentation/images/bpaddress.png) 139 | 140 | 9. Move to the status tab and check mark the 'Central Block' lock. Save the BP. This will create a new Business Partner 141 | 142 | ![lock](./documentation/images/lock.png) 143 | 144 | 10. Now go back to the BusinessPartnerValidation application to see if the new BusinessPartners has come on the UI 145 | 146 | ![new bp](./documentation/images/bpNew.png) 147 | 148 | 11. Go to the details page for the new BusinessPartner. Click on edit. 149 | 150 | ![edit bp](./documentation/images/editBP.png) 151 | 152 | 12. Change the Verification Status to VERIFIED. You can also edit the street name, postal code also if needed. Save the data. 153 | 154 | ![edit values](./documentation/images/editValue.png) 155 | 156 | 13. Open S/4HANA system, bp transaction. Search for the newly created bp 157 | 158 | ![search bp](./documentation/images/searchBP.png) 159 | 160 | 14. Double click on the BP 161 | 162 | ![click bp](./documentation/images/clickBP.png) 163 | 164 | 15. You can see that the central Block lock has been removed 165 | 166 | ![release lock](./documentation/images/releasedLock.png) 167 | 168 | 169 | 16. You can also notice that in the BusinessPartner Validation UI, the status is now set as COMPLETED. 170 | 171 | ## Known Issues 172 | 173 | No known issues. 174 | 175 | ## How to Obtain Support 176 | 177 | In case you find a bug, or you need additional support, please [open an issue](https://github.com/SAP-samples/cloud-extension-s4hana-business-process/issues/new) here in GitHub. 178 | 179 | ## License 180 | Copyright (c) 2020 SAP SE or an SAP affiliate company. All rights reserved. This project is licensed under the Apache Software License, version 2.0 except as noted otherwise in the [LICENSE](LICENSES/Apache-2.0.txt) file. 181 | 182 | 183 | -------------------------------------------------------------------------------- /tests/integration/BPValidation.test.js: -------------------------------------------------------------------------------- 1 | const cds = require("@sap/cds"); 2 | const { default: axios } = require('axios'); 3 | const { expect } = require("chai"); 4 | const { GET, POST, PATCH, DELETE } = cds 5 | .test("serve", "--in-memory", "--with-mocks") 6 | .in(__dirname + "/../../"); //.verbose(true) 7 | 8 | axios.defaults.auth = { username: "admin", password: "admin" }; 9 | 10 | describe("Sanity Test", () => { 11 | describe("Sales Service APIs - GET should return 200", () => { 12 | // API access 13 | it("Should return list of notifications", async () => { 14 | const response = await GET("/odata/v4/sales/Notifications"); 15 | expect(response.status).to.eql(200); 16 | }); 17 | 18 | it("Should return list of Business Partners", async () => { 19 | const response = await GET("/odata/v4/sales/BusinessPartner"); 20 | expect(response.status).to.eql(200); 21 | }); 22 | 23 | it("Should return list of Business Partners Address", async () => { 24 | const response = await GET("/odata/v4/sales/BusinessPartnerAddress"); 25 | expect(response.status).to.eql(200); 26 | }); 27 | 28 | // Programatic access 29 | it("Should return one notification", async () => { 30 | const SalesService = await cds.connect.to( 31 | "service.businessPartnerValidation.SalesService" 32 | ); 33 | const { Notifications } = SalesService.entities; 34 | const result = await SELECT.one(Notifications); 35 | expect(result).to.deep.contains({ 36 | businessPartnerId: "17100001", 37 | businessPartnerName: "TestData1", 38 | }); 39 | }); 40 | }); 41 | 42 | describe("GET /api-business-partner/A_BusinessPartner", () => { 43 | it("+ should return a list of Mock BusinessPartners", async () => { 44 | const response = await GET("/odata/v4/api-business-partner/A_BusinessPartner"); 45 | expect(response.status).to.eql(200); 46 | }); 47 | }); 48 | }); 49 | 50 | describe("Business Partner Validation", () => { 51 | it("Creates a new Business Partner", async () => { 52 | const payload = { 53 | BusinessPartner: "17100015", 54 | BusinessPartnerIsBlocked: true, 55 | BusinessPartnerFullName: "John Doee", 56 | }; 57 | const response = await POST( 58 | "/odata/v4/api-business-partner/A_BusinessPartner", 59 | payload 60 | ); 61 | expect(response.status).to.eql(201); 62 | }); 63 | 64 | it("Verify the newly created Business Partner", async () => { 65 | const response = await GET(`/odata/v4/sales/Notifications?$filter=businessPartnerId eq '17100015'`); 66 | expect(response.status).to.eql(200); 67 | expect(response.data.value).to.exist; 68 | expect(response.data.value[0]).to.contains({ 69 | businessPartnerName: "John Doee", 70 | }); 71 | }); 72 | }); 73 | 74 | describe("Draft Choreography APIs", () => { 75 | it("Push the Notification to draft", async () => { 76 | const response = await POST( 77 | `/odata/v4/sales/Notifications(ID=2c728381-72ce-4fdd-8293-8add71579666,IsActiveEntity=true)/service.businessPartnerValidation.SalesService.draftEdit?$select=HasActiveEntity,HasDraftEntity,ID,IsActiveEntity,businessPartnerId,businessPartnerName,verificationStatus_code&$expand=DraftAdministrativeData($select=DraftUUID,InProcessByUser),verificationStatus($select=code,updateCode)`, 78 | { PreserveChanges: true } 79 | ); 80 | expect(response.status).to.eql(201); 81 | }); 82 | 83 | it("Update the verificationStatus_code in draft state", async () => { 84 | const response = await PATCH( 85 | `/odata/v4/sales/Notifications(ID=2c728381-72ce-4fdd-8293-8add71579666,IsActiveEntity=false)`, 86 | { verificationStatus_code: "V" } 87 | ); 88 | expect(response.status).to.eql(200); 89 | }); 90 | 91 | it("Update the Side effects qualifier", async () => { 92 | const response = await POST( 93 | `/odata/v4/sales/Notifications(ID=2c728381-72ce-4fdd-8293-8add71579666,IsActiveEntity=false)/service.businessPartnerValidation.SalesService.draftPrepare`, 94 | { SideEffectsQualifier: "" } 95 | ); 96 | expect(response.status).to.eql(200); 97 | }); 98 | 99 | it("Activate the draft notification", async () => { 100 | const response = await POST( 101 | `/odata/v4/sales/Notifications(ID=2c728381-72ce-4fdd-8293-8add71579666,IsActiveEntity=false)/service.businessPartnerValidation.SalesService.draftActivate?$select=HasActiveEntity,HasDraftEntity,ID,IsActiveEntity,businessPartnerId,businessPartnerName,verificationStatus_code&$expand=DraftAdministrativeData($select=DraftIsCreatedByMe,DraftUUID,InProcessByUser),verificationStatus($select=code,updateCode)`, 102 | {} 103 | ); 104 | expect(response.status).to.eql(200); 105 | }); 106 | 107 | it("Test the verfication status", async () => { 108 | const response = await GET(`/odata/v4/sales/Notifications(ID=2c728381-72ce-4fdd-8293-8add71579666,IsActiveEntity=true)`); 109 | expect(response.status).to.eql(200); 110 | expect(response.data).to.deep.contains({ verificationStatus_code: "C" }); 111 | }); 112 | }); 113 | 114 | describe("Push new Notification directly to Completed state and Verify", () => { 115 | it("Push new notification", async () => { 116 | const response = await POST( 117 | `/odata/v4/sales/Notifications(ID=ff0bc005-710c-4097-a687-64ef380498f4,IsActiveEntity=true)/service.businessPartnerValidation.SalesService.draftEdit?$select=HasActiveEntity,HasDraftEntity,ID,IsActiveEntity,businessPartnerId,businessPartnerName,verificationStatus_code&$expand=DraftAdministrativeData($select=DraftUUID,InProcessByUser),verificationStatus($select=code,updateCode)`, 118 | { PreserveChanges: true } 119 | ); 120 | expect(response.status).to.eql(201); 121 | }); 122 | 123 | it("Update verificationStatus_code in draft state to Completed", async () => { 124 | const response = await PATCH( 125 | `/odata/v4/sales/Notifications(ID=ff0bc005-710c-4097-a687-64ef380498f4,IsActiveEntity=false)`, 126 | { verificationStatus_code: "C" } 127 | ); 128 | expect(response.status).to.eql(200); 129 | expect(response.data.verificationStatus_code).to.eql("C"); 130 | }); 131 | 132 | it("Should return 400 for activating the draft state whose verification status is marked as Completed", async () => { 133 | try { 134 | const response = await POST( 135 | "/odata/v4/sales/Notifications(ID=ff0bc005-710c-4097-a687-64ef380498f4,IsActiveEntity=false)/service.businessPartnerValidation.SalesService.draftActivate", 136 | {} 137 | ); 138 | 139 | } catch (err) { 140 | const errorData = 141 | err && err.response && err.response.data && err.response.data.error; 142 | expect(errorData && errorData.code).to.eql("400"); 143 | expect(errorData && errorData.message).to.eql( 144 | "Cannot mark as COMPLETED. Please change to VERIFIED" 145 | ); 146 | expect(errorData && errorData.target).to.eql("verificationStatus_code"); 147 | } 148 | }); 149 | }); 150 | 151 | describe("Push new Notification to Invalid state and Verify", () => { 152 | it("Push new notification", async () => { 153 | const response = await POST( 154 | `/odata/v4/sales/Notifications(ID=16f00c9c-323f-4ce4-876f-efaefe1c6f69,IsActiveEntity=true)/service.businessPartnerValidation.SalesService.draftEdit?$select=HasActiveEntity,HasDraftEntity,ID,IsActiveEntity,businessPartnerId,businessPartnerName,verificationStatus_code&$expand=DraftAdministrativeData($select=DraftUUID,InProcessByUser),verificationStatus($select=code,updateCode)`, 155 | { PreserveChanges: true } 156 | ); 157 | expect(response.status).to.eql(201); 158 | }); 159 | 160 | it("Update verificationStatus_code in draft state to Invalid", async () => { 161 | const response = await PATCH( 162 | `/odata/v4/sales/Notifications(ID=16f00c9c-323f-4ce4-876f-efaefe1c6f69,IsActiveEntity=false)`, 163 | { verificationStatus_code: "INV" } 164 | ); 165 | expect(response.status).to.eql(200); 166 | expect(response.data.verificationStatus_code).to.eql("INV"); 167 | }); 168 | 169 | it("Side effects qualifier", async () => { 170 | const response = await POST( 171 | "/odata/v4/sales/Notifications(ID=16f00c9c-323f-4ce4-876f-efaefe1c6f69,IsActiveEntity=false)/service.businessPartnerValidation.SalesService.draftPrepare", 172 | { SideEffectsQualifier: "" } 173 | ); 174 | expect(response.status).to.eql(200); 175 | }); 176 | 177 | it("Activate the draft notification", async () => { 178 | const response = await POST( 179 | "/odata/v4/sales/Notifications(ID=16f00c9c-323f-4ce4-876f-efaefe1c6f69,IsActiveEntity=false)/service.businessPartnerValidation.SalesService.draftActivate", 180 | {} 181 | ); 182 | expect(response.status).to.eql(200); 183 | }); 184 | }); 185 | 186 | describe("PATCH call for updating Address and verifying postal code", () => { 187 | it("Pushing active notification back to draft mode", async () => { 188 | const response = await POST( 189 | `/odata/v4/sales/Notifications(ID=2c728381-72ce-4fdd-8293-8add71579666,IsActiveEntity=true)/service.businessPartnerValidation.SalesService.draftEdit?$select=HasActiveEntity,HasDraftEntity,ID,IsActiveEntity,businessPartnerId,businessPartnerName,verificationStatus_code&$expand=DraftAdministrativeData($select=DraftUUID,InProcessByUser),verificationStatus($select=code,updateCode)`, 190 | { PreserveChanges: true } 191 | ); 192 | expect(response.status).to.eql(201); 193 | }); 194 | 195 | it("Should return 200 for updating the valid postal code", async () => { 196 | const payload = { 197 | country: "DE", 198 | cityName: "city", 199 | streetName: "street", 200 | postalCode: "99998", 201 | }; 202 | const response = await PATCH( 203 | "/odata/v4/sales/Addresses(ID=58040e66-1dcd-4ffb-ab10-fdce32028b79,IsActiveEntity=false)", 204 | payload 205 | ); 206 | expect(response.status).to.eql(200); 207 | }); 208 | 209 | it("Should return 400 for updating the invalid postal code", async () => { 210 | try { 211 | const payload = { 212 | postalCode: "123234", 213 | }; 214 | const response = await PATCH( 215 | "/odata/v4/sales/Addresses(ID=58040e66-1dcd-4ffb-ab10-fdce32028b79,IsActiveEntity=false)", 216 | payload 217 | ); 218 | } catch (err) { 219 | const errorData = 220 | err && err.response && err.response.data && err.response.data.error; 221 | expect(errorData && errorData.code).to.eql("400"); 222 | expect(errorData && errorData.message).to.eql( 223 | "invalid postal code" 224 | ); 225 | expect(errorData && errorData.target).to.eql("postalCode"); 226 | } 227 | }); 228 | }); 229 | -------------------------------------------------------------------------------- /LICENSES/Apache-2.0.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | 3 | Version 2.0, January 2004 4 | 5 | http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, 6 | AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | 11 | 12 | "License" shall mean the terms and conditions for use, reproduction, and distribution 13 | as defined by Sections 1 through 9 of this document. 14 | 15 | 16 | 17 | "Licensor" shall mean the copyright owner or entity authorized by the copyright 18 | owner that is granting the License. 19 | 20 | 21 | 22 | "Legal Entity" shall mean the union of the acting entity and all other entities 23 | that control, are controlled by, or are under common control with that entity. 24 | For the purposes of this definition, "control" means (i) the power, direct 25 | or indirect, to cause the direction or management of such entity, whether 26 | by contract or otherwise, or (ii) ownership of fifty percent (50%) or more 27 | of the outstanding shares, or (iii) beneficial ownership of such entity. 28 | 29 | 30 | 31 | "You" (or "Your") shall mean an individual or Legal Entity exercising permissions 32 | granted by this License. 33 | 34 | 35 | 36 | "Source" form shall mean the preferred form for making modifications, including 37 | but not limited to software source code, documentation source, and configuration 38 | files. 39 | 40 | 41 | 42 | "Object" form shall mean any form resulting from mechanical transformation 43 | or translation of a Source form, including but not limited to compiled object 44 | code, generated documentation, and conversions to other media types. 45 | 46 | 47 | 48 | "Work" shall mean the work of authorship, whether in Source or Object form, 49 | made available under the License, as indicated by a copyright notice that 50 | is included in or attached to the work (an example is provided in the Appendix 51 | below). 52 | 53 | 54 | 55 | "Derivative Works" shall mean any work, whether in Source or Object form, 56 | that is based on (or derived from) the Work and for which the editorial revisions, 57 | annotations, elaborations, or other modifications represent, as a whole, an 58 | original work of authorship. For the purposes of this License, Derivative 59 | Works shall not include works that remain separable from, or merely link (or 60 | bind by name) to the interfaces of, the Work and Derivative Works thereof. 61 | 62 | 63 | 64 | "Contribution" shall mean any work of authorship, including the original version 65 | of the Work and any modifications or additions to that Work or Derivative 66 | Works thereof, that is intentionally submitted to Licensor for inclusion in 67 | the Work by the copyright owner or by an individual or Legal Entity authorized 68 | to submit on behalf of the copyright owner. For the purposes of this definition, 69 | "submitted" means any form of electronic, verbal, or written communication 70 | sent to the Licensor or its representatives, including but not limited to 71 | communication on electronic mailing lists, source code control systems, and 72 | issue tracking systems that are managed by, or on behalf of, the Licensor 73 | for the purpose of discussing and improving the Work, but excluding communication 74 | that is conspicuously marked or otherwise designated in writing by the copyright 75 | owner as "Not a Contribution." 76 | 77 | 78 | 79 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf 80 | of whom a Contribution has been received by Licensor and subsequently incorporated 81 | within the Work. 82 | 83 | 2. Grant of Copyright License. Subject to the terms and conditions of this 84 | License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, 85 | no-charge, royalty-free, irrevocable copyright license to reproduce, prepare 86 | Derivative Works of, publicly display, publicly perform, sublicense, and distribute 87 | the Work and such Derivative Works in Source or Object form. 88 | 89 | 3. Grant of Patent License. Subject to the terms and conditions of this License, 90 | each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, 91 | no-charge, royalty-free, irrevocable (except as stated in this section) patent 92 | license to make, have made, use, offer to sell, sell, import, and otherwise 93 | transfer the Work, where such license applies only to those patent claims 94 | licensable by such Contributor that are necessarily infringed by their Contribution(s) 95 | alone or by combination of their Contribution(s) with the Work to which such 96 | Contribution(s) was submitted. If You institute patent litigation against 97 | any entity (including a cross-claim or counterclaim in a lawsuit) alleging 98 | that the Work or a Contribution incorporated within the Work constitutes direct 99 | or contributory patent infringement, then any patent licenses granted to You 100 | under this License for that Work shall terminate as of the date such litigation 101 | is filed. 102 | 103 | 4. Redistribution. You may reproduce and distribute copies of the Work or 104 | Derivative Works thereof in any medium, with or without modifications, and 105 | in Source or Object form, provided that You meet the following conditions: 106 | 107 | (a) You must give any other recipients of the Work or Derivative Works a copy 108 | of this License; and 109 | 110 | (b) You must cause any modified files to carry prominent notices stating that 111 | You changed the files; and 112 | 113 | (c) You must retain, in the Source form of any Derivative Works that You distribute, 114 | all copyright, patent, trademark, and attribution notices from the Source 115 | form of the Work, excluding those notices that do not pertain to any part 116 | of the Derivative Works; and 117 | 118 | (d) If the Work includes a "NOTICE" text file as part of its distribution, 119 | then any Derivative Works that You distribute must include a readable copy 120 | of the attribution notices contained within such NOTICE file, excluding those 121 | notices that do not pertain to any part of the Derivative Works, in at least 122 | one of the following places: within a NOTICE text file distributed as part 123 | of the Derivative Works; within the Source form or documentation, if provided 124 | along with the Derivative Works; or, within a display generated by the Derivative 125 | Works, if and wherever such third-party notices normally appear. The contents 126 | of the NOTICE file are for informational purposes only and do not modify the 127 | License. You may add Your own attribution notices within Derivative Works 128 | that You distribute, alongside or as an addendum to the NOTICE text from the 129 | Work, provided that such additional attribution notices cannot be construed 130 | as modifying the License. 131 | 132 | You may add Your own copyright statement to Your modifications and may provide 133 | additional or different license terms and conditions for use, reproduction, 134 | or distribution of Your modifications, or for any such Derivative Works as 135 | a whole, provided Your use, reproduction, and distribution of the Work otherwise 136 | complies with the conditions stated in this License. 137 | 138 | 5. Submission of Contributions. Unless You explicitly state otherwise, any 139 | Contribution intentionally submitted for inclusion in the Work by You to the 140 | Licensor shall be under the terms and conditions of this License, without 141 | any additional terms or conditions. Notwithstanding the above, nothing herein 142 | shall supersede or modify the terms of any separate license agreement you 143 | may have executed with Licensor regarding such Contributions. 144 | 145 | 6. Trademarks. This License does not grant permission to use the trade names, 146 | trademarks, service marks, or product names of the Licensor, except as required 147 | for reasonable and customary use in describing the origin of the Work and 148 | reproducing the content of the NOTICE file. 149 | 150 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed to 151 | in writing, Licensor provides the Work (and each Contributor provides its 152 | Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 153 | KIND, either express or implied, including, without limitation, any warranties 154 | or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR 155 | A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness 156 | of using or redistributing the Work and assume any risks associated with Your 157 | exercise of permissions under this License. 158 | 159 | 8. Limitation of Liability. In no event and under no legal theory, whether 160 | in tort (including negligence), contract, or otherwise, unless required by 161 | applicable law (such as deliberate and grossly negligent acts) or agreed to 162 | in writing, shall any Contributor be liable to You for damages, including 163 | any direct, indirect, special, incidental, or consequential damages of any 164 | character arising as a result of this License or out of the use or inability 165 | to use the Work (including but not limited to damages for loss of goodwill, 166 | work stoppage, computer failure or malfunction, or any and all other commercial 167 | damages or losses), even if such Contributor has been advised of the possibility 168 | of such damages. 169 | 170 | 9. Accepting Warranty or Additional Liability. While redistributing the Work 171 | or Derivative Works thereof, You may choose to offer, and charge a fee for, 172 | acceptance of support, warranty, indemnity, or other liability obligations 173 | and/or rights consistent with this License. However, in accepting such obligations, 174 | You may act only on Your own behalf and on Your sole responsibility, not on 175 | behalf of any other Contributor, and only if You agree to indemnify, defend, 176 | and hold each Contributor harmless for any liability incurred by, or claims 177 | asserted against, such Contributor by reason of your accepting any such warranty 178 | or additional liability. END OF TERMS AND CONDITIONS 179 | 180 | APPENDIX: How to apply the Apache License to your work. 181 | 182 | To apply the Apache License to your work, attach the following boilerplate 183 | notice, with the fields enclosed by brackets "[]" replaced with your own identifying 184 | information. (Don't include the brackets!) The text should be enclosed in 185 | the appropriate comment syntax for the file format. We also recommend that 186 | a file or class name and description of purpose be included on the same "printed 187 | page" as the copyright notice for easier identification within third-party 188 | archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | 194 | you may not use this file except in compliance with the License. 195 | 196 | You may obtain a copy of the License at 197 | 198 | http://www.apache.org/licenses/LICENSE-2.0 199 | 200 | Unless required by applicable law or agreed to in writing, software 201 | 202 | distributed under the License is distributed on an "AS IS" BASIS, 203 | 204 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 205 | 206 | See the License for the specific language governing permissions and 207 | 208 | limitations under the License. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2021 SAP 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /tests/ui/specs/test.spec.js: -------------------------------------------------------------------------------- 1 | const bpApi = require("../services/bpApi"); 2 | const bpApiService = require("../services/bpApi"); 3 | const {newBp , newAdr} = require("../services/mockData"); 4 | const endPoint = require("../../util/config").bp_app; 5 | 6 | let fioriElementsFacade; 7 | 8 | before(async () => { 9 | //initialize the list report and object pages 10 | try{ 11 | fioriElementsFacade = await browser.fe.initialize({ 12 | onTheMainPage: { 13 | ListReport: { 14 | appId: "com.sap.bp.BusinessPartners", 15 | componentId: "NotificationList", 16 | entitySet: "Notifications" 17 | } 18 | }, 19 | 20 | onTheDetailPage: { 21 | ObjectPage: { 22 | appId: "com.sap.bp.BusinessPartners", 23 | componentId: "NotificationObjectPage", 24 | entitySet: "Notifications" 25 | } 26 | }, 27 | 28 | onTheShell: { 29 | Shell:{} 30 | } 31 | }); 32 | 33 | console.log("Test library integrated") 34 | } 35 | catch(err){ 36 | console.log(`Could not integrate test library: ${err}`) 37 | process.exit() 38 | } 39 | }); 40 | 41 | describe("Before Validating the application", () => { 42 | // create mock BP before executing any test suites 43 | it("Create test data", async() => { 44 | response = await bpApiService.postMethod(browser) 45 | try{ 46 | expect(response.status).toEqual(201) 47 | // response.should.have.status(201) 48 | console.log(`Business Partner created : ${response.data.BusinessPartnerName}`) 49 | } 50 | catch(err){ 51 | console.error(err) 52 | console.log("Business Partner not created"); 53 | console.log(`Error Code : ${response.status}`) 54 | await browser.closeWindow() 55 | process.exit() 56 | } 57 | }) 58 | }) 59 | describe("After test data is created", () => { 60 | 61 | it("Validations on table on list report page", async () => { 62 | await fioriElementsFacade.execute(async(Given, When, Then) => { 63 | console.log("Table validation") 64 | 65 | //ensure the man page has loaded 66 | Then.onTheMainPage.iSeeThisPage() 67 | //display all rows of the table 68 | When.onTheMainPage.onFilterBar().iExecuteSearch() 69 | 70 | //verify data of the mock BP created 71 | Then.onTheMainPage.onTable().iCheckRows( 72 | mRowValues = { 73 | 0 : newBp.BusinessPartner, 74 | 1 : newBp.BusinessPartnerName, 75 | 2 : "NEW" 76 | } 77 | ) 78 | 79 | //aggrgate the rows by a particular verification status column 80 | When.onTheMainPage.onTable().iAggregateByColumn( 81 | vColumnIdentifier = { name : "Verification Status" }, 82 | sFieldLabel = "Verification Status (Verification Status)" 83 | ) 84 | 85 | // change sorting order and check the same 86 | When.onTheMainPage.onTable().iChangeSortOrder( 87 | vColumnIdentifier = { name : "verificationStatus_code" }, 88 | sSortOrder = "Descending" 89 | ) 90 | 91 | //to undo the column aggregation 92 | When.onTheMainPage.onTable().iAggregateByColumn( 93 | vColumnIdentifier = { name : "Verification Status" }, 94 | sFieldLabel = "Verification Status (Verification Status)" 95 | ) 96 | 97 | }) 98 | }); 99 | 100 | it("Validations on filter bar on list report page", async () => { 101 | await fioriElementsFacade.execute(async(Given, When, Then) => { 102 | 103 | console.log("Filter bar validation") 104 | Then.onTheMainPage.iSeeThisPage() 105 | When.onTheMainPage.onFilterBar().iExecuteSearch() 106 | 107 | // Search with filter field business partner ID 108 | When.onTheMainPage.onFilterBar().iChangeFilterField( 109 | vFieldIdentifier = { property : "businessPartnerId" }, 110 | vValue = newBp.BusinessPartner 111 | ).and.iExecuteSearch() 112 | 113 | Then.onTheMainPage.onTable().iCheckRows( 114 | mRowValues = { 1 : newBp.BusinessPartnerName }, 115 | iExpectedNumberOfRows = 1 116 | ) 117 | 118 | When.onTheMainPage.onFilterBar().iChangeFilterField( 119 | vFieldIdentifier = { property : "businessPartnerId" }, 120 | bClearFirst = true 121 | ) 122 | 123 | //Search with filter field business partner name 124 | When.onTheMainPage.onFilterBar().iChangeFilterField( 125 | vFieldIdentifier = { property : "businessPartnerName" }, 126 | vValue = newBp.BusinessPartnerName 127 | ).and.iExecuteSearch() 128 | 129 | Then.onTheMainPage.onTable().iCheckRows( 130 | mRowValues = { 0 : newBp.BusinessPartner }, 131 | iExpectedNumberOfRows = 1 132 | ) 133 | 134 | When.onTheMainPage.onFilterBar().iChangeFilterField( 135 | vFieldIdentifier = { property : "businessPartnerName" }, 136 | bClearFirst = true 137 | ) 138 | 139 | // Search with filter field verification status 140 | When.onTheMainPage.onFilterBar().iChangeFilterField( 141 | vFieldIdentifier = { property : "verificationStatus_code" }, 142 | vValue = "NEW (N)" 143 | ).and.iExecuteSearch() 144 | 145 | Then.onTheMainPage.onTable().iCheckRows( iExpectedNumberOfRows = 2 ) 146 | 147 | When.onTheMainPage.onFilterBar().iChangeFilterField( 148 | vFieldIdentifier = { property : "verificationStatus_code" }, 149 | bClearFirst = true 150 | ) 151 | 152 | // Search with the search field 153 | When.onTheMainPage.onFilterBar().iChangeSearchField( 154 | newBp.BusinessPartnerName 155 | ).and.iExecuteSearch() 156 | 157 | Then.onTheMainPage.onTable().iCheckRows( 158 | mRowValues = { 0 : newBp.BusinessPartner }, 159 | iExpectedNumberOfRows = 1 160 | ) 161 | 162 | When.onTheMainPage.onFilterBar().iResetSearchField().and.iExecuteSearch() 163 | 164 | }) 165 | }); 166 | 167 | it("Validations on the object page", async()=>{ 168 | await fioriElementsFacade.execute(async (Given, When, Then) => { 169 | 170 | console.log("Object page validation") 171 | Then.onTheMainPage.iSeeThisPage() 172 | //display the table on the list report page 173 | When.onTheMainPage.onFilterBar().iExecuteSearch() 174 | //click on the specific row to see object page 175 | When.onTheMainPage.onTable().iPressRow({ "Business Partner ID" : newBp.BusinessPartner }) 176 | Then.onTheDetailPage.iSeeThisPage() 177 | 178 | //verify title and details on header : Name and Verification Status 179 | Then.onTheDetailPage.onHeader().iCheckTitle(sTitle = newBp.BusinessPartner) 180 | 181 | Then.onTheDetailPage.onHeader().iCheckDataPoint( 182 | sTitle = "Business Partner Name", 183 | sValue = newBp.BusinessPartnerName 184 | ) 185 | 186 | Then.onTheDetailPage.onHeader() 187 | .iCheckFieldInFieldGroup( 188 | vFieldIdentifier = { 189 | fieldGroup : "FieldGroup::Detail", 190 | field : "verificationStatus_code" 191 | }, 192 | value = "N" 193 | ) 194 | 195 | //verify address details 196 | Then.onTheDetailPage 197 | .onTable({property : "addresses"}) 198 | .iCheckRows( 199 | vRowValues = { 200 | 0 : newBp.to_BusinessPartnerAddress[0].AddressID, 201 | 1 : newBp.BusinessPartner, 202 | 2 : newBp.to_BusinessPartnerAddress[0].StreetName, 203 | 3 : newBp.to_BusinessPartnerAddress[0].CityName, 204 | 4 : newBp.to_BusinessPartnerAddress[0].Country, 205 | 5 : newBp.to_BusinessPartnerAddress[0].PostalCode 206 | }, 207 | iExpectedNumberOfRows = 1 208 | ) 209 | 210 | //check and edit object page 211 | Then.onTheDetailPage.onHeader().iCheckEdit() 212 | When.onTheDetailPage.onHeader().iExecuteEdit() 213 | 214 | 215 | //edit verification status, save and verify change 216 | When.onTheDetailPage 217 | .onForm( vFormIdentifier = { isHeaderFacet : true } ) 218 | .iChangeField( 219 | { property : "verificationStatus_code" }, 220 | "V" 221 | ) 222 | 223 | When.onTheDetailPage 224 | .onTable({property : "addresses"}) 225 | .iChangeRow( 226 | vRowValues = 0, 227 | mTargetValues = { 228 | 2 : newAdr.Street, 229 | 5 : newAdr.PostalCode 230 | } 231 | ) 232 | 233 | When.onTheDetailPage.onFooter().iExecuteSave(); 234 | 235 | Then.onTheDetailPage.onHeader() 236 | .iCheckFieldInFieldGroup( 237 | vFieldIdentifier = { 238 | fieldGroup : "FieldGroup::Detail", 239 | field : "verificationStatus_code" 240 | }, 241 | value = "V" 242 | ) 243 | 244 | Then.onTheDetailPage 245 | .onTable({property : "addresses"}) 246 | .iCheckRows( 247 | vRowValues = { 248 | 2 : newAdr.Street, 249 | 5 : newAdr.PostalCode 250 | }, 251 | iExpectedNumberOfRows = 1 252 | ) 253 | 254 | }) 255 | }); 256 | 257 | }) 258 | describe("After validation of the application", async() => { 259 | 260 | it("Delete the test data from table", async()=>{ 261 | await browser.url(endPoint.main); 262 | 263 | await fioriElementsFacade.execute(async(Given, When, Then) => { 264 | 265 | Then.onTheMainPage.iSeeThisPage() 266 | When.onTheMainPage.onFilterBar().iExecuteSearch() 267 | 268 | Then.onTheMainPage.onTable().iCheckRows( 269 | mRowValues = { 1 : newBp.BusinessPartnerName, 2 : "COMPLETED" }, 270 | iExpectedNumberOfRows = 1 271 | ) 272 | 273 | //select the row with the created BP 274 | When.onTheMainPage.onTable() 275 | .iSelectRows(vRowValues = { "Business Partner ID" : newBp.BusinessPartner }) 276 | .and 277 | .iExecuteDelete() 278 | 279 | //confirm the dialog that pops up 280 | When.onTheMainPage.onDialog().iConfirm(); 281 | 282 | Then.onTheMainPage.onTable().iCheckRows( 283 | mRowValues = { 1 : newBp.BusinessPartnerName}, 284 | iExpectedNumberOfRows = 0 285 | ) 286 | }) 287 | }) 288 | //delete the created BP from mockserver 289 | it("Delete test data from mock server", async() => { 290 | response = await bpApiService.deleteMethod(browser) 291 | try{ 292 | expect(response.status).toEqual(204) 293 | // expect(response.status).to.be.equal(204) 294 | console.log("Business Partner Deleted from mock server") 295 | } 296 | catch(err){ 297 | console.error(err) 298 | console.log("Business Partner not deleted properly from mock server"); 299 | console.log(`Error Code : ${response.status}`) 300 | await browser.closeWindow() 301 | process.exit() 302 | } 303 | }); 304 | }) 305 | -------------------------------------------------------------------------------- /srv/external/API_BUSINESS_PARTNER.csn: -------------------------------------------------------------------------------- 1 | { 2 | "definitions": { 3 | "API_BUSINESS_PARTNER": { 4 | "kind": "service", 5 | "@imported": true 6 | }, 7 | "API_BUSINESS_PARTNER.A_AddressEmailAddress": { 8 | "kind": "entity", 9 | "@cds.persistence.skip": true, 10 | "elements": { 11 | "AddressID": { 12 | "key": true, 13 | "type": "cds.String", 14 | "length": 10 15 | }, 16 | "Person": { 17 | "key": true, 18 | "type": "cds.String", 19 | "length": 10 20 | }, 21 | "OrdinalNumber": { 22 | "key": true, 23 | "type": "cds.String", 24 | "length": 3 25 | }, 26 | "IsDefaultEmailAddress": { 27 | "type": "cds.Boolean" 28 | }, 29 | "EmailAddress": { 30 | "type": "cds.String", 31 | "length": 241 32 | }, 33 | "SearchEmailAddress": { 34 | "type": "cds.String", 35 | "length": 20 36 | } 37 | } 38 | }, 39 | "API_BUSINESS_PARTNER.A_AddressFaxNumber": { 40 | "kind": "entity", 41 | "@cds.persistence.skip": true, 42 | "elements": { 43 | "AddressID": { 44 | "key": true, 45 | "type": "cds.String", 46 | "length": 10 47 | }, 48 | "Person": { 49 | "key": true, 50 | "type": "cds.String", 51 | "length": 10 52 | }, 53 | "OrdinalNumber": { 54 | "key": true, 55 | "type": "cds.String", 56 | "length": 3 57 | }, 58 | "IsDefaultFaxNumber": { 59 | "type": "cds.Boolean" 60 | }, 61 | "FaxCountry": { 62 | "type": "cds.String", 63 | "length": 3 64 | }, 65 | "FaxNumber": { 66 | "type": "cds.String", 67 | "length": 30 68 | }, 69 | "FaxNumberExtension": { 70 | "type": "cds.String", 71 | "length": 10 72 | }, 73 | "InternationalFaxNumber": { 74 | "type": "cds.String", 75 | "length": 30 76 | } 77 | } 78 | }, 79 | "API_BUSINESS_PARTNER.A_AddressHomePageURL": { 80 | "kind": "entity", 81 | "@cds.persistence.skip": true, 82 | "elements": { 83 | "AddressID": { 84 | "key": true, 85 | "type": "cds.String", 86 | "length": 10 87 | }, 88 | "Person": { 89 | "key": true, 90 | "type": "cds.String", 91 | "length": 10 92 | }, 93 | "OrdinalNumber": { 94 | "key": true, 95 | "type": "cds.String", 96 | "length": 3 97 | }, 98 | "ValidityStartDate": { 99 | "key": true, 100 | "type": "cds.Date" 101 | }, 102 | "IsDefaultURLAddress": { 103 | "key": true, 104 | "type": "cds.Boolean" 105 | }, 106 | "SearchURLAddress": { 107 | "type": "cds.String", 108 | "length": 50 109 | }, 110 | "URLFieldLength": { 111 | "type": "cds.Integer" 112 | }, 113 | "WebsiteURL": { 114 | "type": "cds.String", 115 | "length": 2048 116 | } 117 | } 118 | }, 119 | "API_BUSINESS_PARTNER.A_AddressPhoneNumber": { 120 | "kind": "entity", 121 | "@cds.persistence.skip": true, 122 | "elements": { 123 | "AddressID": { 124 | "key": true, 125 | "type": "cds.String", 126 | "length": 10 127 | }, 128 | "Person": { 129 | "key": true, 130 | "type": "cds.String", 131 | "length": 10 132 | }, 133 | "OrdinalNumber": { 134 | "key": true, 135 | "type": "cds.String", 136 | "length": 3 137 | }, 138 | "DestinationLocationCountry": { 139 | "type": "cds.String", 140 | "length": 3 141 | }, 142 | "IsDefaultPhoneNumber": { 143 | "type": "cds.Boolean" 144 | }, 145 | "PhoneNumber": { 146 | "type": "cds.String", 147 | "length": 30 148 | }, 149 | "PhoneNumberExtension": { 150 | "type": "cds.String", 151 | "length": 10 152 | }, 153 | "InternationalPhoneNumber": { 154 | "type": "cds.String", 155 | "length": 30 156 | }, 157 | "PhoneNumberType": { 158 | "type": "cds.String", 159 | "length": 1 160 | } 161 | } 162 | }, 163 | "API_BUSINESS_PARTNER.A_BPContactToAddress": { 164 | "kind": "entity", 165 | "@cds.persistence.skip": true, 166 | "elements": { 167 | "RelationshipNumber": { 168 | "key": true, 169 | "type": "cds.String", 170 | "length": 12 171 | }, 172 | "BusinessPartnerCompany": { 173 | "key": true, 174 | "type": "cds.String", 175 | "length": 10 176 | }, 177 | "BusinessPartnerPerson": { 178 | "key": true, 179 | "type": "cds.String", 180 | "length": 10 181 | }, 182 | "ValidityEndDate": { 183 | "key": true, 184 | "type": "cds.Date" 185 | }, 186 | "AddressID": { 187 | "key": true, 188 | "type": "cds.String", 189 | "length": 10 190 | }, 191 | "AddressNumber": { 192 | "type": "cds.String", 193 | "length": 10 194 | }, 195 | "AdditionalStreetPrefixName": { 196 | "type": "cds.String", 197 | "length": 40 198 | }, 199 | "AdditionalStreetSuffixName": { 200 | "type": "cds.String", 201 | "length": 40 202 | }, 203 | "AddressTimeZone": { 204 | "type": "cds.String", 205 | "length": 6 206 | }, 207 | "CareOfName": { 208 | "type": "cds.String", 209 | "length": 40 210 | }, 211 | "CityCode": { 212 | "type": "cds.String", 213 | "length": 12 214 | }, 215 | "CityName": { 216 | "type": "cds.String", 217 | "length": 40 218 | }, 219 | "CompanyPostalCode": { 220 | "type": "cds.String", 221 | "length": 10 222 | }, 223 | "Country": { 224 | "type": "cds.String", 225 | "length": 3 226 | }, 227 | "County": { 228 | "type": "cds.String", 229 | "length": 40 230 | }, 231 | "DeliveryServiceNumber": { 232 | "type": "cds.String", 233 | "length": 10 234 | }, 235 | "DeliveryServiceTypeCode": { 236 | "type": "cds.String", 237 | "length": 4 238 | }, 239 | "District": { 240 | "type": "cds.String", 241 | "length": 40 242 | }, 243 | "FormOfAddress": { 244 | "type": "cds.String", 245 | "length": 4 246 | }, 247 | "FullName": { 248 | "type": "cds.String", 249 | "length": 80 250 | }, 251 | "HomeCityName": { 252 | "type": "cds.String", 253 | "length": 40 254 | }, 255 | "HouseNumber": { 256 | "type": "cds.String", 257 | "length": 10 258 | }, 259 | "HouseNumberSupplementText": { 260 | "type": "cds.String", 261 | "length": 10 262 | }, 263 | "Language": { 264 | "type": "cds.String", 265 | "length": 2 266 | }, 267 | "POBox": { 268 | "type": "cds.String", 269 | "length": 10 270 | }, 271 | "POBoxDeviatingCityName": { 272 | "type": "cds.String", 273 | "length": 40 274 | }, 275 | "POBoxDeviatingCountry": { 276 | "type": "cds.String", 277 | "length": 3 278 | }, 279 | "POBoxDeviatingRegion": { 280 | "type": "cds.String", 281 | "length": 3 282 | }, 283 | "POBoxIsWithoutNumber": { 284 | "type": "cds.Boolean" 285 | }, 286 | "POBoxLobbyName": { 287 | "type": "cds.String", 288 | "length": 40 289 | }, 290 | "POBoxPostalCode": { 291 | "type": "cds.String", 292 | "length": 10 293 | }, 294 | "Person": { 295 | "type": "cds.String", 296 | "length": 10 297 | }, 298 | "PostalCode": { 299 | "type": "cds.String", 300 | "length": 10 301 | }, 302 | "PrfrdCommMediumType": { 303 | "type": "cds.String", 304 | "length": 3 305 | }, 306 | "Region": { 307 | "type": "cds.String", 308 | "length": 3 309 | }, 310 | "StreetName": { 311 | "type": "cds.String", 312 | "length": 60 313 | }, 314 | "StreetPrefixName": { 315 | "type": "cds.String", 316 | "length": 40 317 | }, 318 | "StreetSuffixName": { 319 | "type": "cds.String", 320 | "length": 40 321 | }, 322 | "TaxJurisdiction": { 323 | "type": "cds.String", 324 | "length": 15 325 | }, 326 | "TransportZone": { 327 | "type": "cds.String", 328 | "length": 10 329 | }, 330 | "to_EmailAddress": { 331 | "type": "cds.Association", 332 | "target": "API_BUSINESS_PARTNER.A_AddressEmailAddress", 333 | "cardinality": { 334 | "max": "*" 335 | } 336 | }, 337 | "to_FaxNumber": { 338 | "type": "cds.Association", 339 | "target": "API_BUSINESS_PARTNER.A_AddressFaxNumber", 340 | "cardinality": { 341 | "max": "*" 342 | } 343 | }, 344 | "to_MobilePhoneNumber": { 345 | "type": "cds.Association", 346 | "target": "API_BUSINESS_PARTNER.A_AddressPhoneNumber", 347 | "cardinality": { 348 | "max": "*" 349 | } 350 | }, 351 | "to_PhoneNumber": { 352 | "type": "cds.Association", 353 | "target": "API_BUSINESS_PARTNER.A_AddressPhoneNumber", 354 | "cardinality": { 355 | "max": "*" 356 | } 357 | }, 358 | "to_URLAddress": { 359 | "type": "cds.Association", 360 | "target": "API_BUSINESS_PARTNER.A_AddressHomePageURL", 361 | "cardinality": { 362 | "max": "*" 363 | } 364 | } 365 | } 366 | }, 367 | "API_BUSINESS_PARTNER.A_BPContactToFuncAndDept": { 368 | "kind": "entity", 369 | "@cds.persistence.skip": true, 370 | "elements": { 371 | "RelationshipNumber": { 372 | "key": true, 373 | "type": "cds.String", 374 | "length": 12 375 | }, 376 | "BusinessPartnerCompany": { 377 | "key": true, 378 | "type": "cds.String", 379 | "length": 10 380 | }, 381 | "BusinessPartnerPerson": { 382 | "key": true, 383 | "type": "cds.String", 384 | "length": 10 385 | }, 386 | "ValidityEndDate": { 387 | "key": true, 388 | "type": "cds.Date" 389 | }, 390 | "ContactPersonFunction": { 391 | "type": "cds.String", 392 | "length": 4 393 | }, 394 | "ContactPersonDepartment": { 395 | "type": "cds.String", 396 | "length": 4 397 | }, 398 | "PhoneNumber": { 399 | "type": "cds.String", 400 | "length": 30 401 | }, 402 | "PhoneNumberExtension": { 403 | "type": "cds.String", 404 | "length": 10 405 | }, 406 | "FaxNumber": { 407 | "type": "cds.String", 408 | "length": 30 409 | }, 410 | "FaxNumberExtension": { 411 | "type": "cds.String", 412 | "length": 10 413 | }, 414 | "EmailAddress": { 415 | "type": "cds.String", 416 | "length": 241 417 | }, 418 | "RelationshipCategory": { 419 | "type": "cds.String", 420 | "length": 6 421 | } 422 | } 423 | }, 424 | "API_BUSINESS_PARTNER.A_BuPaAddressUsage": { 425 | "kind": "entity", 426 | "@cds.persistence.skip": true, 427 | "elements": { 428 | "BusinessPartner": { 429 | "key": true, 430 | "type": "cds.String", 431 | "length": 10 432 | }, 433 | "ValidityEndDate": { 434 | "key": true, 435 | "type": "cds.Timestamp" 436 | }, 437 | "AddressUsage": { 438 | "key": true, 439 | "type": "cds.String", 440 | "length": 10 441 | }, 442 | "AddressID": { 443 | "key": true, 444 | "type": "cds.String", 445 | "length": 10 446 | }, 447 | "ValidityStartDate": { 448 | "type": "cds.Timestamp" 449 | }, 450 | "StandardUsage": { 451 | "type": "cds.Boolean" 452 | }, 453 | "AuthorizationGroup": { 454 | "type": "cds.String", 455 | "length": 4 456 | } 457 | } 458 | }, 459 | "API_BUSINESS_PARTNER.A_BuPaIdentification": { 460 | "kind": "entity", 461 | "@cds.persistence.skip": true, 462 | "elements": { 463 | "BusinessPartner": { 464 | "key": true, 465 | "type": "cds.String", 466 | "length": 10 467 | }, 468 | "BPIdentificationType": { 469 | "key": true, 470 | "type": "cds.String", 471 | "length": 6 472 | }, 473 | "BPIdentificationNumber": { 474 | "key": true, 475 | "type": "cds.String", 476 | "length": 60 477 | }, 478 | "BPIdnNmbrIssuingInstitute": { 479 | "type": "cds.String", 480 | "length": 40 481 | }, 482 | "BPIdentificationEntryDate": { 483 | "type": "cds.Date" 484 | }, 485 | "Country": { 486 | "type": "cds.String", 487 | "length": 3 488 | }, 489 | "Region": { 490 | "type": "cds.String", 491 | "length": 3 492 | }, 493 | "ValidityStartDate": { 494 | "type": "cds.Date" 495 | }, 496 | "ValidityEndDate": { 497 | "type": "cds.Date" 498 | }, 499 | "AuthorizationGroup": { 500 | "type": "cds.String", 501 | "length": 4 502 | } 503 | } 504 | }, 505 | "API_BUSINESS_PARTNER.A_BuPaIndustry": { 506 | "kind": "entity", 507 | "@cds.persistence.skip": true, 508 | "elements": { 509 | "IndustrySector": { 510 | "key": true, 511 | "type": "cds.String", 512 | "length": 10 513 | }, 514 | "IndustrySystemType": { 515 | "key": true, 516 | "type": "cds.String", 517 | "length": 4 518 | }, 519 | "BusinessPartner": { 520 | "key": true, 521 | "type": "cds.String", 522 | "length": 10 523 | }, 524 | "IsStandardIndustry": { 525 | "type": "cds.String", 526 | "length": 1 527 | }, 528 | "IndustryKeyDescription": { 529 | "type": "cds.String", 530 | "length": 100 531 | } 532 | } 533 | }, 534 | "API_BUSINESS_PARTNER.A_BusinessPartner": { 535 | "kind": "entity", 536 | "@cds.persistence.skip": true, 537 | "elements": { 538 | "BusinessPartner": { 539 | "key": true, 540 | "type": "cds.String", 541 | "length": 10 542 | }, 543 | "Customer": { 544 | "type": "cds.String", 545 | "length": 10 546 | }, 547 | "Supplier": { 548 | "type": "cds.String", 549 | "length": 10 550 | }, 551 | "AcademicTitle": { 552 | "type": "cds.String", 553 | "length": 4 554 | }, 555 | "AuthorizationGroup": { 556 | "type": "cds.String", 557 | "length": 4 558 | }, 559 | "BusinessPartnerCategory": { 560 | "type": "cds.String", 561 | "length": 1 562 | }, 563 | "BusinessPartnerFullName": { 564 | "type": "cds.String", 565 | "length": 81 566 | }, 567 | "BusinessPartnerGrouping": { 568 | "type": "cds.String", 569 | "length": 4 570 | }, 571 | "BusinessPartnerName": { 572 | "type": "cds.String", 573 | "length": 81 574 | }, 575 | "BusinessPartnerUUID": { 576 | "type": "cds.UUID" 577 | }, 578 | "CorrespondenceLanguage": { 579 | "type": "cds.String", 580 | "length": 2 581 | }, 582 | "CreatedByUser": { 583 | "type": "cds.String", 584 | "length": 12 585 | }, 586 | "CreationDate": { 587 | "type": "cds.Date" 588 | }, 589 | "CreationTime": { 590 | "type": "cds.Time" 591 | }, 592 | "FirstName": { 593 | "type": "cds.String", 594 | "length": 40 595 | }, 596 | "FormOfAddress": { 597 | "type": "cds.String", 598 | "length": 4 599 | }, 600 | "Industry": { 601 | "type": "cds.String", 602 | "length": 10 603 | }, 604 | "InternationalLocationNumber1": { 605 | "type": "cds.String", 606 | "length": 7 607 | }, 608 | "InternationalLocationNumber2": { 609 | "type": "cds.String", 610 | "length": 5 611 | }, 612 | "IsFemale": { 613 | "type": "cds.Boolean" 614 | }, 615 | "IsMale": { 616 | "type": "cds.Boolean" 617 | }, 618 | "IsNaturalPerson": { 619 | "type": "cds.String", 620 | "length": 1 621 | }, 622 | "IsSexUnknown": { 623 | "type": "cds.Boolean" 624 | }, 625 | "Language": { 626 | "type": "cds.String", 627 | "length": 2 628 | }, 629 | "LastChangeDate": { 630 | "type": "cds.Date" 631 | }, 632 | "LastChangeTime": { 633 | "type": "cds.Time" 634 | }, 635 | "LastChangedByUser": { 636 | "type": "cds.String", 637 | "length": 12 638 | }, 639 | "LastName": { 640 | "type": "cds.String", 641 | "length": 40 642 | }, 643 | "LegalForm": { 644 | "type": "cds.String", 645 | "length": 2 646 | }, 647 | "OrganizationBPName1": { 648 | "type": "cds.String", 649 | "length": 40 650 | }, 651 | "OrganizationBPName2": { 652 | "type": "cds.String", 653 | "length": 40 654 | }, 655 | "OrganizationBPName3": { 656 | "type": "cds.String", 657 | "length": 40 658 | }, 659 | "OrganizationBPName4": { 660 | "type": "cds.String", 661 | "length": 40 662 | }, 663 | "OrganizationFoundationDate": { 664 | "type": "cds.Date" 665 | }, 666 | "OrganizationLiquidationDate": { 667 | "type": "cds.Date" 668 | }, 669 | "SearchTerm1": { 670 | "type": "cds.String", 671 | "length": 20 672 | }, 673 | "AdditionalLastName": { 674 | "type": "cds.String", 675 | "length": 40 676 | }, 677 | "BirthDate": { 678 | "type": "cds.Date" 679 | }, 680 | "BusinessPartnerIsBlocked": { 681 | "type": "cds.Boolean" 682 | }, 683 | "BusinessPartnerType": { 684 | "type": "cds.String", 685 | "length": 4 686 | }, 687 | "ETag": { 688 | "type": "cds.String", 689 | "length": 26 690 | }, 691 | "GroupBusinessPartnerName1": { 692 | "type": "cds.String", 693 | "length": 40 694 | }, 695 | "GroupBusinessPartnerName2": { 696 | "type": "cds.String", 697 | "length": 40 698 | }, 699 | "IndependentAddressID": { 700 | "type": "cds.String", 701 | "length": 10 702 | }, 703 | "InternationalLocationNumber3": { 704 | "type": "cds.String", 705 | "length": 1 706 | }, 707 | "MiddleName": { 708 | "type": "cds.String", 709 | "length": 40 710 | }, 711 | "NameCountry": { 712 | "type": "cds.String", 713 | "length": 3 714 | }, 715 | "NameFormat": { 716 | "type": "cds.String", 717 | "length": 2 718 | }, 719 | "PersonFullName": { 720 | "type": "cds.String", 721 | "length": 80 722 | }, 723 | "PersonNumber": { 724 | "type": "cds.String", 725 | "length": 10 726 | }, 727 | "IsMarkedForArchiving": { 728 | "type": "cds.Boolean" 729 | }, 730 | "BusinessPartnerIDByExtSystem": { 731 | "type": "cds.String", 732 | "length": 20 733 | }, 734 | "TradingPartner": { 735 | "type": "cds.String", 736 | "length": 6 737 | }, 738 | "to_BuPaIdentification": { 739 | "type": "cds.Association", 740 | "target": "API_BUSINESS_PARTNER.A_BuPaIdentification", 741 | "cardinality": { 742 | "max": "*" 743 | } 744 | }, 745 | "to_BuPaIndustry": { 746 | "type": "cds.Association", 747 | "target": "API_BUSINESS_PARTNER.A_BuPaIndustry", 748 | "cardinality": { 749 | "max": "*" 750 | } 751 | }, 752 | "to_BusinessPartnerAddress": { 753 | "type": "cds.Association", 754 | "target": "API_BUSINESS_PARTNER.A_BusinessPartnerAddress", 755 | "cardinality": { 756 | "max": "*" 757 | } 758 | }, 759 | "to_BusinessPartnerBank": { 760 | "type": "cds.Association", 761 | "target": "API_BUSINESS_PARTNER.A_BusinessPartnerBank", 762 | "cardinality": { 763 | "max": "*" 764 | } 765 | }, 766 | "to_BusinessPartnerContact": { 767 | "type": "cds.Association", 768 | "target": "API_BUSINESS_PARTNER.A_BusinessPartnerContact", 769 | "cardinality": { 770 | "max": "*" 771 | } 772 | }, 773 | "to_BusinessPartnerRole": { 774 | "type": "cds.Association", 775 | "target": "API_BUSINESS_PARTNER.A_BusinessPartnerRole", 776 | "cardinality": { 777 | "max": "*" 778 | } 779 | }, 780 | "to_BusinessPartnerTax": { 781 | "type": "cds.Association", 782 | "target": "API_BUSINESS_PARTNER.A_BusinessPartnerTaxNumber", 783 | "cardinality": { 784 | "max": "*" 785 | } 786 | }, 787 | "to_Customer": { 788 | "type": "cds.Association", 789 | "target": "API_BUSINESS_PARTNER.A_Customer" 790 | }, 791 | "to_Supplier": { 792 | "type": "cds.Association", 793 | "target": "API_BUSINESS_PARTNER.A_Supplier" 794 | } 795 | } 796 | }, 797 | "API_BUSINESS_PARTNER.A_BusinessPartnerAddress": { 798 | "kind": "entity", 799 | "@cds.persistence.skip": true, 800 | "elements": { 801 | "BusinessPartner": { 802 | "key": true, 803 | "type": "cds.String", 804 | "length": 10 805 | }, 806 | "AddressID": { 807 | "key": true, 808 | "type": "cds.String", 809 | "length": 10 810 | }, 811 | "ValidityStartDate": { 812 | "type": "cds.Timestamp" 813 | }, 814 | "ValidityEndDate": { 815 | "type": "cds.Timestamp" 816 | }, 817 | "AuthorizationGroup": { 818 | "type": "cds.String", 819 | "length": 4 820 | }, 821 | "AddressUUID": { 822 | "type": "cds.UUID" 823 | }, 824 | "AdditionalStreetPrefixName": { 825 | "type": "cds.String", 826 | "length": 40 827 | }, 828 | "AdditionalStreetSuffixName": { 829 | "type": "cds.String", 830 | "length": 40 831 | }, 832 | "AddressTimeZone": { 833 | "type": "cds.String", 834 | "length": 6 835 | }, 836 | "CareOfName": { 837 | "type": "cds.String", 838 | "length": 40 839 | }, 840 | "CityCode": { 841 | "type": "cds.String", 842 | "length": 12 843 | }, 844 | "CityName": { 845 | "type": "cds.String", 846 | "length": 40 847 | }, 848 | "CompanyPostalCode": { 849 | "type": "cds.String", 850 | "length": 10 851 | }, 852 | "Country": { 853 | "type": "cds.String", 854 | "length": 3 855 | }, 856 | "County": { 857 | "type": "cds.String", 858 | "length": 40 859 | }, 860 | "DeliveryServiceNumber": { 861 | "type": "cds.String", 862 | "length": 10 863 | }, 864 | "DeliveryServiceTypeCode": { 865 | "type": "cds.String", 866 | "length": 4 867 | }, 868 | "District": { 869 | "type": "cds.String", 870 | "length": 40 871 | }, 872 | "FormOfAddress": { 873 | "type": "cds.String", 874 | "length": 4 875 | }, 876 | "FullName": { 877 | "type": "cds.String", 878 | "length": 80 879 | }, 880 | "HomeCityName": { 881 | "type": "cds.String", 882 | "length": 40 883 | }, 884 | "HouseNumber": { 885 | "type": "cds.String", 886 | "length": 10 887 | }, 888 | "HouseNumberSupplementText": { 889 | "type": "cds.String", 890 | "length": 10 891 | }, 892 | "Language": { 893 | "type": "cds.String", 894 | "length": 2 895 | }, 896 | "POBox": { 897 | "type": "cds.String", 898 | "length": 10 899 | }, 900 | "POBoxDeviatingCityName": { 901 | "type": "cds.String", 902 | "length": 40 903 | }, 904 | "POBoxDeviatingCountry": { 905 | "type": "cds.String", 906 | "length": 3 907 | }, 908 | "POBoxDeviatingRegion": { 909 | "type": "cds.String", 910 | "length": 3 911 | }, 912 | "POBoxIsWithoutNumber": { 913 | "type": "cds.Boolean" 914 | }, 915 | "POBoxLobbyName": { 916 | "type": "cds.String", 917 | "length": 40 918 | }, 919 | "POBoxPostalCode": { 920 | "type": "cds.String", 921 | "length": 10 922 | }, 923 | "Person": { 924 | "type": "cds.String", 925 | "length": 10 926 | }, 927 | "PostalCode": { 928 | "type": "cds.String", 929 | "length": 10 930 | }, 931 | "PrfrdCommMediumType": { 932 | "type": "cds.String", 933 | "length": 3 934 | }, 935 | "Region": { 936 | "type": "cds.String", 937 | "length": 3 938 | }, 939 | "StreetName": { 940 | "type": "cds.String", 941 | "length": 60 942 | }, 943 | "StreetPrefixName": { 944 | "type": "cds.String", 945 | "length": 40 946 | }, 947 | "StreetSuffixName": { 948 | "type": "cds.String", 949 | "length": 40 950 | }, 951 | "TaxJurisdiction": { 952 | "type": "cds.String", 953 | "length": 15 954 | }, 955 | "TransportZone": { 956 | "type": "cds.String", 957 | "length": 10 958 | }, 959 | "AddressIDByExternalSystem": { 960 | "type": "cds.String", 961 | "length": 20 962 | }, 963 | "to_AddressUsage": { 964 | "type": "cds.Association", 965 | "target": "API_BUSINESS_PARTNER.A_BuPaAddressUsage", 966 | "cardinality": { 967 | "max": "*" 968 | } 969 | }, 970 | "to_EmailAddress": { 971 | "type": "cds.Association", 972 | "target": "API_BUSINESS_PARTNER.A_AddressEmailAddress", 973 | "cardinality": { 974 | "max": "*" 975 | } 976 | }, 977 | "to_FaxNumber": { 978 | "type": "cds.Association", 979 | "target": "API_BUSINESS_PARTNER.A_AddressFaxNumber", 980 | "cardinality": { 981 | "max": "*" 982 | } 983 | }, 984 | "to_MobilePhoneNumber": { 985 | "type": "cds.Association", 986 | "target": "API_BUSINESS_PARTNER.A_AddressPhoneNumber", 987 | "cardinality": { 988 | "max": "*" 989 | } 990 | }, 991 | "to_PhoneNumber": { 992 | "type": "cds.Association", 993 | "target": "API_BUSINESS_PARTNER.A_AddressPhoneNumber", 994 | "cardinality": { 995 | "max": "*" 996 | } 997 | }, 998 | "to_URLAddress": { 999 | "type": "cds.Association", 1000 | "target": "API_BUSINESS_PARTNER.A_AddressHomePageURL", 1001 | "cardinality": { 1002 | "max": "*" 1003 | } 1004 | } 1005 | } 1006 | }, 1007 | "API_BUSINESS_PARTNER.A_BusinessPartnerBank": { 1008 | "kind": "entity", 1009 | "@cds.persistence.skip": true, 1010 | "elements": { 1011 | "BusinessPartner": { 1012 | "key": true, 1013 | "type": "cds.String", 1014 | "length": 10 1015 | }, 1016 | "BankIdentification": { 1017 | "key": true, 1018 | "type": "cds.String", 1019 | "length": 4 1020 | }, 1021 | "BankCountryKey": { 1022 | "type": "cds.String", 1023 | "length": 3 1024 | }, 1025 | "BankName": { 1026 | "type": "cds.String", 1027 | "length": 60 1028 | }, 1029 | "BankNumber": { 1030 | "type": "cds.String", 1031 | "length": 15 1032 | }, 1033 | "SWIFTCode": { 1034 | "type": "cds.String", 1035 | "length": 11 1036 | }, 1037 | "BankControlKey": { 1038 | "type": "cds.String", 1039 | "length": 2 1040 | }, 1041 | "BankAccountHolderName": { 1042 | "type": "cds.String", 1043 | "length": 60 1044 | }, 1045 | "BankAccountName": { 1046 | "type": "cds.String", 1047 | "length": 40 1048 | }, 1049 | "ValidityStartDate": { 1050 | "type": "cds.Timestamp" 1051 | }, 1052 | "ValidityEndDate": { 1053 | "type": "cds.Timestamp" 1054 | }, 1055 | "IBAN": { 1056 | "type": "cds.String", 1057 | "length": 34 1058 | }, 1059 | "IBANValidityStartDate": { 1060 | "type": "cds.Date" 1061 | }, 1062 | "BankAccount": { 1063 | "type": "cds.String", 1064 | "length": 18 1065 | }, 1066 | "BankAccountReferenceText": { 1067 | "type": "cds.String", 1068 | "length": 20 1069 | }, 1070 | "CollectionAuthInd": { 1071 | "type": "cds.Boolean" 1072 | }, 1073 | "CityName": { 1074 | "type": "cds.String", 1075 | "length": 35 1076 | }, 1077 | "AuthorizationGroup": { 1078 | "type": "cds.String", 1079 | "length": 4 1080 | } 1081 | } 1082 | }, 1083 | "API_BUSINESS_PARTNER.A_BusinessPartnerContact": { 1084 | "kind": "entity", 1085 | "@cds.persistence.skip": true, 1086 | "elements": { 1087 | "RelationshipNumber": { 1088 | "key": true, 1089 | "type": "cds.String", 1090 | "length": 12 1091 | }, 1092 | "BusinessPartnerCompany": { 1093 | "key": true, 1094 | "type": "cds.String", 1095 | "length": 10 1096 | }, 1097 | "BusinessPartnerPerson": { 1098 | "key": true, 1099 | "type": "cds.String", 1100 | "length": 10 1101 | }, 1102 | "ValidityEndDate": { 1103 | "key": true, 1104 | "type": "cds.Date" 1105 | }, 1106 | "ValidityStartDate": { 1107 | "type": "cds.Date" 1108 | }, 1109 | "IsStandardRelationship": { 1110 | "type": "cds.Boolean" 1111 | }, 1112 | "RelationshipCategory": { 1113 | "type": "cds.String", 1114 | "length": 6 1115 | }, 1116 | "to_ContactAddress": { 1117 | "type": "cds.Association", 1118 | "target": "API_BUSINESS_PARTNER.A_BPContactToAddress", 1119 | "cardinality": { 1120 | "max": "*" 1121 | } 1122 | }, 1123 | "to_ContactRelationship": { 1124 | "type": "cds.Association", 1125 | "target": "API_BUSINESS_PARTNER.A_BPContactToFuncAndDept" 1126 | } 1127 | } 1128 | }, 1129 | "API_BUSINESS_PARTNER.A_BusinessPartnerRole": { 1130 | "kind": "entity", 1131 | "@cds.persistence.skip": true, 1132 | "elements": { 1133 | "BusinessPartner": { 1134 | "key": true, 1135 | "type": "cds.String", 1136 | "length": 10 1137 | }, 1138 | "BusinessPartnerRole": { 1139 | "key": true, 1140 | "type": "cds.String", 1141 | "length": 6 1142 | }, 1143 | "ValidFrom": { 1144 | "type": "cds.Timestamp" 1145 | }, 1146 | "ValidTo": { 1147 | "type": "cds.Timestamp" 1148 | }, 1149 | "AuthorizationGroup": { 1150 | "type": "cds.String", 1151 | "length": 4 1152 | } 1153 | } 1154 | }, 1155 | "API_BUSINESS_PARTNER.A_BusinessPartnerTaxNumber": { 1156 | "kind": "entity", 1157 | "@cds.persistence.skip": true, 1158 | "elements": { 1159 | "BusinessPartner": { 1160 | "key": true, 1161 | "type": "cds.String", 1162 | "length": 10 1163 | }, 1164 | "BPTaxType": { 1165 | "key": true, 1166 | "type": "cds.String", 1167 | "length": 4 1168 | }, 1169 | "BPTaxNumber": { 1170 | "type": "cds.String", 1171 | "length": 20 1172 | }, 1173 | "BPTaxLongNumber": { 1174 | "type": "cds.String", 1175 | "length": 60 1176 | }, 1177 | "AuthorizationGroup": { 1178 | "type": "cds.String", 1179 | "length": 4 1180 | } 1181 | } 1182 | }, 1183 | "API_BUSINESS_PARTNER.A_Customer": { 1184 | "kind": "entity", 1185 | "@cds.persistence.skip": true, 1186 | "elements": { 1187 | "Customer": { 1188 | "key": true, 1189 | "type": "cds.String", 1190 | "length": 10 1191 | }, 1192 | "AuthorizationGroup": { 1193 | "type": "cds.String", 1194 | "length": 4 1195 | }, 1196 | "BillingIsBlockedForCustomer": { 1197 | "type": "cds.String", 1198 | "length": 2 1199 | }, 1200 | "CreatedByUser": { 1201 | "type": "cds.String", 1202 | "length": 12 1203 | }, 1204 | "CreationDate": { 1205 | "type": "cds.Date" 1206 | }, 1207 | "CustomerAccountGroup": { 1208 | "type": "cds.String", 1209 | "length": 4 1210 | }, 1211 | "CustomerClassification": { 1212 | "type": "cds.String", 1213 | "length": 2 1214 | }, 1215 | "CustomerFullName": { 1216 | "type": "cds.String", 1217 | "length": 220 1218 | }, 1219 | "CustomerName": { 1220 | "type": "cds.String", 1221 | "length": 80 1222 | }, 1223 | "DeliveryIsBlocked": { 1224 | "type": "cds.String", 1225 | "length": 2 1226 | }, 1227 | "NFPartnerIsNaturalPerson": { 1228 | "type": "cds.String", 1229 | "length": 1 1230 | }, 1231 | "OrderIsBlockedForCustomer": { 1232 | "type": "cds.String", 1233 | "length": 2 1234 | }, 1235 | "PostingIsBlocked": { 1236 | "type": "cds.Boolean" 1237 | }, 1238 | "Supplier": { 1239 | "type": "cds.String", 1240 | "length": 10 1241 | }, 1242 | "CustomerCorporateGroup": { 1243 | "type": "cds.String", 1244 | "length": 10 1245 | }, 1246 | "FiscalAddress": { 1247 | "type": "cds.String", 1248 | "length": 10 1249 | }, 1250 | "Industry": { 1251 | "type": "cds.String", 1252 | "length": 4 1253 | }, 1254 | "IndustryCode1": { 1255 | "type": "cds.String", 1256 | "length": 10 1257 | }, 1258 | "IndustryCode2": { 1259 | "type": "cds.String", 1260 | "length": 10 1261 | }, 1262 | "IndustryCode3": { 1263 | "type": "cds.String", 1264 | "length": 10 1265 | }, 1266 | "IndustryCode4": { 1267 | "type": "cds.String", 1268 | "length": 10 1269 | }, 1270 | "IndustryCode5": { 1271 | "type": "cds.String", 1272 | "length": 10 1273 | }, 1274 | "InternationalLocationNumber1": { 1275 | "type": "cds.String", 1276 | "length": 7 1277 | }, 1278 | "NielsenRegion": { 1279 | "type": "cds.String", 1280 | "length": 2 1281 | }, 1282 | "ResponsibleType": { 1283 | "type": "cds.String", 1284 | "length": 2 1285 | }, 1286 | "TaxNumber1": { 1287 | "type": "cds.String", 1288 | "length": 16 1289 | }, 1290 | "TaxNumber2": { 1291 | "type": "cds.String", 1292 | "length": 11 1293 | }, 1294 | "TaxNumber3": { 1295 | "type": "cds.String", 1296 | "length": 18 1297 | }, 1298 | "TaxNumber4": { 1299 | "type": "cds.String", 1300 | "length": 18 1301 | }, 1302 | "TaxNumber5": { 1303 | "type": "cds.String", 1304 | "length": 60 1305 | }, 1306 | "TaxNumberType": { 1307 | "type": "cds.String", 1308 | "length": 2 1309 | }, 1310 | "VATRegistration": { 1311 | "type": "cds.String", 1312 | "length": 20 1313 | }, 1314 | "DeletionIndicator": { 1315 | "type": "cds.Boolean" 1316 | }, 1317 | "to_CustomerCompany": { 1318 | "type": "cds.Association", 1319 | "target": "API_BUSINESS_PARTNER.A_CustomerCompany", 1320 | "cardinality": { 1321 | "max": "*" 1322 | } 1323 | }, 1324 | "to_CustomerSalesArea": { 1325 | "type": "cds.Association", 1326 | "target": "API_BUSINESS_PARTNER.A_CustomerSalesArea", 1327 | "cardinality": { 1328 | "max": "*" 1329 | } 1330 | } 1331 | } 1332 | }, 1333 | "API_BUSINESS_PARTNER.A_CustomerCompany": { 1334 | "kind": "entity", 1335 | "@cds.persistence.skip": true, 1336 | "elements": { 1337 | "Customer": { 1338 | "key": true, 1339 | "type": "cds.String", 1340 | "length": 10 1341 | }, 1342 | "CompanyCode": { 1343 | "key": true, 1344 | "type": "cds.String", 1345 | "length": 4 1346 | }, 1347 | "APARToleranceGroup": { 1348 | "type": "cds.String", 1349 | "length": 4 1350 | }, 1351 | "AccountByCustomer": { 1352 | "type": "cds.String", 1353 | "length": 12 1354 | }, 1355 | "AccountingClerk": { 1356 | "type": "cds.String", 1357 | "length": 2 1358 | }, 1359 | "AccountingClerkFaxNumber": { 1360 | "type": "cds.String", 1361 | "length": 31 1362 | }, 1363 | "AccountingClerkInternetAddress": { 1364 | "type": "cds.String", 1365 | "length": 130 1366 | }, 1367 | "AccountingClerkPhoneNumber": { 1368 | "type": "cds.String", 1369 | "length": 30 1370 | }, 1371 | "AlternativePayerAccount": { 1372 | "type": "cds.String", 1373 | "length": 10 1374 | }, 1375 | "AuthorizationGroup": { 1376 | "type": "cds.String", 1377 | "length": 4 1378 | }, 1379 | "CollectiveInvoiceVariant": { 1380 | "type": "cds.String", 1381 | "length": 1 1382 | }, 1383 | "CustomerAccountNote": { 1384 | "type": "cds.String", 1385 | "length": 30 1386 | }, 1387 | "CustomerHeadOffice": { 1388 | "type": "cds.String", 1389 | "length": 10 1390 | }, 1391 | "CustomerSupplierClearingIsUsed": { 1392 | "type": "cds.Boolean" 1393 | }, 1394 | "HouseBank": { 1395 | "type": "cds.String", 1396 | "length": 5 1397 | }, 1398 | "InterestCalculationCode": { 1399 | "type": "cds.String", 1400 | "length": 2 1401 | }, 1402 | "InterestCalculationDate": { 1403 | "type": "cds.Date" 1404 | }, 1405 | "IntrstCalcFrequencyInMonths": { 1406 | "type": "cds.String", 1407 | "length": 2 1408 | }, 1409 | "IsToBeLocallyProcessed": { 1410 | "type": "cds.Boolean" 1411 | }, 1412 | "ItemIsToBePaidSeparately": { 1413 | "type": "cds.Boolean" 1414 | }, 1415 | "LayoutSortingRule": { 1416 | "type": "cds.String", 1417 | "length": 3 1418 | }, 1419 | "PaymentBlockingReason": { 1420 | "type": "cds.String", 1421 | "length": 1 1422 | }, 1423 | "PaymentMethodsList": { 1424 | "type": "cds.String", 1425 | "length": 10 1426 | }, 1427 | "PaymentTerms": { 1428 | "type": "cds.String", 1429 | "length": 4 1430 | }, 1431 | "PaytAdviceIsSentbyEDI": { 1432 | "type": "cds.Boolean" 1433 | }, 1434 | "PhysicalInventoryBlockInd": { 1435 | "type": "cds.Boolean" 1436 | }, 1437 | "ReconciliationAccount": { 1438 | "type": "cds.String", 1439 | "length": 10 1440 | }, 1441 | "RecordPaymentHistoryIndicator": { 1442 | "type": "cds.Boolean" 1443 | }, 1444 | "UserAtCustomer": { 1445 | "type": "cds.String", 1446 | "length": 15 1447 | }, 1448 | "DeletionIndicator": { 1449 | "type": "cds.Boolean" 1450 | }, 1451 | "CustomerAccountGroup": { 1452 | "type": "cds.String", 1453 | "length": 4 1454 | }, 1455 | "to_CustomerDunning": { 1456 | "type": "cds.Association", 1457 | "target": "API_BUSINESS_PARTNER.A_CustomerDunning", 1458 | "cardinality": { 1459 | "max": "*" 1460 | } 1461 | }, 1462 | "to_WithHoldingTax": { 1463 | "type": "cds.Association", 1464 | "target": "API_BUSINESS_PARTNER.A_CustomerWithHoldingTax", 1465 | "cardinality": { 1466 | "max": "*" 1467 | } 1468 | } 1469 | } 1470 | }, 1471 | "API_BUSINESS_PARTNER.A_CustomerDunning": { 1472 | "kind": "entity", 1473 | "@cds.persistence.skip": true, 1474 | "elements": { 1475 | "Customer": { 1476 | "key": true, 1477 | "type": "cds.String", 1478 | "length": 10 1479 | }, 1480 | "CompanyCode": { 1481 | "key": true, 1482 | "type": "cds.String", 1483 | "length": 4 1484 | }, 1485 | "DunningArea": { 1486 | "key": true, 1487 | "type": "cds.String", 1488 | "length": 2 1489 | }, 1490 | "DunningBlock": { 1491 | "type": "cds.String", 1492 | "length": 1 1493 | }, 1494 | "DunningLevel": { 1495 | "type": "cds.String", 1496 | "length": 1 1497 | }, 1498 | "DunningProcedure": { 1499 | "type": "cds.String", 1500 | "length": 4 1501 | }, 1502 | "DunningRecipient": { 1503 | "type": "cds.String", 1504 | "length": 10 1505 | }, 1506 | "LastDunnedOn": { 1507 | "type": "cds.Date" 1508 | }, 1509 | "LegDunningProcedureOn": { 1510 | "type": "cds.Date" 1511 | }, 1512 | "DunningClerk": { 1513 | "type": "cds.String", 1514 | "length": 2 1515 | }, 1516 | "AuthorizationGroup": { 1517 | "type": "cds.String", 1518 | "length": 4 1519 | }, 1520 | "CustomerAccountGroup": { 1521 | "type": "cds.String", 1522 | "length": 4 1523 | } 1524 | } 1525 | }, 1526 | "API_BUSINESS_PARTNER.A_CustomerSalesArea": { 1527 | "kind": "entity", 1528 | "@cds.persistence.skip": true, 1529 | "elements": { 1530 | "Customer": { 1531 | "key": true, 1532 | "type": "cds.String", 1533 | "length": 10 1534 | }, 1535 | "SalesOrganization": { 1536 | "key": true, 1537 | "type": "cds.String", 1538 | "length": 4 1539 | }, 1540 | "DistributionChannel": { 1541 | "key": true, 1542 | "type": "cds.String", 1543 | "length": 2 1544 | }, 1545 | "Division": { 1546 | "key": true, 1547 | "type": "cds.String", 1548 | "length": 2 1549 | }, 1550 | "AccountByCustomer": { 1551 | "type": "cds.String", 1552 | "length": 12 1553 | }, 1554 | "AuthorizationGroup": { 1555 | "type": "cds.String", 1556 | "length": 4 1557 | }, 1558 | "BillingIsBlockedForCustomer": { 1559 | "type": "cds.String", 1560 | "length": 2 1561 | }, 1562 | "CompleteDeliveryIsDefined": { 1563 | "type": "cds.Boolean" 1564 | }, 1565 | "Currency": { 1566 | "type": "cds.String", 1567 | "length": 5 1568 | }, 1569 | "CustomerABCClassification": { 1570 | "type": "cds.String", 1571 | "length": 2 1572 | }, 1573 | "CustomerAccountAssignmentGroup": { 1574 | "type": "cds.String", 1575 | "length": 2 1576 | }, 1577 | "CustomerGroup": { 1578 | "type": "cds.String", 1579 | "length": 2 1580 | }, 1581 | "CustomerPaymentTerms": { 1582 | "type": "cds.String", 1583 | "length": 4 1584 | }, 1585 | "CustomerPriceGroup": { 1586 | "type": "cds.String", 1587 | "length": 2 1588 | }, 1589 | "CustomerPricingProcedure": { 1590 | "type": "cds.String", 1591 | "length": 2 1592 | }, 1593 | "DeliveryIsBlockedForCustomer": { 1594 | "type": "cds.String", 1595 | "length": 2 1596 | }, 1597 | "DeliveryPriority": { 1598 | "type": "cds.String", 1599 | "length": 2 1600 | }, 1601 | "IncotermsClassification": { 1602 | "type": "cds.String", 1603 | "length": 3 1604 | }, 1605 | "IncotermsLocation2": { 1606 | "type": "cds.String", 1607 | "length": 70 1608 | }, 1609 | "IncotermsVersion": { 1610 | "type": "cds.String", 1611 | "length": 4 1612 | }, 1613 | "IncotermsLocation1": { 1614 | "type": "cds.String", 1615 | "length": 70 1616 | }, 1617 | "DeletionIndicator": { 1618 | "type": "cds.Boolean" 1619 | }, 1620 | "IncotermsTransferLocation": { 1621 | "type": "cds.String", 1622 | "length": 28 1623 | }, 1624 | "InvoiceDate": { 1625 | "type": "cds.String", 1626 | "length": 2 1627 | }, 1628 | "ItemOrderProbabilityInPercent": { 1629 | "type": "cds.String", 1630 | "length": 3 1631 | }, 1632 | "OrderCombinationIsAllowed": { 1633 | "type": "cds.Boolean" 1634 | }, 1635 | "OrderIsBlockedForCustomer": { 1636 | "type": "cds.String", 1637 | "length": 2 1638 | }, 1639 | "PartialDeliveryIsAllowed": { 1640 | "type": "cds.String", 1641 | "length": 1 1642 | }, 1643 | "PriceListType": { 1644 | "type": "cds.String", 1645 | "length": 2 1646 | }, 1647 | "SalesGroup": { 1648 | "type": "cds.String", 1649 | "length": 3 1650 | }, 1651 | "SalesOffice": { 1652 | "type": "cds.String", 1653 | "length": 4 1654 | }, 1655 | "ShippingCondition": { 1656 | "type": "cds.String", 1657 | "length": 2 1658 | }, 1659 | "SupplyingPlant": { 1660 | "type": "cds.String", 1661 | "length": 4 1662 | }, 1663 | "SalesDistrict": { 1664 | "type": "cds.String", 1665 | "length": 6 1666 | }, 1667 | "CustomerAccountGroup": { 1668 | "type": "cds.String", 1669 | "length": 4 1670 | }, 1671 | "to_PartnerFunction": { 1672 | "type": "cds.Association", 1673 | "target": "API_BUSINESS_PARTNER.A_CustSalesPartnerFunc", 1674 | "cardinality": { 1675 | "max": "*" 1676 | } 1677 | }, 1678 | "to_SalesAreaTax": { 1679 | "type": "cds.Association", 1680 | "target": "API_BUSINESS_PARTNER.A_CustomerSalesAreaTax", 1681 | "cardinality": { 1682 | "max": "*" 1683 | } 1684 | } 1685 | } 1686 | }, 1687 | "API_BUSINESS_PARTNER.A_CustomerSalesAreaTax": { 1688 | "kind": "entity", 1689 | "@cds.persistence.skip": true, 1690 | "elements": { 1691 | "Customer": { 1692 | "key": true, 1693 | "type": "cds.String", 1694 | "length": 10 1695 | }, 1696 | "SalesOrganization": { 1697 | "key": true, 1698 | "type": "cds.String", 1699 | "length": 4 1700 | }, 1701 | "DistributionChannel": { 1702 | "key": true, 1703 | "type": "cds.String", 1704 | "length": 2 1705 | }, 1706 | "Division": { 1707 | "key": true, 1708 | "type": "cds.String", 1709 | "length": 2 1710 | }, 1711 | "DepartureCountry": { 1712 | "key": true, 1713 | "type": "cds.String", 1714 | "length": 3 1715 | }, 1716 | "CustomerTaxCategory": { 1717 | "key": true, 1718 | "type": "cds.String", 1719 | "length": 4 1720 | }, 1721 | "CustomerTaxClassification": { 1722 | "type": "cds.String", 1723 | "length": 1 1724 | } 1725 | } 1726 | }, 1727 | "API_BUSINESS_PARTNER.A_CustomerWithHoldingTax": { 1728 | "kind": "entity", 1729 | "@cds.persistence.skip": true, 1730 | "elements": { 1731 | "Customer": { 1732 | "key": true, 1733 | "type": "cds.String", 1734 | "length": 10 1735 | }, 1736 | "CompanyCode": { 1737 | "key": true, 1738 | "type": "cds.String", 1739 | "length": 4 1740 | }, 1741 | "WithholdingTaxType": { 1742 | "key": true, 1743 | "type": "cds.String", 1744 | "length": 2 1745 | }, 1746 | "WithholdingTaxCode": { 1747 | "type": "cds.String", 1748 | "length": 2 1749 | }, 1750 | "WithholdingTaxAgent": { 1751 | "type": "cds.Boolean" 1752 | }, 1753 | "ObligationDateBegin": { 1754 | "type": "cds.Date" 1755 | }, 1756 | "ObligationDateEnd": { 1757 | "type": "cds.Date" 1758 | }, 1759 | "WithholdingTaxNumber": { 1760 | "type": "cds.String", 1761 | "length": 16 1762 | }, 1763 | "WithholdingTaxCertificate": { 1764 | "type": "cds.String", 1765 | "length": 25 1766 | }, 1767 | "WithholdingTaxExmptPercent": { 1768 | "type": "cds.Decimal", 1769 | "precision": 5, 1770 | "scale": 2 1771 | }, 1772 | "ExemptionDateBegin": { 1773 | "type": "cds.Date" 1774 | }, 1775 | "ExemptionDateEnd": { 1776 | "type": "cds.Date" 1777 | }, 1778 | "ExemptionReason": { 1779 | "type": "cds.String", 1780 | "length": 2 1781 | }, 1782 | "AuthorizationGroup": { 1783 | "type": "cds.String", 1784 | "length": 4 1785 | } 1786 | } 1787 | }, 1788 | "API_BUSINESS_PARTNER.A_CustSalesPartnerFunc": { 1789 | "kind": "entity", 1790 | "@cds.persistence.skip": true, 1791 | "elements": { 1792 | "Customer": { 1793 | "key": true, 1794 | "type": "cds.String", 1795 | "length": 10 1796 | }, 1797 | "SalesOrganization": { 1798 | "key": true, 1799 | "type": "cds.String", 1800 | "length": 4 1801 | }, 1802 | "DistributionChannel": { 1803 | "key": true, 1804 | "type": "cds.String", 1805 | "length": 2 1806 | }, 1807 | "Division": { 1808 | "key": true, 1809 | "type": "cds.String", 1810 | "length": 2 1811 | }, 1812 | "PartnerCounter": { 1813 | "key": true, 1814 | "type": "cds.String", 1815 | "length": 3 1816 | }, 1817 | "PartnerFunction": { 1818 | "key": true, 1819 | "type": "cds.String", 1820 | "length": 2 1821 | }, 1822 | "BPCustomerNumber": { 1823 | "type": "cds.String", 1824 | "length": 10 1825 | }, 1826 | "CustomerPartnerDescription": { 1827 | "type": "cds.String", 1828 | "length": 30 1829 | }, 1830 | "DefaultPartner": { 1831 | "type": "cds.Boolean" 1832 | }, 1833 | "AuthorizationGroup": { 1834 | "type": "cds.String", 1835 | "length": 4 1836 | } 1837 | } 1838 | }, 1839 | "API_BUSINESS_PARTNER.A_Supplier": { 1840 | "kind": "entity", 1841 | "@cds.persistence.skip": true, 1842 | "elements": { 1843 | "Supplier": { 1844 | "key": true, 1845 | "type": "cds.String", 1846 | "length": 10 1847 | }, 1848 | "AlternativePayeeAccountNumber": { 1849 | "type": "cds.String", 1850 | "length": 10 1851 | }, 1852 | "AuthorizationGroup": { 1853 | "type": "cds.String", 1854 | "length": 4 1855 | }, 1856 | "CreatedByUser": { 1857 | "type": "cds.String", 1858 | "length": 12 1859 | }, 1860 | "CreationDate": { 1861 | "type": "cds.Date" 1862 | }, 1863 | "Customer": { 1864 | "type": "cds.String", 1865 | "length": 10 1866 | }, 1867 | "PaymentIsBlockedForSupplier": { 1868 | "type": "cds.Boolean" 1869 | }, 1870 | "PostingIsBlocked": { 1871 | "type": "cds.Boolean" 1872 | }, 1873 | "PurchasingIsBlocked": { 1874 | "type": "cds.Boolean" 1875 | }, 1876 | "SupplierAccountGroup": { 1877 | "type": "cds.String", 1878 | "length": 4 1879 | }, 1880 | "SupplierFullName": { 1881 | "type": "cds.String", 1882 | "length": 220 1883 | }, 1884 | "SupplierName": { 1885 | "type": "cds.String", 1886 | "length": 80 1887 | }, 1888 | "VATRegistration": { 1889 | "type": "cds.String", 1890 | "length": 20 1891 | }, 1892 | "BirthDate": { 1893 | "type": "cds.Date" 1894 | }, 1895 | "ConcatenatedInternationalLocNo": { 1896 | "type": "cds.String", 1897 | "length": 20 1898 | }, 1899 | "DeletionIndicator": { 1900 | "type": "cds.Boolean" 1901 | }, 1902 | "FiscalAddress": { 1903 | "type": "cds.String", 1904 | "length": 10 1905 | }, 1906 | "Industry": { 1907 | "type": "cds.String", 1908 | "length": 4 1909 | }, 1910 | "InternationalLocationNumber1": { 1911 | "type": "cds.String", 1912 | "length": 7 1913 | }, 1914 | "InternationalLocationNumber2": { 1915 | "type": "cds.String", 1916 | "length": 5 1917 | }, 1918 | "InternationalLocationNumber3": { 1919 | "type": "cds.String", 1920 | "length": 1 1921 | }, 1922 | "IsNaturalPerson": { 1923 | "type": "cds.String", 1924 | "length": 1 1925 | }, 1926 | "ResponsibleType": { 1927 | "type": "cds.String", 1928 | "length": 2 1929 | }, 1930 | "SuplrQltyInProcmtCertfnValidTo": { 1931 | "type": "cds.Date" 1932 | }, 1933 | "SuplrQualityManagementSystem": { 1934 | "type": "cds.String", 1935 | "length": 4 1936 | }, 1937 | "SupplierCorporateGroup": { 1938 | "type": "cds.String", 1939 | "length": 10 1940 | }, 1941 | "SupplierProcurementBlock": { 1942 | "type": "cds.String", 1943 | "length": 2 1944 | }, 1945 | "TaxNumber1": { 1946 | "type": "cds.String", 1947 | "length": 16 1948 | }, 1949 | "TaxNumber2": { 1950 | "type": "cds.String", 1951 | "length": 11 1952 | }, 1953 | "TaxNumber3": { 1954 | "type": "cds.String", 1955 | "length": 18 1956 | }, 1957 | "TaxNumber4": { 1958 | "type": "cds.String", 1959 | "length": 18 1960 | }, 1961 | "TaxNumber5": { 1962 | "type": "cds.String", 1963 | "length": 60 1964 | }, 1965 | "TaxNumberResponsible": { 1966 | "type": "cds.String", 1967 | "length": 18 1968 | }, 1969 | "TaxNumberType": { 1970 | "type": "cds.String", 1971 | "length": 2 1972 | }, 1973 | "to_SupplierCompany": { 1974 | "type": "cds.Association", 1975 | "target": "API_BUSINESS_PARTNER.A_SupplierCompany", 1976 | "cardinality": { 1977 | "max": "*" 1978 | } 1979 | }, 1980 | "to_SupplierPurchasingOrg": { 1981 | "type": "cds.Association", 1982 | "target": "API_BUSINESS_PARTNER.A_SupplierPurchasingOrg", 1983 | "cardinality": { 1984 | "max": "*" 1985 | } 1986 | } 1987 | } 1988 | }, 1989 | "API_BUSINESS_PARTNER.A_SupplierCompany": { 1990 | "kind": "entity", 1991 | "@cds.persistence.skip": true, 1992 | "elements": { 1993 | "Supplier": { 1994 | "key": true, 1995 | "type": "cds.String", 1996 | "length": 10 1997 | }, 1998 | "CompanyCode": { 1999 | "key": true, 2000 | "type": "cds.String", 2001 | "length": 4 2002 | }, 2003 | "AuthorizationGroup": { 2004 | "type": "cds.String", 2005 | "length": 4 2006 | }, 2007 | "CompanyCodeName": { 2008 | "type": "cds.String", 2009 | "length": 25 2010 | }, 2011 | "PaymentBlockingReason": { 2012 | "type": "cds.String", 2013 | "length": 1 2014 | }, 2015 | "SupplierIsBlockedForPosting": { 2016 | "type": "cds.Boolean" 2017 | }, 2018 | "AccountingClerk": { 2019 | "type": "cds.String", 2020 | "length": 2 2021 | }, 2022 | "AccountingClerkFaxNumber": { 2023 | "type": "cds.String", 2024 | "length": 31 2025 | }, 2026 | "AccountingClerkPhoneNumber": { 2027 | "type": "cds.String", 2028 | "length": 30 2029 | }, 2030 | "SupplierClerk": { 2031 | "type": "cds.String", 2032 | "length": 15 2033 | }, 2034 | "SupplierClerkURL": { 2035 | "type": "cds.String", 2036 | "length": 130 2037 | }, 2038 | "PaymentMethodsList": { 2039 | "type": "cds.String", 2040 | "length": 10 2041 | }, 2042 | "PaymentTerms": { 2043 | "type": "cds.String", 2044 | "length": 4 2045 | }, 2046 | "ClearCustomerSupplier": { 2047 | "type": "cds.Boolean" 2048 | }, 2049 | "IsToBeLocallyProcessed": { 2050 | "type": "cds.Boolean" 2051 | }, 2052 | "ItemIsToBePaidSeparately": { 2053 | "type": "cds.Boolean" 2054 | }, 2055 | "PaymentIsToBeSentByEDI": { 2056 | "type": "cds.Boolean" 2057 | }, 2058 | "HouseBank": { 2059 | "type": "cds.String", 2060 | "length": 5 2061 | }, 2062 | "CheckPaidDurationInDays": { 2063 | "type": "cds.Decimal", 2064 | "precision": 3, 2065 | "scale": 0 2066 | }, 2067 | "BillOfExchLmtAmtInCoCodeCrcy": { 2068 | "type": "cds.Decimal", 2069 | "precision": 14, 2070 | "scale": 3 2071 | }, 2072 | "SupplierClerkIDBySupplier": { 2073 | "type": "cds.String", 2074 | "length": 12 2075 | }, 2076 | "ReconciliationAccount": { 2077 | "type": "cds.String", 2078 | "length": 10 2079 | }, 2080 | "InterestCalculationCode": { 2081 | "type": "cds.String", 2082 | "length": 2 2083 | }, 2084 | "InterestCalculationDate": { 2085 | "type": "cds.Date" 2086 | }, 2087 | "IntrstCalcFrequencyInMonths": { 2088 | "type": "cds.String", 2089 | "length": 2 2090 | }, 2091 | "SupplierHeadOffice": { 2092 | "type": "cds.String", 2093 | "length": 10 2094 | }, 2095 | "AlternativePayee": { 2096 | "type": "cds.String", 2097 | "length": 10 2098 | }, 2099 | "LayoutSortingRule": { 2100 | "type": "cds.String", 2101 | "length": 3 2102 | }, 2103 | "APARToleranceGroup": { 2104 | "type": "cds.String", 2105 | "length": 4 2106 | }, 2107 | "SupplierCertificationDate": { 2108 | "type": "cds.Date" 2109 | }, 2110 | "SupplierAccountNote": { 2111 | "type": "cds.String", 2112 | "length": 30 2113 | }, 2114 | "WithholdingTaxCountry": { 2115 | "type": "cds.String", 2116 | "length": 3 2117 | }, 2118 | "DeletionIndicator": { 2119 | "type": "cds.Boolean" 2120 | }, 2121 | "CashPlanningGroup": { 2122 | "type": "cds.String", 2123 | "length": 10 2124 | }, 2125 | "IsToBeCheckedForDuplicates": { 2126 | "type": "cds.Boolean" 2127 | }, 2128 | "SupplierAccountGroup": { 2129 | "type": "cds.String", 2130 | "length": 4 2131 | }, 2132 | "to_SupplierDunning": { 2133 | "type": "cds.Association", 2134 | "target": "API_BUSINESS_PARTNER.A_SupplierDunning", 2135 | "cardinality": { 2136 | "max": "*" 2137 | } 2138 | }, 2139 | "to_SupplierWithHoldingTax": { 2140 | "type": "cds.Association", 2141 | "target": "API_BUSINESS_PARTNER.A_SupplierWithHoldingTax", 2142 | "cardinality": { 2143 | "max": "*" 2144 | } 2145 | } 2146 | } 2147 | }, 2148 | "API_BUSINESS_PARTNER.A_SupplierDunning": { 2149 | "kind": "entity", 2150 | "@cds.persistence.skip": true, 2151 | "elements": { 2152 | "Supplier": { 2153 | "key": true, 2154 | "type": "cds.String", 2155 | "length": 10 2156 | }, 2157 | "CompanyCode": { 2158 | "key": true, 2159 | "type": "cds.String", 2160 | "length": 4 2161 | }, 2162 | "DunningArea": { 2163 | "key": true, 2164 | "type": "cds.String", 2165 | "length": 2 2166 | }, 2167 | "DunningBlock": { 2168 | "type": "cds.String", 2169 | "length": 1 2170 | }, 2171 | "DunningLevel": { 2172 | "type": "cds.String", 2173 | "length": 1 2174 | }, 2175 | "DunningProcedure": { 2176 | "type": "cds.String", 2177 | "length": 4 2178 | }, 2179 | "DunningRecipient": { 2180 | "type": "cds.String", 2181 | "length": 10 2182 | }, 2183 | "LastDunnedOn": { 2184 | "type": "cds.Date" 2185 | }, 2186 | "LegDunningProcedureOn": { 2187 | "type": "cds.Date" 2188 | }, 2189 | "DunningClerk": { 2190 | "type": "cds.String", 2191 | "length": 2 2192 | }, 2193 | "AuthorizationGroup": { 2194 | "type": "cds.String", 2195 | "length": 4 2196 | }, 2197 | "SupplierAccountGroup": { 2198 | "type": "cds.String", 2199 | "length": 4 2200 | } 2201 | } 2202 | }, 2203 | "API_BUSINESS_PARTNER.A_SupplierPartnerFunc": { 2204 | "kind": "entity", 2205 | "@cds.persistence.skip": true, 2206 | "elements": { 2207 | "Supplier": { 2208 | "key": true, 2209 | "type": "cds.String", 2210 | "length": 10 2211 | }, 2212 | "PurchasingOrganization": { 2213 | "key": true, 2214 | "type": "cds.String", 2215 | "length": 4 2216 | }, 2217 | "SupplierSubrange": { 2218 | "key": true, 2219 | "type": "cds.String", 2220 | "length": 6 2221 | }, 2222 | "Plant": { 2223 | "key": true, 2224 | "type": "cds.String", 2225 | "length": 4 2226 | }, 2227 | "PartnerFunction": { 2228 | "key": true, 2229 | "type": "cds.String", 2230 | "length": 2 2231 | }, 2232 | "PartnerCounter": { 2233 | "key": true, 2234 | "type": "cds.String", 2235 | "length": 3 2236 | }, 2237 | "DefaultPartner": { 2238 | "type": "cds.Boolean" 2239 | }, 2240 | "CreationDate": { 2241 | "type": "cds.Date" 2242 | }, 2243 | "CreatedByUser": { 2244 | "type": "cds.String", 2245 | "length": 12 2246 | }, 2247 | "ReferenceSupplier": { 2248 | "type": "cds.String", 2249 | "length": 10 2250 | }, 2251 | "AuthorizationGroup": { 2252 | "type": "cds.String", 2253 | "length": 4 2254 | } 2255 | } 2256 | }, 2257 | "API_BUSINESS_PARTNER.A_SupplierPurchasingOrg": { 2258 | "kind": "entity", 2259 | "@cds.persistence.skip": true, 2260 | "elements": { 2261 | "Supplier": { 2262 | "key": true, 2263 | "type": "cds.String", 2264 | "length": 10 2265 | }, 2266 | "PurchasingOrganization": { 2267 | "key": true, 2268 | "type": "cds.String", 2269 | "length": 4 2270 | }, 2271 | "CalculationSchemaGroupCode": { 2272 | "type": "cds.String", 2273 | "length": 2 2274 | }, 2275 | "DeletionIndicator": { 2276 | "type": "cds.Boolean" 2277 | }, 2278 | "IncotermsClassification": { 2279 | "type": "cds.String", 2280 | "length": 3 2281 | }, 2282 | "IncotermsTransferLocation": { 2283 | "type": "cds.String", 2284 | "length": 28 2285 | }, 2286 | "IncotermsVersion": { 2287 | "type": "cds.String", 2288 | "length": 4 2289 | }, 2290 | "IncotermsLocation1": { 2291 | "type": "cds.String", 2292 | "length": 70 2293 | }, 2294 | "IncotermsLocation2": { 2295 | "type": "cds.String", 2296 | "length": 70 2297 | }, 2298 | "InvoiceIsGoodsReceiptBased": { 2299 | "type": "cds.Boolean" 2300 | }, 2301 | "MaterialPlannedDeliveryDurn": { 2302 | "type": "cds.Decimal", 2303 | "precision": 3, 2304 | "scale": 0 2305 | }, 2306 | "MinimumOrderAmount": { 2307 | "type": "cds.Decimal", 2308 | "precision": 14, 2309 | "scale": 3 2310 | }, 2311 | "PaymentTerms": { 2312 | "type": "cds.String", 2313 | "length": 4 2314 | }, 2315 | "PricingDateControl": { 2316 | "type": "cds.String", 2317 | "length": 1 2318 | }, 2319 | "PurOrdAutoGenerationIsAllowed": { 2320 | "type": "cds.Boolean" 2321 | }, 2322 | "PurchaseOrderCurrency": { 2323 | "type": "cds.String", 2324 | "length": 5 2325 | }, 2326 | "PurchasingGroup": { 2327 | "type": "cds.String", 2328 | "length": 3 2329 | }, 2330 | "PurchasingIsBlockedForSupplier": { 2331 | "type": "cds.Boolean" 2332 | }, 2333 | "ShippingCondition": { 2334 | "type": "cds.String", 2335 | "length": 2 2336 | }, 2337 | "SupplierABCClassificationCode": { 2338 | "type": "cds.String", 2339 | "length": 1 2340 | }, 2341 | "SupplierPhoneNumber": { 2342 | "type": "cds.String", 2343 | "length": 16 2344 | }, 2345 | "SupplierRespSalesPersonName": { 2346 | "type": "cds.String", 2347 | "length": 30 2348 | }, 2349 | "AuthorizationGroup": { 2350 | "type": "cds.String", 2351 | "length": 4 2352 | }, 2353 | "SupplierAccountGroup": { 2354 | "type": "cds.String", 2355 | "length": 4 2356 | }, 2357 | "to_PartnerFunction": { 2358 | "type": "cds.Association", 2359 | "target": "API_BUSINESS_PARTNER.A_SupplierPartnerFunc", 2360 | "cardinality": { 2361 | "max": "*" 2362 | } 2363 | } 2364 | } 2365 | }, 2366 | "API_BUSINESS_PARTNER.A_SupplierWithHoldingTax": { 2367 | "kind": "entity", 2368 | "@cds.persistence.skip": true, 2369 | "elements": { 2370 | "Supplier": { 2371 | "key": true, 2372 | "type": "cds.String", 2373 | "length": 10 2374 | }, 2375 | "CompanyCode": { 2376 | "key": true, 2377 | "type": "cds.String", 2378 | "length": 4 2379 | }, 2380 | "WithholdingTaxType": { 2381 | "key": true, 2382 | "type": "cds.String", 2383 | "length": 2 2384 | }, 2385 | "ExemptionDateBegin": { 2386 | "type": "cds.Date" 2387 | }, 2388 | "ExemptionDateEnd": { 2389 | "type": "cds.Date" 2390 | }, 2391 | "ExemptionReason": { 2392 | "type": "cds.String", 2393 | "length": 2 2394 | }, 2395 | "IsWithholdingTaxSubject": { 2396 | "type": "cds.Boolean" 2397 | }, 2398 | "RecipientType": { 2399 | "type": "cds.String", 2400 | "length": 2 2401 | }, 2402 | "WithholdingTaxCertificate": { 2403 | "type": "cds.String", 2404 | "length": 25 2405 | }, 2406 | "WithholdingTaxCode": { 2407 | "type": "cds.String", 2408 | "length": 2 2409 | }, 2410 | "WithholdingTaxExmptPercent": { 2411 | "type": "cds.Decimal", 2412 | "precision": 5, 2413 | "scale": 2 2414 | }, 2415 | "WithholdingTaxNumber": { 2416 | "type": "cds.String", 2417 | "length": 16 2418 | }, 2419 | "AuthorizationGroup": { 2420 | "type": "cds.String", 2421 | "length": 4 2422 | } 2423 | } 2424 | } 2425 | } 2426 | } --------------------------------------------------------------------------------