├── .gitignore ├── .reuse └── dep5 ├── Applications ├── author-readings-mt │ ├── .cdsrc.json │ ├── .npmrc │ ├── .vscode │ │ ├── extensions.json │ │ ├── launch.json │ │ ├── settings.json │ │ └── tasks.json │ ├── app │ │ ├── authorreadingmanager │ │ │ ├── README.md │ │ │ ├── annotations.cds │ │ │ ├── package.json │ │ │ ├── ui5-deploy.yaml │ │ │ ├── ui5.yaml │ │ │ ├── webapp │ │ │ │ ├── Component.js │ │ │ │ ├── i18n │ │ │ │ │ ├── i18n.properties │ │ │ │ │ └── i18n_de.properties │ │ │ │ ├── index.html │ │ │ │ ├── manifest.json │ │ │ │ └── test │ │ │ │ │ └── flpSandbox.html │ │ │ └── xs-app.json │ │ └── services.cds │ ├── approuter │ │ ├── package.json │ │ └── xs-app.json │ ├── broker │ │ ├── catalog.json │ │ └── package.json │ ├── db │ │ ├── data │ │ │ ├── sap.common-Currencies.csv │ │ │ ├── sap.common-Currencies_texts.csv │ │ │ ├── sap.samples.authorreadings-AuthorReadingStatusCodes.csv │ │ │ ├── sap.samples.authorreadings-AuthorReadingStatusCodes_texts.csv │ │ │ ├── sap.samples.authorreadings-AuthorReadings.csv │ │ │ ├── sap.samples.authorreadings-ParticipantStatusCodes.csv │ │ │ ├── sap.samples.authorreadings-ParticipantStatusCodes_texts.csv │ │ │ └── sap.samples.authorreadings-Participants.csv │ │ ├── entity-models.cds │ │ ├── i18n │ │ │ ├── i18n.properties │ │ │ └── i18n_de.properties │ │ ├── src │ │ │ └── .hdiconfig │ │ └── undeploy.json │ ├── external_resources │ │ ├── S4HC_API_ENTERPRISE_PROJECT_SRV_0002.edmx │ │ ├── S4HC_ENTPROJECTPROCESSINGSTATUS_0001.edmx │ │ ├── S4HC_ENTPROJECTPROFILECODE_0001.edmx │ │ ├── byd_khproject.edmx │ │ ├── byd_khproject_tech_user.edmx │ │ ├── c4p_ProjectService.edmx │ │ ├── c4p_TaskService.edmx │ │ └── package.json │ ├── mta.yaml │ ├── package.json │ ├── server.js │ ├── srv │ │ ├── connector-byd.js │ │ ├── connector-c4p.js │ │ ├── connector-s4hc.js │ │ ├── external │ │ │ ├── S4HC_API_ENTERPRISE_PROJECT_SRV_0002.cds │ │ │ ├── S4HC_API_ENTERPRISE_PROJECT_SRV_0002.edmx │ │ │ ├── S4HC_ENTPROJECTPROCESSINGSTATUS_0001.cds │ │ │ ├── S4HC_ENTPROJECTPROCESSINGSTATUS_0001.edmx │ │ │ ├── S4HC_ENTPROJECTPROFILECODE_0001.cds │ │ │ ├── S4HC_ENTPROJECTPROFILECODE_0001.edmx │ │ │ ├── byd_khproject.cds │ │ │ ├── byd_khproject.edmx │ │ │ ├── byd_khproject_tech_user.cds │ │ │ ├── byd_khproject_tech_user.edmx │ │ │ ├── c4p_ProjectService.cds │ │ │ ├── c4p_ProjectService.edmx │ │ │ ├── c4p_TaskService.cds │ │ │ └── c4p_TaskService.edmx │ │ ├── i18n │ │ │ ├── messages.properties │ │ │ └── messages_de.properties │ │ ├── reuse.js │ │ ├── service-auth.cds │ │ ├── service-implementation.js │ │ └── service-models.cds │ ├── test │ │ ├── authorreading.test.js │ │ └── index.js │ └── xs-security.json └── author-readings │ ├── .cdsrc.json │ ├── .npmrc │ ├── .vscode │ ├── extensions.json │ ├── launch.json │ ├── settings.json │ └── tasks.json │ ├── app │ ├── authorreadingmanager │ │ ├── README.md │ │ ├── annotations.cds │ │ ├── package.json │ │ ├── ui5-deploy.yaml │ │ ├── ui5.yaml │ │ ├── webapp │ │ │ ├── Component.js │ │ │ ├── i18n │ │ │ │ ├── i18n.properties │ │ │ │ └── i18n_de.properties │ │ │ ├── index.html │ │ │ ├── manifest.json │ │ │ └── test │ │ │ │ └── flpSandbox.html │ │ └── xs-app.json │ └── services.cds │ ├── db │ ├── data │ │ ├── sap.common-Currencies.csv │ │ ├── sap.common-Currencies_texts.csv │ │ ├── sap.samples.authorreadings-AuthorReadingStatusCodes.csv │ │ ├── sap.samples.authorreadings-AuthorReadingStatusCodes_texts.csv │ │ ├── sap.samples.authorreadings-AuthorReadings.csv │ │ ├── sap.samples.authorreadings-ParticipantStatusCodes.csv │ │ ├── sap.samples.authorreadings-ParticipantStatusCodes_texts.csv │ │ └── sap.samples.authorreadings-Participants.csv │ ├── entity-models.cds │ ├── i18n │ │ ├── i18n.properties │ │ └── i18n_de.properties │ ├── src │ │ └── .hdiconfig │ └── undeploy.json │ ├── event-mesh.json │ ├── external_resources │ ├── byd_khproject.edmx │ └── byd_khproject_tech_user.edmx │ ├── mta.yaml │ ├── package.json │ ├── server.js │ ├── srv │ ├── connector-byd.js │ ├── external │ │ ├── byd_khproject.cds │ │ ├── byd_khproject.edmx │ │ ├── byd_khproject_tech_user.cds │ │ └── byd_khproject_tech_user.edmx │ ├── i18n │ │ ├── messages.properties │ │ └── messages_de.properties │ ├── reuse.js │ ├── service-auth.cds │ ├── service-implementation.js │ ├── service-models.cds │ └── service-models_without_ERP-integration.backup │ ├── test │ ├── authorreading.test.js │ └── index.js │ └── xs-security.json ├── LICENSE ├── LICENSES └── Apache-2.0.txt ├── README.md └── Tutorials ├── 01-Prepare-BTP-Account.md ├── 02-Develop-Core-Application.md ├── 03-One-Off-Deployment.md ├── 04-ByD-Integration.md ├── 05-ByD-Event-Integration.md ├── 06-Manage-Data-Privacy.md ├── 07-Test-Trace-Debug.md ├── 20-Deploy-Sample-Application.md ├── 30-Guided-Tour.md ├── 40-Multi-Tenancy.md ├── 44-Multi-Tenancy-Deployment.md ├── 45-Multi-Tenancy-Provisioning.md ├── 46-Multi-Tenancy-Provisioning-Connect-ByD.md ├── 51-S4HC-Integration.md ├── 52-Multi-Tenancy-Provisioning-Connect-S4HC.md ├── 61-C4P-Integration.md ├── 62-Multi-Tenancy-Provisioning-Connect-C4P.md ├── 71-Multi-Tenancy-Service-Broker.md ├── 72-Multi-Tenancy-Provisioning-Service-Broker.md ├── api-samples ├── Partner Reference App (MT).postman_collection.json └── Partner Reference App (MT).postman_environment.json └── images ├── 20-byd-launchpad.jpg ├── 20-create-project.jpg ├── 20-project-mixin.jpg ├── 20-project-onhold.jpg ├── ByD_integration_overview.jpg ├── Dependencies_with_destination.png ├── Dependencies_without_destination.png ├── FE-Wizard-open.png ├── FE-Wizard2.png ├── FE-Wizard3.png ├── FE-Wizard4.png ├── FE-Wizard5.png ├── FLP1.png ├── btp_eventmesh_entitlements.jpg ├── btp_eventmesh_service1.jpg ├── btp_eventmesh_service2.jpg ├── byd_launchpad.jpg ├── enableBAS1.png ├── enableBAS2.png ├── enableBAS3.png ├── enableBAS4.png ├── enableBAS5.png ├── enableBAS6.png ├── enableCF1.png ├── launchpad_sitemanager1.jpg ├── launchpad_sitemanager3.jpg ├── mt_byd_integration.jpg ├── mt_byd_launchpad.jpg ├── mt_deployment_model.jpg ├── mt_s4hc_integration.jpg ├── mt_s4hc_launchpad.jpg ├── readme_bom.jpg ├── readme_btp_components.jpg ├── readme_incremental-approach.jpg ├── readme_progressive_dev.jpg ├── readme_sample-deployment.jpg ├── readme_sample-use-case.jpg ├── startBAS.png └── startBAS2.png /.gitignore: -------------------------------------------------------------------------------- 1 | # CAP author-readings 2 | _out 3 | *.db 4 | connection.properties 5 | default-*.json 6 | .cdsrc-private.json 7 | gen/ 8 | node_modules/ 9 | target/ 10 | dist/ 11 | resources/ 12 | *.*-mt_mta_build_tmp 13 | 14 | # Web IDE, App Studio 15 | .che/ 16 | .gen/ 17 | .vscode 18 | .idea 19 | 20 | # MTA 21 | *_mta_build_tmp 22 | *.mtar 23 | mtad.yaml 24 | mta_archives/ 25 | Makefile*.mta 26 | 27 | # Other 28 | .DS_Store 29 | *.orig 30 | *.log 31 | 32 | *.iml 33 | *.flattened-pom.xml 34 | 35 | default-*.json 36 | package-lock.json 37 | -------------------------------------------------------------------------------- /.reuse/dep5: -------------------------------------------------------------------------------- 1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: sme-partner-reference-application 3 | Upstream-Contact: Knut Heusermann (knut.heusermann@sap.com) 4 | Source: https://github.com/sap-samples/sme-partner-reference-application 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: 2022 SAP SE or an SAP affiliate company and SME Partner Reference Application contributors 29 | License: Apache-2.0 30 | -------------------------------------------------------------------------------- /Applications/author-readings-mt/.cdsrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "requires": { 3 | "[development]": { 4 | "auth": { 5 | "kind": "mocked", 6 | "users": { 7 | "Kate Jacob": { 8 | "password": "welcome", 9 | "ID": "kjacob", 10 | "roles": [ 11 | "AuthorReadingManagerRole", 12 | "authenticated-user" 13 | ] 14 | }, 15 | "Peter Sellers": { 16 | "password": "welcome", 17 | "ID": "pseller", 18 | "roles": [ 19 | "AuthorReadingAdminRole", 20 | "authenticated-user" 21 | ] 22 | }, 23 | "Julia Brunner": { 24 | "password": "welcome", 25 | "ID": "jbrunner", 26 | "roles": [ 27 | "authenticated-user" 28 | ] 29 | }, 30 | "*": true 31 | } 32 | } 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /Applications/author-readings-mt/.npmrc: -------------------------------------------------------------------------------- 1 | strict-ssl=false 2 | registry=https://registry.npmjs.com/ 3 | @sap:registry=https://registry.npmjs.com/ 4 | -------------------------------------------------------------------------------- /Applications/author-readings-mt/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. 3 | // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp 4 | 5 | // List of extensions which should be recommended for users of this workspace. 6 | "recommendations": [ 7 | "SAPSE.vscode-cds", 8 | "dbaeumer.vscode-eslint", 9 | "esbenp.prettier-vscode", 10 | "mechatroner.rainbow-csv", 11 | "humao.rest-client", 12 | "alexcvzz.vscode-sqlite", 13 | "hbenl.vscode-mocha-test-adapter", 14 | "sdras.night-owl" 15 | ], 16 | // List of extensions recommended by VS Code that should not be recommended for users of this workspace. 17 | "unwantedRecommendations": [ 18 | 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /Applications/author-readings-mt/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "command": "cds run --with-mocks --in-memory?", 9 | "name": "cds run", 10 | "request": "launch", 11 | "type": "node-terminal", 12 | "skipFiles": [ 13 | "/**" 14 | ] 15 | }, 16 | { 17 | "command": "cds run --profile sandbox --with-mocks --in-memory?", 18 | "name": "cds run Sandbox", 19 | "request": "launch", 20 | "type": "node-terminal", 21 | "skipFiles": [ 22 | "/**" 23 | ] 24 | }, 25 | { 26 | "command": "cds run --profile production --with-mocks --in-memory?", 27 | "name": "cds run Production", 28 | "request": "launch", 29 | "type": "node-terminal", 30 | "skipFiles": [ 31 | "/**" 32 | ] 33 | } 34 | ] 35 | } -------------------------------------------------------------------------------- /Applications/author-readings-mt/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": { 3 | "**/.gitignore": true, 4 | "**/.git": true, 5 | "**/.vscode": true 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Applications/author-readings-mt/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "shell", 8 | "label": "cds watch", 9 | "command": "cds", 10 | "args": ["watch"], 11 | "group": { 12 | "kind": "build", 13 | "isDefault": true 14 | }, 15 | "problemMatcher": [] 16 | }, 17 | { 18 | "type": "shell", 19 | "label": "cds run", 20 | "command": "cds", 21 | "args": ["run", "--with-mocks", "--in-memory?"], 22 | "problemMatcher": [] 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /Applications/author-readings-mt/app/authorreadingmanager/README.md: -------------------------------------------------------------------------------- 1 | ## Application Details 2 | | | 3 | | ------------- | 4 | |**Generation Date and Time**
Tue Apr 05 2022 14:53:44 GMT+0000 (Coordinated Universal Time)| 5 | |**App Generator**
@sap/generator-fiori-elements| 6 | |**App Generator Version**
1.5.3| 7 | |**Generation Platform**
SAP Business Application Studio| 8 | |**Floorplan Used**
List Report Object Page V4| 9 | |**Service Type**
Local Cap| 10 | |**Service URL**
/authorreadingmanager/ 11 | |**Module Name**
authorreadingmanager| 12 | |**Application Title**
Manage Author Readings| 13 | |**Namespace**
| 14 | |**UI5 Theme**
sap_fiori_3_dark| 15 | |**UI5 Version**
1.100.0| 16 | |**Enable Code Assist Libraries**
False| 17 | |**Add Eslint configuration**
False| 18 | |**Main Entity**
AuthorReadings| 19 | |**Navigation Entity**
participants| 20 | 21 | ## authorreadingmanager 22 | 23 | An application to create and manage author readings. 24 | 25 | ### Starting the generated app 26 | 27 | - 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 start your CAP project and navigate to the following location in your browser: 28 | 29 | http://localhost:4004/authorreadingmanager/webapp/index.html 30 | 31 | #### Pre-requisites: 32 | 33 | 1. Active NodeJS LTS (Long Term Support) version and associated supported NPM version. (See https://nodejs.org) 34 | 35 | 36 | -------------------------------------------------------------------------------- /Applications/author-readings-mt/app/authorreadingmanager/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "authorreadingmanager", 3 | "version": "1.1.0", 4 | "description": "An application to create and manage author readings.", 5 | "keywords": [ 6 | "ui5", 7 | "openui5", 8 | "sapui5" 9 | ], 10 | "main": "webapp/index.html", 11 | "scripts": { 12 | "deploy-config": "npx -p @sap/ux-ui5-tooling fiori add deploy-config cf", 13 | "build:cf": "ui5 build preload --clean-dest --config ui5-deploy.yaml --include-task=generateManifestBundle generateCachebusterInfo" 14 | }, 15 | "devDependencies": { 16 | "@sap/ui5-builder-webide-extension": "^1.1.9", 17 | "ui5-task-zipper": "^0.8.5", 18 | "mbt": "^1.2.24" 19 | }, 20 | "ui5": { 21 | "dependencies": [ 22 | "@sap/ui5-builder-webide-extension", 23 | "ui5-task-zipper", 24 | "mbt" 25 | ] 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Applications/author-readings-mt/app/authorreadingmanager/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: authorreadingmanager 5 | type: application 6 | resources: 7 | configuration: 8 | propertiesFileSourceEncoding: UTF-8 9 | builder: 10 | resources: 11 | excludes: 12 | - "/test/**" 13 | - "/localService/**" 14 | customTasks: 15 | - name: webide-extension-task-updateManifestJson 16 | beforeTask: generateCachebusterInfo 17 | configuration: 18 | appFolder: webapp 19 | destDir: dist 20 | - name: ui5-task-zipper 21 | afterTask: generateCachebusterInfo 22 | configuration: 23 | archiveName: authorreadingmanager 24 | additionalFiles: 25 | - xs-app.json 26 | -------------------------------------------------------------------------------- /Applications/author-readings-mt/app/authorreadingmanager/ui5.yaml: -------------------------------------------------------------------------------- 1 | specVersion: '2.4' 2 | metadata: 3 | name: 'authorreadingmanager' 4 | type: application 5 | server: 6 | customMiddleware: 7 | - name: fiori-tools-proxy 8 | afterMiddleware: compression 9 | configuration: 10 | ignoreCertError: false # If set to true, certificate errors will be ignored. E.g. self-signed certificates will be accepted 11 | backend: 12 | - path: /authorreadingmanager 13 | url: http://localhost:4004 14 | ui5: 15 | path: 16 | - /resources 17 | - /test-resources 18 | url: https://ui5.sap.com 19 | - name: fiori-tools-appreload 20 | afterMiddleware: compression 21 | configuration: 22 | port: 35729 23 | path: webapp 24 | delay: 300 25 | -------------------------------------------------------------------------------- /Applications/author-readings-mt/app/authorreadingmanager/webapp/Component.js: -------------------------------------------------------------------------------- 1 | sap.ui.define(["sap/fe/core/AppComponent"], function(AppComponent) { 2 | 'use strict'; 3 | 4 | return AppComponent.extend("authorreadingmanager.Component", { 5 | metadata: { 6 | manifest: "json" 7 | } 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /Applications/author-readings-mt/app/authorreadingmanager/webapp/i18n/i18n.properties: -------------------------------------------------------------------------------- 1 | # This is the resource bundle for authorreadingmanager 2 | 3 | #Texts for manifest.json 4 | 5 | #XTIT: Application name 6 | appTitle=Manage Author Readings 7 | 8 | #YDES: Application description 9 | appDescription=An application to create and manage author readings. 10 | 11 | flpTitle=Author Readings 12 | 13 | flpSubtitle=Create and manage author readings 14 | -------------------------------------------------------------------------------- /Applications/author-readings-mt/app/authorreadingmanager/webapp/i18n/i18n_de.properties: -------------------------------------------------------------------------------- 1 | # This is the resource bundle for authorreadingmanager 2 | 3 | #Texts for manifest.json 4 | 5 | #XTIT: Application name 6 | appTitle = Autorenlesungen 7 | 8 | #YDES: Application description 9 | appDescription = Plane Autorenlesungen und Poetry Slams 10 | 11 | flpTitle = Autorenlesungen 12 | 13 | flpSubtitle = Plane Autorenlesungen und Poetry Slams 14 | -------------------------------------------------------------------------------- /Applications/author-readings-mt/app/authorreadingmanager/webapp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Author Readings 8 | 13 | 14 | 46 | 47 | 48 | 59 | 60 | 61 | 62 | 63 | 64 |
70 |
71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /Applications/author-readings-mt/app/authorreadingmanager/webapp/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "_version": "1.32.0", 3 | "sap.app": { 4 | "id": "authorreadingmanager", 5 | "type": "application", 6 | "i18n": "i18n/i18n.properties", 7 | "applicationVersion": { 8 | "version": "1.0.0" 9 | }, 10 | "title": "{{appTitle}}", 11 | "description": "{{appDescription}}", 12 | "dataSources": { 13 | "mainService": { 14 | "uri": "/odata/v4/authorreadingmanager/", 15 | "type": "OData", 16 | "settings": { 17 | "odataVersion": "4.0" 18 | } 19 | } 20 | }, 21 | "offline": false, 22 | "resources": "resources.json", 23 | "sourceTemplate": { 24 | "id": "ui5template.fiorielements.v4.lrop", 25 | "version": "1.0.0" 26 | }, 27 | "crossNavigation": { 28 | "inbounds": { 29 | "authorreadingmanager-inbound": { 30 | "signature": { 31 | "parameters": {}, 32 | "additionalParameters": "allowed" 33 | }, 34 | "semanticObject": "Object", 35 | "action": "display", 36 | "title": "{{flpTitle}}", 37 | "subTitle": "{{flpSubtitle}}", 38 | "icon": "" 39 | } 40 | } 41 | } 42 | }, 43 | "sap.ui": { 44 | "technology": "UI5", 45 | "icons": { 46 | "icon": "", 47 | "favIcon": "", 48 | "phone": "", 49 | "phone@2": "", 50 | "tablet": "", 51 | "tablet@2": "" 52 | }, 53 | "deviceTypes": { 54 | "desktop": true, 55 | "tablet": true, 56 | "phone": true 57 | } 58 | }, 59 | "sap.ui5": { 60 | "resources": { 61 | "js": [], 62 | "css": [] 63 | }, 64 | "dependencies": { 65 | "minUI5Version": "1.100.0", 66 | "libs": { 67 | "sap.ui.core": {}, 68 | "sap.fe.templates": {} 69 | } 70 | }, 71 | "models": { 72 | "@i18n": { 73 | "type": "sap.ui.model.resource.ResourceModel", 74 | "uri": "i18n/i18n.properties" 75 | }, 76 | "i18n": { 77 | "type": "sap.ui.model.resource.ResourceModel", 78 | "uri": "i18n/i18n.properties" 79 | }, 80 | "": { 81 | "dataSource": "mainService", 82 | "preload": true, 83 | "settings": { 84 | "synchronizationMode": "None", 85 | "operationMode": "Server", 86 | "autoExpandSelect": true, 87 | "earlyRequests": true 88 | } 89 | } 90 | }, 91 | "routing": { 92 | "routes": [ 93 | { 94 | "pattern": ":?query:", 95 | "name": "AuthorReadingsList", 96 | "target": "AuthorReadingsList" 97 | }, 98 | { 99 | "pattern": "AuthorReadings({key}):?query:", 100 | "name": "AuthorReadingsObjectPage", 101 | "target": "AuthorReadingsObjectPage" 102 | }, 103 | { 104 | "pattern": "AuthorReadings({key})/participants({key2}):?query:", 105 | "name": "ParticipantsObjectPage", 106 | "target": "ParticipantsObjectPage" 107 | } 108 | ], 109 | "targets": { 110 | "AuthorReadingsList": { 111 | "type": "Component", 112 | "id": "AuthorReadingsList", 113 | "name": "sap.fe.templates.ListReport", 114 | "options": { 115 | "settings": { 116 | "entitySet": "AuthorReadings", 117 | "initialLoad": true, 118 | "variantManagement": "Page", 119 | "navigation": { 120 | "AuthorReadings": { 121 | "detail": { 122 | "route": "AuthorReadingsObjectPage" 123 | } 124 | } 125 | } 126 | } 127 | } 128 | }, 129 | "AuthorReadingsObjectPage": { 130 | "type": "Component", 131 | "id": "AuthorReadingsObjectPage", 132 | "name": "sap.fe.templates.ObjectPage", 133 | "options": { 134 | "settings": { 135 | "editableHeaderContent": false, 136 | "entitySet": "AuthorReadings", 137 | "navigation": { 138 | "participants": { 139 | "detail": { 140 | "route": "ParticipantsObjectPage" 141 | } 142 | } 143 | } 144 | } 145 | } 146 | }, 147 | "ParticipantsObjectPage": { 148 | "type": "Component", 149 | "id": "ParticipantsObjectPage", 150 | "name": "sap.fe.templates.ObjectPage", 151 | "options": { 152 | "settings": { 153 | "editableHeaderContent": false, 154 | "entitySet": "Participants" 155 | } 156 | } 157 | } 158 | } 159 | }, 160 | "contentDensities": { 161 | "compact": true, 162 | "cozy": true 163 | } 164 | }, 165 | "sap.platform.abap": { 166 | "_version": "1.1.0", 167 | "uri": "" 168 | }, 169 | "sap.platform.hcp": { 170 | "_version": "1.1.0", 171 | "uri": "" 172 | }, 173 | "sap.fiori": { 174 | "_version": "1.1.0", 175 | "registrationIds": [], 176 | "archeType": "transactional" 177 | }, 178 | "sap.cloud": { 179 | "public": true, 180 | "service": "authorreadingmanager" 181 | } 182 | } -------------------------------------------------------------------------------- /Applications/author-readings-mt/app/authorreadingmanager/webapp/test/flpSandbox.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {{appTitle}} 9 | 10 | 25 | 56 | 57 | 58 | 59 | 70 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /Applications/author-readings-mt/app/authorreadingmanager/xs-app.json: -------------------------------------------------------------------------------- 1 | { 2 | "welcomeFile": "/index.html", 3 | "authenticationMethod": "route", 4 | "routes": [ 5 | { 6 | "source": "^/odata/v4/authorreadingmanager/(.*)$", 7 | "target": "/odata/v4/authorreadingmanager/$1", 8 | "destination": "srv-api", 9 | "authenticationType": "xsuaa", 10 | "csrfProtection": true 11 | }, 12 | { 13 | "source": "^(.*)$", 14 | "target": "$1", 15 | "service": "html5-apps-repo-rt", 16 | "authenticationType": "xsuaa" 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /Applications/author-readings-mt/app/services.cds: -------------------------------------------------------------------------------- 1 | 2 | using from './authorreadingmanager/annotations'; -------------------------------------------------------------------------------- /Applications/author-readings-mt/approuter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "approuter", 3 | "dependencies": { 4 | "@sap/approuter": "^14" 5 | }, 6 | "engines": { 7 | "node": ">=16.17.1 <19.0.0" 8 | }, 9 | "scripts": { 10 | "start": "node node_modules/@sap/approuter/approuter.js" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Applications/author-readings-mt/approuter/xs-app.json: -------------------------------------------------------------------------------- 1 | { 2 | "authenticationMethod": "route", 3 | "routes": [ 4 | { 5 | "source": "^(.*)$", 6 | "target": "$1", 7 | "service": "html5-apps-repo-rt", 8 | "authenticationType": "xsuaa" 9 | } 10 | ] 11 | } -------------------------------------------------------------------------------- /Applications/author-readings-mt/broker/catalog.json: -------------------------------------------------------------------------------- 1 | { 2 | "services": [ 3 | { 4 | "name": "authorreadings", 5 | "id": "1aac0de3-bc10-42bc-a950-00a9fbec536e", 6 | "description": "Author Readings API", 7 | "bindable": true, 8 | "plans": [ 9 | { 10 | "name": "standard", 11 | "id": "358813f4-6ed2-47e1-90b1-dd9fefda4b1f", 12 | "description": "standard", 13 | "metadata": { 14 | "supportedPlatforms": [ 15 | "cloudfoundry", 16 | "sapcp" 17 | ] 18 | } 19 | } 20 | ] 21 | 22 | } 23 | ] 24 | } -------------------------------------------------------------------------------- /Applications/author-readings-mt/broker/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "broker", 3 | "version": "1.0.0", 4 | "description": "", 5 | "scripts": { 6 | "start": "start-broker" 7 | }, 8 | "author": "", 9 | "license": "ISC", 10 | "dependencies": { 11 | "@sap/sbf": "^6.6.1" 12 | }, 13 | "engines": { 14 | "node": ">=16.17.1 <19.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Applications/author-readings-mt/db/data/sap.common-Currencies.csv: -------------------------------------------------------------------------------- 1 | code;symbol;name;descr 2 | EUR;€;Euro;European Euro 3 | USD;$;US Dollar;United States Dollar 4 | CAD;$;Canadian Dollar;Canadian Dollar 5 | AUD;$;Australian Dollar;Australian Dollar 6 | GBP;£;British Pound;Great Britain Pound 7 | ILS;₪;Shekel;Israeli New Shekel 8 | INR;₹;Rupee;Indian Rupee 9 | QAR;﷼;Riyal;Katar Riyal 10 | SAR;﷼;Riyal;Saudi Riyal 11 | JPY;¥;Yen;Japanese Yen 12 | CNY;¥;Yuan;Chinese Yuan Renminbi -------------------------------------------------------------------------------- /Applications/author-readings-mt/db/data/sap.common-Currencies_texts.csv: -------------------------------------------------------------------------------- 1 | code;locale;name;descr 2 | EUR;en;Euro;European Euro 3 | USD;en;US Dollar;United States Dollar 4 | CAD;en;Canadian Dollar;Canadian Dollar 5 | AUD;en;Australian Dollar;Australian Dollar 6 | GBP;en;British Pound;Great Britain Pound 7 | ILS;en;Shekel;Israeli New Shekel 8 | INR;en;Rupee;Indian Rupee 9 | QAR;en;Riyal;Katar Riyal 10 | SAR;en;Riyal;Saudi Riyal 11 | JPY;en;Yen;Japanese Yen 12 | CNY;en;Yuan;Chinese Yuan Renminbi 13 | EUR;de;Euro;Europäischer Euro 14 | USD;de;US-Dollar;US-Dollar 15 | CAD;de;Kanadischer Dollar;Kanadischer Dollar 16 | AUD;de;Australischer Dollar;Australischer Dollar 17 | GBP;de;Britisches Pfund;Großbritannien Pfund 18 | ILS;de;Schekel;Israelischer Neuer Schekel 19 | INR;de;Rupie;Indische Rupie 20 | QAR;de;Riyal;Katar Riyal 21 | SAR;de;Riyal;Saudi-Riyal 22 | JPY;de;Yen;Japanischer Yen 23 | CNY;de;Yuan;Chinesischer Yuan Renminbi -------------------------------------------------------------------------------- /Applications/author-readings-mt/db/data/sap.samples.authorreadings-AuthorReadingStatusCodes.csv: -------------------------------------------------------------------------------- 1 | code;name;descr 2 | 0;NotReleased;Not Released 3 | 1;Published;Published 4 | 2;Booked;Booked 5 | 4;Blocked;Blocked -------------------------------------------------------------------------------- /Applications/author-readings-mt/db/data/sap.samples.authorreadings-AuthorReadingStatusCodes_texts.csv: -------------------------------------------------------------------------------- 1 | code;locale;name;descr 2 | 0;en;NotReleased;Not Released 3 | 1;en;Published;Published 4 | 2;en;Booked;Booked 5 | 4;en;Blocked;Blocked 6 | 0;de;NotReleased;Nicht freigegeben 7 | 1;de;Published;Veröffentlicht 8 | 2;de;Booked;Gebucht 9 | 4;de;Blocked;Blockiert -------------------------------------------------------------------------------- /Applications/author-readings-mt/db/data/sap.samples.authorreadings-AuthorReadings.csv: -------------------------------------------------------------------------------- 1 | ID;identifier;date;maxParticipantsNumber;availableFreeSlots;participantsFeeAmount;currency_code;statusCode_code;createdBy;title;description 2 | 79ceab87-300d-4b66-8cc3-f82c679b77a1;1;2023-03-03;50;48;100.00;EUR;1;anonymous;The one plus one;Author reading: Jojo Moyes reading in her novel "The one plus one" 3 | 79ceab87-300d-4b66-8cc3-f82c679b77a2;2;2023-08-29;50;47;105.00;CNY;1;anonymous;三体;Liu Cixin talks about the philosophy in his science fiction trilogy "The Three-Body Problem", "The Dark Forest" and "Death's End" 4 | 79ceab87-300d-4b66-8cc3-f82c679b77a3;3;2023-09-01;75;73;95.00;USD;1;anonymous;The Hobbit;Thorin Oakenshield reads J. R. Tolkiens "The Hobbit" supported by the Rivendell Orchestra 5 | 79ceab87-300d-4b66-8cc3-f82c679b77a4;4;2023-07-07;75;73;1000;INR;1;anonymous;A Midsommer Night's Dream;Hermia Lysander reading William Shakespeare's comedy "A Midsommer Night's Dream" 6 | 79ceab87-300d-4b66-8cc3-f82c679b77a5;5;2023-07-27;50;47;100;EUR;1;anonymous;By the Sea;Author reading: Abdulrazak Gurnah reads "By the Sea" 7 | 79ceab87-300d-4b66-8cc3-f82c679b77a6;6;2023-09-23;50;50;79;EUR;0;anonymous;Catweazle;Stuffy Gladstone reading Catweazle live 8 | 79ceab87-300d-4b66-8cc3-f82c679b77a7;7;2023-10-14;50;50;25;EUR;0;anonymous;Poetry Slam Berlin;Live! Poetry slam 2023 in Berlin 9 | 79ceab87-300d-4b66-8cc3-f82c679b77a8;8;2023-10-21;50;50;25;EUR;0;anonymous;Wacken Poetry Open Air;Open air poetry festival in Wacken -------------------------------------------------------------------------------- /Applications/author-readings-mt/db/data/sap.samples.authorreadings-ParticipantStatusCodes.csv: -------------------------------------------------------------------------------- 1 | code;name;descr 2 | 1;InProcess;In Process 3 | 2;Confirmed;Confirmed 4 | 3;Cancelled;Cancelled -------------------------------------------------------------------------------- /Applications/author-readings-mt/db/data/sap.samples.authorreadings-ParticipantStatusCodes_texts.csv: -------------------------------------------------------------------------------- 1 | code;locale;name;descr 2 | 1;en;InProcess;In Process 3 | 2;en;Confirmed;Confirmed 4 | 3;en;Cancelled;Cancelled 5 | 1;de;InProcess;In Bearbeitung 6 | 2;de;Confirmed;Bestätigt 7 | 3;de;Cancelled;Storniert -------------------------------------------------------------------------------- /Applications/author-readings-mt/db/data/sap.samples.authorreadings-Participants.csv: -------------------------------------------------------------------------------- 1 | ID;parent_ID;identifier;name;email;mobileNumber;statusCode_code 2 | 79ceab87-300d-4b66-8cc3-182c679b7c01;79ceab87-300d-4b66-8cc3-f82c679b77a1;1;Carlos Garcia;carlos.garcia@sapbydesign.com;+34 789654123;2 3 | 79ceab87-300d-4b66-8cc3-282c679b7c02;79ceab87-300d-4b66-8cc3-f82c679b77a1;2;Lucas Van Brekelenkam;Lucas.VanBrekelenkam@sapbydesign.com;+31 4399357102;2 4 | 79ceab87-300d-4b66-8cc3-382c679b7c03;79ceab87-300d-4b66-8cc3-f82c679b77a5;1;Susan Winters;Susan.Winters@sapbydesign.com;;2 5 | 79ceab87-300d-4b66-8cc3-482c679b7c04;79ceab87-300d-4b66-8cc3-f82c679b77a5;2;Julia Brunner;Julia.Brunner@sapbydesign.com;+43 519369020;2 6 | 79ceab87-300d-4b66-8cc3-582c679b7c05;79ceab87-300d-4b66-8cc3-f82c679b77a5;3;Eddie Smoke;eddie.smoke@sapbydesign.com;+49 15116810562;2 7 | 79ceab87-300d-4b66-8cc3-682c679b7c06;79ceab87-300d-4b66-8cc3-f82c679b77a3;1;Bram De Jong;Bram.DeJong@sapbydesign.com;+31 40399357104;2 8 | 79ceab87-300d-4b66-8cc3-782c679b7c07;79ceab87-300d-4b66-8cc3-f82c679b77a3;2;Giuseppe Rosso;giuseppe.rossi@sapbydesign.com;+39 68747524;2 9 | 79ceab87-300d-4b66-8cc3-882c679b7c08;79ceab87-300d-4b66-8cc3-f82c679b77a4;1;Jessica Orwell;jessica.orwell@sapbydesign.com;;2 10 | 79ceab87-300d-4b66-8cc3-982c679b7c09;79ceab87-300d-4b66-8cc3-f82c679b77a4;2;Catherine Kennedy-Woods;Catherine.Kennedy-Woods@sapbydesign.com;;2 11 | 79ceab87-300d-4b66-8cc3-a82c679b7c10;79ceab87-300d-4b66-8cc3-f82c679b77a2;1;Jie Wenjie;Jie.Wenjie@sapbydesign.com;;2 12 | 79ceab87-300d-4b66-8cc3-b82c679b7c11;79ceab87-300d-4b66-8cc3-f82c679b77a2;2;Knut Evans;Knut.Evans@sapbydesign.com;;2 13 | 79ceab87-300d-4b66-8cc3-c82c679b7c12;79ceab87-300d-4b66-8cc3-f82c679b77a2;3;Richard Miao;Richard.Miao@sapbydesign.com;;2 -------------------------------------------------------------------------------- /Applications/author-readings-mt/db/entity-models.cds: -------------------------------------------------------------------------------- 1 | namespace sap.samples.authorreadings; 2 | 3 | using { 4 | sap, 5 | managed, 6 | cuid, 7 | Currency 8 | } from '@sap/cds/common'; 9 | 10 | // Author readings 11 | entity AuthorReadings : managed, cuid { 12 | identifier : String; 13 | title : localized String(100); 14 | description : localized String(500); 15 | date : DateTime; 16 | maxParticipantsNumber : Integer; 17 | availableFreeSlots : Integer; 18 | participantsFeeAmount : Decimal(6,2); 19 | currency : Association to one sap.common.Currencies; 20 | statusCode : Association to one AuthorReadingStatusCodes; 21 | participants : Composition of many Participants on participants.parent = $self; 22 | projectID : String; 23 | projectObjectID : String; 24 | projectURL : String; 25 | projectSystem : String; 26 | eventMeshMessage : String; 27 | } 28 | 29 | // Participants (sub-node of AuthorReadings) 30 | entity Participants : managed, cuid { 31 | parent : Association to AuthorReadings; 32 | identifier : String; 33 | name : String; 34 | email : String; 35 | mobileNumber : String; 36 | statusCode : Association to one ParticipantStatusCodes; 37 | } 38 | 39 | // Author reading status codes 40 | entity AuthorReadingStatusCodes : sap.common.CodeList { 41 | @Common.Text : { 42 | $value : descr, 43 | ![@UI.TextArrangement] : #TextOnly 44 | } 45 | key code : Integer default 0 46 | } 47 | 48 | // Participant status codes 49 | entity ParticipantStatusCodes : sap.common.CodeList { 50 | @Common.Text : { 51 | $value : descr, 52 | ![@UI.TextArrangement] : #TextOnly 53 | } 54 | key code : Integer default 1 55 | } 56 | 57 | annotate AuthorReadings with @fiori.draft.enabled { 58 | ID @title : '{i18n>uuid}' @Core.Computed; 59 | identifier @title : '{i18n>identifier}' @mandatory; 60 | title @title : '{i18n>title}' @mandatory; 61 | description @title : '{i18n>description}'; 62 | date @title : '{i18n>date}' @mandatory; 63 | maxParticipantsNumber @title : '{i18n>maxParticipantsNumber}' @mandatory; 64 | availableFreeSlots @title : '{i18n>availableFreeSlots}' @readonly; 65 | participantsFeeAmount @title : '{i18n>participantsFeeAmount}' @Measures.ISOCurrency: currency_code; 66 | currency @title : '{i18n>currency}'; 67 | statusCode @title : '{i18n>statusCode}' @readonly; 68 | projectID @title : '{i18n>projectID}'; 69 | projectObjectID @title : '{i18n>projectObjectID}'; 70 | projectURL @title : '{i18n>projectURL}'; 71 | projectSystem @title : '{i18n>projectSystem}'; 72 | eventMeshMessage @title : '{i18n>eventMeshMessage}'; 73 | } 74 | 75 | annotate Participants with { 76 | ID @title : '{i18n>uuid}' @Core.Computed; 77 | parent @title : '{i18n>authorReadingUUID}'; 78 | identifier @title : '{i18n>identifier}' @mandatory; 79 | name @title : '{i18n>name}' @mandatory; 80 | email @title : '{i18n>email}'; 81 | mobileNumber @title : '{i18n>mobileNumber}'; 82 | statusCode @title : '{i18n>statusCode}' @readonly; 83 | } 84 | 85 | annotate AuthorReadingStatusCodes with { 86 | code @title : '{i18n>codeListStatusCode}'; 87 | descr @title : '{i18n>codeListStatusText}' 88 | } 89 | 90 | annotate ParticipantStatusCodes with { 91 | code @title : '{i18n>codeListStatusCode}'; 92 | descr @title : '{i18n>codeListStatusText}' 93 | } 94 | -------------------------------------------------------------------------------- /Applications/author-readings-mt/db/i18n/i18n.properties: -------------------------------------------------------------------------------- 1 | # Entity model translation / default language 2 | 3 | # Texts for titles used in data model 4 | 5 | #XTIT 6 | AuthorReadingStatusCode = Author Reading Status 7 | ParticipantStatusCode = Participant Status 8 | 9 | # ------------------------------------------------------------------------------------- 10 | # Labels for entity AuthorReadings 11 | 12 | title = Title 13 | description = Description 14 | date = Date 15 | maxParticipantsNumber = Max Number of Participants 16 | availableFreeSlots = Available Free Slots 17 | participantsFeeAmount = Participants Fee 18 | currency = Currency 19 | projectID = Project 20 | projectObjectID = Project UUID 21 | projectURL = Project URL 22 | projectSystem = Project System Type 23 | projectSystemName = Project System 24 | eventMeshMessage = Event Messages 25 | 26 | # ------------------------------------------------------------------------------------- 27 | # Labels for entity Participants 28 | 29 | authorReadingUUID = Author Reading UUID 30 | name = Name 31 | email = E-Mail 32 | mobileNumber = Phone Number 33 | 34 | # ------------------------------------------------------------------------------------- 35 | # Common labels 36 | 37 | uuid = UUID 38 | identifier = ID 39 | statusCode = Status Code 40 | codeListStatusCode = Status Code 41 | codeListStatusText = Status 42 | 43 | # ------------------------------------------------------------------------------------- 44 | # Transient Service Elements 45 | 46 | statusCriticality = Status 47 | createByDProjectEnabled = SAP Business ByDesign connected 48 | createS4HCProjectEnabled = S/4HANA Cloud connected 49 | 50 | # ------------------------------------------------------------------------------------- 51 | # Service Actions 52 | 53 | publish = Publish 54 | block = Block 55 | confirmParticipation = Confirm Participation 56 | cancelParticipation = Cancel Participation 57 | createByDProject = Create Project in ByD 58 | createS4HCProject = Create Project in S/4HANA Cloud 59 | createC4PProject = Create Collaborative Project 60 | createProject = Create Project 61 | 62 | # ------------------------------------------------------------------------------------- 63 | # Remote Service Elements 64 | 65 | projectTypeCodeText = Project Type 66 | projectStatusCodeText = Project Status 67 | projectCostCenter = Cost Center 68 | projectStartDateTime = Start Date 69 | projectEndDateTime = End Date 70 | projectDescription = Project Description 71 | projectProfile = Project Profile 72 | responsibleCostCenter = Responsible Cost Center 73 | processingStatus = Processing Status 74 | projectName = Project Name 75 | projectStatus = Project Status 76 | 77 | # ------------------------------------------------------------------------------------- 78 | # Web Application Titles 79 | 80 | authorreading = Author Reading 81 | authorreading-plural = Author Readings 82 | 83 | participant = Participant 84 | participant-plural = Participants 85 | 86 | generalData = General Data 87 | participantData = Participant Data 88 | administativeData = Administrative Data 89 | projectData = Project Data 90 | -------------------------------------------------------------------------------- /Applications/author-readings-mt/db/i18n/i18n_de.properties: -------------------------------------------------------------------------------- 1 | # Entity model translation / German 2 | 3 | # Texts for titles used in data model 4 | 5 | #XTIT 6 | AuthorReadingStatusCode = Status der Lesung 7 | ParticipantStatusCode = Teilnehmerstatus 8 | 9 | # ------------------------------------------------------------------------------------- 10 | # Labels for entity AuthorReadings 11 | 12 | title = Titel 13 | description = Beschreibung 14 | date = Datum 15 | maxParticipantsNumber = Maximale Teilnehmeranzahl 16 | availableFreeSlots = Freie Plätze 17 | participantsFeeAmount = Unkostenbeitrag 18 | currency = Währung 19 | projectID = Projekt 20 | projectObjectID = Projekt-ID 21 | projectURL = Projektlink 22 | projectSystem = Projektsystemtyp 23 | projectSystemName = Projektsystem 24 | eventMeshMessage = Event-Nachrichten 25 | 26 | # ------------------------------------------------------------------------------------- 27 | # Labels for entity Participants 28 | 29 | authorReadingUUID = UUID der Lesung 30 | name = Name 31 | email = E-Mail 32 | mobileNumber = Telefonnummer 33 | 34 | # ------------------------------------------------------------------------------------- 35 | # Common labels 36 | 37 | uuid = UUID 38 | identifier = ID 39 | statusCode = Statuscode 40 | codeListStatusCode = Code 41 | codeListStatusText = Statusbeschreibung 42 | 43 | # ------------------------------------------------------------------------------------- 44 | # Transient Service Elements 45 | 46 | statusCriticality = Status 47 | createByDProjectEnabled = SAP Business ByDesign verbunden 48 | createS4HCProjectEnabled = S/4HANA Cloud verbunden 49 | 50 | # ------------------------------------------------------------------------------------- 51 | # Service Actions 52 | 53 | publish = Veröffentlichen 54 | block = Absagen 55 | confirmParticipation = Teilnahme bestätigen 56 | cancelParticipation = Teilnahme absagen 57 | createByDProject = Projekt in ByD anlegen 58 | createS4HCProject = Projekt in S/4HANA Cloud anlegen 59 | createC4PProject = Kollaborationsprojekt anlegen 60 | createProject = Projekt anlegen 61 | 62 | # ------------------------------------------------------------------------------------- 63 | # Remote Service Elements 64 | 65 | projectTypeCodeText = Projekttyp 66 | projectStatusCodeText = Projektstatus 67 | projectCostCenter = Kostenstelle 68 | projectStartDateTime = Projektstart 69 | projectEndDateTime = Projektende 70 | projectDescription = Beschreibung 71 | projectProfile = Projektprofil 72 | responsibleCostCenter = Verantwortliche Kostenstelle 73 | processingStatus = Ausführungsstatus 74 | projectName = Projektname 75 | projectStatus = Projektstatus 76 | 77 | # ------------------------------------------------------------------------------------- 78 | # Web Application Titles 79 | 80 | authorreading = Autorenlesung 81 | authorreading-plural = Autorenlesungen 82 | 83 | participant = Teilnehmer 84 | participant-plural = Teilnehmer 85 | 86 | generalData = Allgemeine Informationen 87 | participantData = Teilnehmerdaten 88 | administativeData = Administrative Daten 89 | projectData = Projektdaten 90 | -------------------------------------------------------------------------------- /Applications/author-readings-mt/db/src/.hdiconfig: -------------------------------------------------------------------------------- 1 | { 2 | "file_suffixes": { 3 | "csv": { 4 | "plugin_name": "com.sap.hana.di.tabledata.source" 5 | }, 6 | "hdbafllangprocedure": { 7 | "plugin_name": "com.sap.hana.di.afllangprocedure" 8 | }, 9 | "hdbanalyticprivilege": { 10 | "plugin_name": "com.sap.hana.di.analyticprivilege" 11 | }, 12 | "hdbcalculationview": { 13 | "plugin_name": "com.sap.hana.di.calculationview" 14 | }, 15 | "hdbcollection": { 16 | "plugin_name": "com.sap.hana.di.collection" 17 | }, 18 | "hdbconstraint": { 19 | "plugin_name": "com.sap.hana.di.constraint" 20 | }, 21 | "hdbdropcreatetable": { 22 | "plugin_name": "com.sap.hana.di.dropcreatetable" 23 | }, 24 | "hdbflowgraph": { 25 | "plugin_name": "com.sap.hana.di.flowgraph" 26 | }, 27 | "hdbfunction": { 28 | "plugin_name": "com.sap.hana.di.function" 29 | }, 30 | "hdbgraphworkspace": { 31 | "plugin_name": "com.sap.hana.di.graphworkspace" 32 | }, 33 | "hdbhadoopmrjob": { 34 | "plugin_name": "com.sap.hana.di.virtualfunctionpackage.hadoop" 35 | }, 36 | "hdbindex": { 37 | "plugin_name": "com.sap.hana.di.index" 38 | }, 39 | "hdblibrary": { 40 | "plugin_name": "com.sap.hana.di.library" 41 | }, 42 | "hdbmigrationtable": { 43 | "plugin_name": "com.sap.hana.di.table.migration" 44 | }, 45 | "hdbprocedure": { 46 | "plugin_name": "com.sap.hana.di.procedure" 47 | }, 48 | "hdbprojectionview": { 49 | "plugin_name": "com.sap.hana.di.projectionview" 50 | }, 51 | "hdbprojectionviewconfig": { 52 | "plugin_name": "com.sap.hana.di.projectionview.config" 53 | }, 54 | "hdbreptask": { 55 | "plugin_name": "com.sap.hana.di.reptask" 56 | }, 57 | "hdbresultcache": { 58 | "plugin_name": "com.sap.hana.di.resultcache" 59 | }, 60 | "hdbrole": { 61 | "plugin_name": "com.sap.hana.di.role" 62 | }, 63 | "hdbroleconfig": { 64 | "plugin_name": "com.sap.hana.di.role.config" 65 | }, 66 | "hdbsearchruleset": { 67 | "plugin_name": "com.sap.hana.di.searchruleset" 68 | }, 69 | "hdbsequence": { 70 | "plugin_name": "com.sap.hana.di.sequence" 71 | }, 72 | "hdbstatistics": { 73 | "plugin_name": "com.sap.hana.di.statistics" 74 | }, 75 | "hdbstructuredprivilege": { 76 | "plugin_name": "com.sap.hana.di.structuredprivilege" 77 | }, 78 | "hdbsynonym": { 79 | "plugin_name": "com.sap.hana.di.synonym" 80 | }, 81 | "hdbsynonymconfig": { 82 | "plugin_name": "com.sap.hana.di.synonym.config" 83 | }, 84 | "hdbsystemversioning": { 85 | "plugin_name": "com.sap.hana.di.systemversioning" 86 | }, 87 | "hdbtable": { 88 | "plugin_name": "com.sap.hana.di.table" 89 | }, 90 | "hdbtabledata": { 91 | "plugin_name": "com.sap.hana.di.tabledata" 92 | }, 93 | "hdbtabletype": { 94 | "plugin_name": "com.sap.hana.di.tabletype" 95 | }, 96 | "hdbtrigger": { 97 | "plugin_name": "com.sap.hana.di.trigger" 98 | }, 99 | "hdbview": { 100 | "plugin_name": "com.sap.hana.di.view" 101 | }, 102 | "hdbvirtualfunction": { 103 | "plugin_name": "com.sap.hana.di.virtualfunction" 104 | }, 105 | "hdbvirtualfunctionconfig": { 106 | "plugin_name": "com.sap.hana.di.virtualfunction.config" 107 | }, 108 | "hdbvirtualpackagehadoop": { 109 | "plugin_name": "com.sap.hana.di.virtualpackage.hadoop" 110 | }, 111 | "hdbvirtualpackagesparksql": { 112 | "plugin_name": "com.sap.hana.di.virtualpackage.sparksql" 113 | }, 114 | "hdbvirtualprocedure": { 115 | "plugin_name": "com.sap.hana.di.virtualprocedure" 116 | }, 117 | "hdbvirtualprocedureconfig": { 118 | "plugin_name": "com.sap.hana.di.virtualprocedure.config" 119 | }, 120 | "hdbvirtualtable": { 121 | "plugin_name": "com.sap.hana.di.virtualtable" 122 | }, 123 | "hdbvirtualtableconfig": { 124 | "plugin_name": "com.sap.hana.di.virtualtable.config" 125 | }, 126 | "properties": { 127 | "plugin_name": "com.sap.hana.di.tabledata.properties" 128 | }, 129 | "tags": { 130 | "plugin_name": "com.sap.hana.di.tabledata.properties" 131 | }, 132 | "txt": { 133 | "plugin_name": "com.sap.hana.di.copyonly" 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /Applications/author-readings-mt/db/undeploy.json: -------------------------------------------------------------------------------- 1 | [ 2 | "src/gen/**/*.hdbview", 3 | "src/gen/**/*.hdbindex", 4 | "src/gen/**/*.hdbconstraint" 5 | ] 6 | -------------------------------------------------------------------------------- /Applications/author-readings-mt/external_resources/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "cds": { 3 | "requires": { 4 | "S4HC_API_ENTERPRISE_PROJECT_SRV_0002": { 5 | "kind": "odata-v2", 6 | "model": "srv/external/S4HC_API_ENTERPRISE_PROJECT_SRV_0002" 7 | } 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /Applications/author-readings-mt/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "author-readings", 3 | "version": "1.1.0", 4 | "description": "SAP Partner Reference Application v1.1", 5 | "repository": "https://github.com/SAP-samples/sme-partner-reference-application", 6 | "author": "SAP", 7 | "license": "SAP SAMPLE CODE LICENSE", 8 | "dependencies": { 9 | "@sap-cloud-sdk/connectivity": "^3.8.0", 10 | "@sap-cloud-sdk/http-client": "^3.8.0", 11 | "@sap/audit-logging": "^5.8.1", 12 | "@sap/cds": "^7.4.0", 13 | "@sap/cds-dk": "^7.4.0", 14 | "@sap/cds-mtxs": "^1.13.0", 15 | "@sap/xssec": "^3.5.0", 16 | "cors": "^2.8.5", 17 | "express": "^4.18.2", 18 | "hdb": "^0.19.6", 19 | "passport": "^0.6.0", 20 | "moment": "^2.29.4" 21 | }, 22 | "devDependencies": { 23 | "@sap/ux-specification": "^1.108.16", 24 | "chai": "^4.3.10", 25 | "chai-http": "^4.4.0", 26 | "mocha": "^10.2.0", 27 | "sqlite3": "^5.1.6" 28 | }, 29 | "engines": { 30 | "node": ">=16.17.1 <19.0.0" 31 | }, 32 | "scripts": { 33 | "start": "cds-serve", 34 | "test": "mocha 'test/*.test.js' --recursive --timeout 10000 --exit", 35 | "undeploy": "cf undeploy author-readings --delete-services --delete-service-keys" 36 | }, 37 | "cds": { 38 | "features": { 39 | "fetch_csrf": true, 40 | "audit_personal_data": true 41 | }, 42 | "requires": { 43 | "db": { 44 | "kind": "sql" 45 | }, 46 | "uaa": { 47 | "kind": "xsuaa" 48 | }, 49 | "audit-log": { 50 | "[sandbox]": { 51 | "kind": "audit-log-to-console" 52 | }, 53 | "[production]": { 54 | "kind": "audit-log-service" 55 | } 56 | }, 57 | "[production]": { 58 | "db": { 59 | "kind": "hana-mt" 60 | }, 61 | "auth": { 62 | "kind": "xsuaa", 63 | "strategy": "JWT" 64 | }, 65 | "multitenancy": true 66 | }, 67 | "byd_khproject": { 68 | "kind": "odata-v2", 69 | "model": "srv/external/byd_khproject", 70 | "[sandbox]": { 71 | "credentials": { 72 | "url": "https://{{ByD-hostname}}/sap/byd/odata/cust/v1/khproject/", 73 | "authentication": "BasicAuthentication", 74 | "username": "{{test-user}}", 75 | "password": "{{test-password}}" 76 | } 77 | }, 78 | "[production]": { 79 | "credentials": { 80 | "destination": "byd", 81 | "path": "/sap/byd/odata/cust/v1/khproject" 82 | } 83 | } 84 | }, 85 | "byd_khproject_tech_user": { 86 | "kind": "odata-v2", 87 | "model": "srv/external/byd_khproject_tech_user", 88 | "[sandbox]": { 89 | "credentials": { 90 | "url": "https://{{ByD-hostname}}/sap/byd/odata/cust/v1/khproject/", 91 | "authentication": "BasicAuthentication", 92 | "username": "{{test-user}}", 93 | "password": "{{test-password}}" 94 | } 95 | }, 96 | "[production]": { 97 | "credentials": { 98 | "destination": "byd-tech-user", 99 | "path": "/sap/byd/odata/cust/v1/khproject" 100 | } 101 | } 102 | }, 103 | "S4HC_API_ENTERPRISE_PROJECT_SRV_0002": { 104 | "kind": "odata-v2", 105 | "model": "srv/external/S4HC_API_ENTERPRISE_PROJECT_SRV_0002", 106 | "[sandbox]": { 107 | "credentials": { 108 | "url": "https://{{S4HC-hostname}}/sap/opu/odata/sap/API_ENTERPRISE_PROJECT_SRV;v=0002", 109 | "authentication": "BasicAuthentication", 110 | "username": "{{test-user}}", 111 | "password": "{{test-password}}" 112 | } 113 | }, 114 | "[production]": { 115 | "credentials": { 116 | "destination": "s4hc", 117 | "path": "/sap/opu/odata/sap/API_ENTERPRISE_PROJECT_SRV;v=0002" 118 | } 119 | } 120 | }, 121 | "S4HC_ENTPROJECTPROCESSINGSTATUS_0001": { 122 | "kind": "odata", 123 | "model": "srv/external/S4HC_ENTPROJECTPROCESSINGSTATUS_0001", 124 | "[sandbox]": { 125 | "credentials": { 126 | "url": "https://{{S4HC-hostname}}/sap/opu/odata4/sap/api_entprojprocessingstat/srvd_a2x/sap/entprojectprocessingstatus/0001", 127 | "authentication": "BasicAuthentication", 128 | "username": "{{test-user}}", 129 | "password": "{{test-password}}" 130 | } 131 | }, 132 | "[production]": { 133 | "credentials": { 134 | "destination": "s4hc-tech-user", 135 | "path": "/sap/opu/odata4/sap/api_entprojprocessingstat/srvd_a2x/sap/entprojectprocessingstatus/0001" 136 | } 137 | } 138 | }, 139 | "S4HC_ENTPROJECTPROFILECODE_0001": { 140 | "kind": "odata", 141 | "model": "srv/external/S4HC_ENTPROJECTPROFILECODE_0001", 142 | "[sandbox]": { 143 | "credentials": { 144 | "url": "https://{{S4HC-hostname}}/sap/opu/odata4/sap/api_entprojectprofilecode/srvd_a2x/sap/entprojectprofilecode/0001", 145 | "authentication": "BasicAuthentication", 146 | "username": "{{test-user}}", 147 | "password": "{{test-password}}" 148 | } 149 | }, 150 | "[production]": { 151 | "credentials": { 152 | "destination": "s4hc-tech-user", 153 | "path": "/sap/opu/odata4/sap/api_entprojectprofilecode/srvd_a2x/sap/entprojectprofilecode/0001" 154 | } 155 | } 156 | }, 157 | "c4p_ProjectService": { 158 | "kind": "odata", 159 | "model": "srv/external/c4p_ProjectService", 160 | "[production]": { 161 | "credentials": { 162 | "destination": "c4p", 163 | "path": "/ProjectService/v1" 164 | } 165 | } 166 | }, 167 | "c4p_TaskService": { 168 | "kind": "odata", 169 | "model": "srv/external/c4p_TaskService", 170 | "[production]": { 171 | "credentials": { 172 | "destination": "c4p", 173 | "path": "/TaskService/v1" 174 | } 175 | } 176 | } 177 | }, 178 | "hana": { 179 | "deploy-format": "hdbtable" 180 | }, 181 | "mtx": { 182 | "element-prefix": "Z_", 183 | "namespace-blocklist": [], 184 | "extension-allowlist": [] 185 | } 186 | }, 187 | "sapux": [ 188 | "app/authorreadingmanager" 189 | ] 190 | } 191 | -------------------------------------------------------------------------------- /Applications/author-readings-mt/server.js: -------------------------------------------------------------------------------- 1 | // Define allowed access origins for CORS checks 2 | // In our example we allow all origins. For productive use specific origins shall be allowed only. 3 | 4 | const cds = require('@sap/cds') 5 | 6 | cds.on('bootstrap', (app) => { 7 | const cors = require('cors') 8 | app.use(cors()) 9 | app.use((req, res, next) => { 10 | res.setHeader('Access-Control-Allow-Origin', '*'); 11 | next(); 12 | }); 13 | }) 14 | 15 | cds.on('listening', () => { 16 | // add more middleware ... 17 | }) 18 | 19 | module.exports = cds.server // delegate to default server.js -------------------------------------------------------------------------------- /Applications/author-readings-mt/srv/connector-byd.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | // Include cds libraries and reuse files 4 | const cds = require("@sap/cds"); 5 | 6 | // ---------------------------------------------------------------------------- 7 | // ByD specific reuse functions 8 | // ---------------------------------------------------------------------------- 9 | 10 | // Delegate OData requests to remote ByD project entities 11 | async function delegateODataRequests(req,remoteService) { 12 | try{ 13 | const bydProject = await cds.connect.to(remoteService); 14 | return bydProject.run(req.query); 15 | }catch (error) { 16 | console.log(error); 17 | } 18 | } 19 | 20 | // Return json-payload to create ByD projects 21 | async function projectDataRecord(authorReadingIdentifier, authorReadingTitle, authorReadingDate) { 22 | try{ 23 | // Set project ID with pattern AR-{{author reading identifier}} 24 | var generatedID = "AR-" + authorReadingIdentifier; 25 | // Set project start date 40 days before author reading date 26 | var moment = require("moment"); 27 | var generatedStartDate = moment(authorReadingDate).subtract(40, "days").toISOString().substring(0, 10) + "T00:00:00.0000000Z"; 28 | 29 | // Assemble project payload based the sample data provided by *SAP Business ByDesign Partner Demo Tenants* (reference systems) 30 | const projectRecord = { 31 | ProjectID: generatedID, 32 | EstimatedCompletionPercent: 10, 33 | ResponsibleCostCentreID: "S1111", 34 | ProjectTypeCode: "10", 35 | ProjectLanguageCode: "EN", 36 | PlannedStartDateTime: generatedStartDate, 37 | PlannedEndDateTime: authorReadingDate, 38 | ProjectSummaryTask: { 39 | ProjectName: authorReadingTitle, 40 | ResponsibleEmployeeID: "E0202", 41 | }, 42 | Task: [ 43 | { 44 | TaskID: generatedID + "-PREP", 45 | TaskName: "Event planning and preparations", 46 | PlannedDuration: "P30D", 47 | TaskRelationship: [ 48 | { 49 | DependencyTypeCode: "2", 50 | SuccessorTaskID: generatedID + "-EXE", 51 | LagDuration: "P2D", 52 | }, 53 | ], 54 | }, 55 | { 56 | TaskID: generatedID + "-EXE", 57 | TaskName: "Event administration and execution", 58 | PlannedDuration: "P5D", 59 | ConstraintEndDateTime: authorReadingDate, 60 | ScheduleActivityEndDateTimeConstraintTypeCode: "2", 61 | }, 62 | ], 63 | }; 64 | return projectRecord; 65 | }catch (error) { 66 | console.log(error); 67 | } 68 | } 69 | 70 | // Expand author readings to remote projects 71 | async function readProject(authorReadings) { 72 | try { 73 | const bydProject = await cds.connect.to('byd_khproject'); 74 | let isProjectIDs = false; 75 | const asArray = x => Array.isArray(x) ? x : [ x ]; 76 | 77 | // Read Project ID's related to ByD 78 | let projectIDs = []; 79 | for (const authorReading of asArray(authorReadings)) { 80 | // Check if the Project ID exists in the author reading record AND backend ERP is ByD => then read project information from ByD 81 | if(authorReading.projectSystem == "ByD" && authorReading.projectID ){ 82 | projectIDs.push(authorReading.projectID); 83 | isProjectIDs = true; 84 | } 85 | } 86 | 87 | // Read ByD projects data 88 | if(isProjectIDs){ 89 | 90 | // Request all associated projects 91 | const projects = await bydProject.run( SELECT.from('AuthorReadingManager.ByDProjects').where({ projectID: projectIDs }) ); 92 | 93 | // Convert in a map for easier lookup 94 | const projectsMap = {}; 95 | for (const project of projects) projectsMap[project.projectID] = project; 96 | 97 | // Assemble result 98 | for (const authorReading of asArray(authorReadings)) { 99 | authorReading.toByDProject = projectsMap[authorReading.projectID]; 100 | }; 101 | } 102 | return authorReadings; 103 | } catch (error) { 104 | // App reacts error tolerant in case of calling the remote service, mostly if the remote service is not available of if the destination is missing 105 | console.log("ACTION_READ_PROJECT_CONNECTION" + "; " + error); 106 | }; 107 | } 108 | 109 | // Publish constants and functions 110 | module.exports = { 111 | readProject, 112 | projectDataRecord, 113 | delegateODataRequests 114 | }; 115 | -------------------------------------------------------------------------------- /Applications/author-readings-mt/srv/connector-c4p.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | // Include cds libraries and reuse files 4 | const cds = require("@sap/cds"); 5 | 6 | // ---------------------------------------------------------------------------- 7 | // C4P specific reuse functions 8 | // ---------------------------------------------------------------------------- 9 | 10 | // Delegate OData requests to remote C4P project entities 11 | async function delegateODataRequests(req,remoteService) { 12 | try{ 13 | const c4pProject = await cds.connect.to(remoteService); 14 | return c4pProject.run(req.query); 15 | }catch (error) { 16 | console.log(error); 17 | } 18 | } 19 | 20 | // Return json-payload to create C4P projects 21 | async function projectDataRecord(authorReadingIdentifier, authorReadingTitle, authorReadingDate) { 22 | try{ 23 | // Set project ID with pattern PS-{{author reading identifier}} 24 | var generatedID = "PS-" + authorReadingIdentifier; 25 | 26 | // Set project start date 30 days before author reading date 27 | var moment = require("moment"); 28 | var generatedStartDate = moment(authorReadingDate).subtract(30, "days").toISOString().substring(0, 10); 29 | var generatedEndDate = moment(generatedStartDate).add(30, "days").toISOString().substring(0, 10); 30 | 31 | // Assemble project payload 32 | const projectRecord = { 33 | "displayId": generatedID, 34 | "projectName": authorReadingTitle, 35 | "startDate": generatedStartDate, 36 | "endDate": generatedEndDate, 37 | "location": "Dietmar-Hopp-Allee 15a, 69190 Walldorf, Germany", 38 | "description": "This project is created by the partner reference application for author readings and poetry slams.", 39 | }; 40 | return projectRecord; 41 | }catch (error) { 42 | console.log(error); 43 | } 44 | } 45 | 46 | // Expand author readings to remote projects 47 | async function readProject(authorReadings) { 48 | try { 49 | const c4pProject = await cds.connect.to('c4p_ProjectService'); 50 | let isProjectIDs = false; 51 | const asArray = x => Array.isArray(x) ? x : [ x ]; 52 | 53 | // Read Project ID's related to C4P 54 | let projectIDs = []; 55 | for (const authorReading of asArray(authorReadings)) { 56 | // Check if the Project ID exists in the author reading record AND backend ERP is C4P => then read project information from C4P 57 | if(authorReading.projectSystem == "C4P" && authorReading.projectID ){ 58 | projectIDs.push(authorReading.projectID); 59 | isProjectIDs = true; 60 | } 61 | } 62 | 63 | // Read C4P projects data 64 | if(isProjectIDs){ 65 | 66 | // Request all associated projects 67 | const projects = await c4pProject.run( SELECT.from('AuthorReadingManager.C4PProject').where({ displayId: projectIDs }) ); 68 | 69 | // Convert in a map for easier lookup 70 | const projectsMap = {}; 71 | for (const project of projects) projectsMap[project.displayId] = project; 72 | 73 | // Assemble result 74 | for (const authorReading of asArray(authorReadings)) { 75 | authorReading.toC4PProject = projectsMap[authorReading.projectID]; 76 | }; 77 | } 78 | return authorReadings; 79 | } catch (error) { 80 | // App reacts error tolerant in case of calling the remote service, mostly if the remote service is not available of if the destination is missing 81 | console.log("ACTION_READ_PROJECT_CONNECTION" + "; " + error); 82 | }; 83 | } 84 | 85 | // Publish constants and functions 86 | module.exports = { 87 | readProject, 88 | projectDataRecord, 89 | delegateODataRequests 90 | }; -------------------------------------------------------------------------------- /Applications/author-readings-mt/srv/connector-s4hc.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | // Include cds libraries and reuse files 4 | const cds = require("@sap/cds"); 5 | 6 | // ---------------------------------------------------------------------------- 7 | // S4HC specific reuse functions 8 | // ---------------------------------------------------------------------------- 9 | 10 | // Delegate OData requests to remote S4HC project entities 11 | async function delegateODataRequests(req,remoteService) { 12 | try{ 13 | const s4hcProject = await cds.connect.to(remoteService); 14 | return s4hcProject.run(req.query); 15 | }catch (error) { 16 | console.log(error); 17 | } 18 | } 19 | 20 | // Return json-payload to create S4HC projects 21 | async function projectDataRecord(authorReadingIdentifier, authorReadingTitle, authorReadingDate) { 22 | try{ 23 | // Set project ID with pattern PRA-{{author reading identifier}} 24 | var generatedID = "PRA-" + authorReadingIdentifier; 25 | var generatedPLANID = generatedID + "-PLAN"; 26 | var generatedEXEID = generatedID + "-EXE"; 27 | 28 | // Set project start date 30 days before author reading date 29 | var moment = require("moment"); 30 | var generatedStartDate = moment(authorReadingDate).subtract(30, "days").toISOString().substring(0, 10) + "T00:00:00.0000000Z"; 31 | var generatedEndDate = moment(authorReadingDate).toISOString().substring(0, 10) + "T00:00:00.0000000Z"; 32 | var generatedTask1EndDate = moment(authorReadingDate).subtract(4, "days").toISOString().substring(0, 10) + "T00:00:00.0000000Z"; 33 | var generatedTask2StartDate = moment(authorReadingDate).subtract(1, "days").toISOString().substring(0, 10) + "T00:00:00.0000000Z"; 34 | 35 | // Assemble project payload 36 | const projectRecord = { 37 | "Project": generatedID, 38 | "ProjectDescription": authorReadingTitle, 39 | "ProjectStartDate": generatedStartDate, 40 | "ProjectEndDate": generatedEndDate, 41 | "EntProjectIsConfidential": false, 42 | "ResponsibleCostCenter": "10101601", 43 | "ProfitCenter": "YB900", 44 | "ProjectProfileCode": "YP03", 45 | "ProjectCurrency": "EUR", 46 | "to_EnterpriseProjectElement": [ 47 | { 48 | "ProjectElement": generatedPLANID, 49 | "ProjectElementDescription": "Event planning and preparations", 50 | "PlannedStartDate": generatedStartDate, 51 | "PlannedEndDate": generatedTask1EndDate 52 | }, 53 | { 54 | "ProjectElement": generatedEXEID, 55 | "ProjectElementDescription": "Event administration and execution", 56 | "PlannedStartDate": generatedTask2StartDate, 57 | "PlannedEndDate": generatedEndDate 58 | } 59 | ] 60 | }; 61 | return projectRecord; 62 | }catch (error) { 63 | console.log(error); 64 | } 65 | } 66 | 67 | // Expand author readings to remote projects 68 | async function readProject(authorReadings) { 69 | try { 70 | const s4hcProject = await cds.connect.to('S4HC_API_ENTERPRISE_PROJECT_SRV_0002'); 71 | const s4hcProjectsProjectProfileCode = await cds.connect.to('S4HC_ENTPROJECTPROFILECODE_0001'); 72 | const s4hcProjectsProcessingStatus = await cds.connect.to('S4HC_ENTPROJECTPROCESSINGSTATUS_0001'); 73 | let isProjectIDs = false; 74 | const asArray = x => Array.isArray(x) ? x : [ x ]; 75 | 76 | // Read Project ID's related to S4HC 77 | let projectIDs = []; 78 | for (const authorReading of asArray(authorReadings)) { 79 | // Check if the Project ID exists in the author reading record AND backend ERP is S4HC => then read project information from S4HC 80 | if(authorReading.projectSystem == "S4HC" && authorReading.projectID ){ 81 | projectIDs.push(authorReading.projectID); 82 | isProjectIDs = true; 83 | } 84 | } 85 | 86 | // Read S4HC projects data 87 | if(isProjectIDs){ 88 | 89 | // Request all associated projects 90 | const projects = await s4hcProject.run( SELECT.from('AuthorReadingManager.S4HCProjects').where({ Project: projectIDs }) ); 91 | 92 | // Convert in a map for easier lookup 93 | const projectsMap = {}; 94 | for (const project of projects) projectsMap[project.Project] = project; 95 | 96 | // Assemble result 97 | for (const authorReading of asArray(authorReadings)) { 98 | authorReading.toS4HCProject = projectsMap[authorReading.projectID]; 99 | 100 | // Get Project Profile Code Text from S4HC 101 | var projectProfileCode = authorReading.toS4HCProject.ProjectProfileCode; 102 | const S4HCProjectsProjectProfileCodeRecords = await s4hcProjectsProjectProfileCode.run( SELECT.from('AuthorReadingManager.S4HCProjectsProjectProfileCode').where({ ProjectProfileCode: projectProfileCode }) ); 103 | for (const S4HCProjectsProjectProfileCodeRecord of S4HCProjectsProjectProfileCodeRecords) { 104 | authorReading.projectProfileCodeText = S4HCProjectsProjectProfileCodeRecord.ProjectProfileCodeText; 105 | } 106 | 107 | // Get Project Processing Status Text from S4HC 108 | var processingStatus = authorReading.toS4HCProject.ProcessingStatus;; 109 | const S4HCProjectsProcessingStatusRecords = await s4hcProjectsProcessingStatus.run( SELECT.from('AuthorReadingManager.S4HCProjectsProcessingStatus').where({ ProcessingStatus: processingStatus }) ); 110 | for (const S4HCProjectsProcessingStatusRecord of S4HCProjectsProcessingStatusRecords) { 111 | authorReading.processingStatusText = S4HCProjectsProcessingStatusRecord.ProcessingStatusText; 112 | } 113 | }; 114 | } 115 | return authorReadings; 116 | } catch (error) { 117 | // App reacts error tolerant in case of calling the remote service, mostly if the remote service is not available of if the destination is missing 118 | console.log("ACTION_READ_PROJECT_CONNECTION" + "; " + error); 119 | }; 120 | } 121 | 122 | // Publish constants and functions 123 | module.exports = { 124 | readProject, 125 | projectDataRecord, 126 | delegateODataRequests 127 | }; -------------------------------------------------------------------------------- /Applications/author-readings-mt/srv/external/S4HC_ENTPROJECTPROCESSINGSTATUS_0001.cds: -------------------------------------------------------------------------------- 1 | /* checksum : b25f54b418484e6f0af7f21d099f55fb */ 2 | @cds.external : true 3 | @cds.persistence.skip : true 4 | @Capabilities.SearchRestrictions : { 5 | Searchable: true, 6 | UnsupportedExpressions: #phrase 7 | } 8 | @Capabilities.InsertRestrictions : { Insertable: false } 9 | @Capabilities.DeleteRestrictions : { Deletable: false } 10 | @Capabilities.UpdateRestrictions : { 11 | Updatable: false, 12 | QueryOptions: { SelectSupported: true } 13 | } 14 | @Core.OptimisticConcurrency : [ ] 15 | @Capabilities.FilterRestrictions : { FilterExpressionRestrictions: [ { 16 | Property: ProcessingStatus, 17 | AllowedExpressions: 'MultiValue' 18 | }, { 19 | Property: ProcessingStatusText, 20 | AllowedExpressions: 'MultiValue' 21 | } ] } 22 | entity S4HC_ENTPROJECTPROCESSINGSTATUS_0001.ProcessingStatusText { 23 | @Common.Label : 'Language Key' 24 | @Common.Heading : 'Language' 25 | key Language : String(2) not null; 26 | @Common.Text : { $Path: 'ProcessingStatusText' } 27 | @Common.IsUpperCase : true 28 | @Common.Label : 'Processing Status' 29 | key ProcessingStatus : String(2) not null; 30 | @Common.IsUpperCase : true 31 | @Common.Label : 'Status' 32 | @Common.Heading : 'Processing Status Text' 33 | @Common.QuickInfo : 'Processing Status Text' 34 | ProcessingStatusText : String(60) not null; 35 | @cds.ambiguous : 'missing on condition?' 36 | _ProcessingStatus : Association to one S4HC_ENTPROJECTPROCESSINGSTATUS_0001.ProcessingStatus on _ProcessingStatus.ProcessingStatus = ProcessingStatus; 37 | }; 38 | 39 | @cds.external : true 40 | @cds.persistence.skip : true 41 | @Capabilities.SearchRestrictions : { 42 | Searchable: true, 43 | UnsupportedExpressions: #phrase 44 | } 45 | @Capabilities.InsertRestrictions : { Insertable: false } 46 | @Capabilities.DeleteRestrictions : { Deletable: false } 47 | @Capabilities.UpdateRestrictions : { 48 | Updatable: false, 49 | QueryOptions: { SelectSupported: true } 50 | } 51 | @Core.OptimisticConcurrency : [ ] 52 | @Capabilities.FilterRestrictions : { FilterExpressionRestrictions: [ { 53 | Property: ProcessingStatus, 54 | AllowedExpressions: 'MultiValue' 55 | }, { 56 | Property: ProcessingStatusText, 57 | AllowedExpressions: 'MultiValue' 58 | } ] } 59 | entity S4HC_ENTPROJECTPROCESSINGSTATUS_0001.ProcessingStatus { 60 | @Common.Text : { $Path: 'ProcessingStatusText' } 61 | @Common.IsUpperCase : true 62 | @Common.Label : 'Processing Status' 63 | key ProcessingStatus : String(2) not null; 64 | @Common.IsUpperCase : true 65 | @Common.Label : 'Status' 66 | @Common.Heading : 'Processing Status Text' 67 | @Common.QuickInfo : 'Processing Status Text' 68 | ProcessingStatusText : String(60) not null; 69 | @cds.ambiguous : 'missing on condition?' 70 | @Common.Composition : null 71 | _ProcessingStatusText : Composition of many S4HC_ENTPROJECTPROCESSINGSTATUS_0001.ProcessingStatusText; 72 | }; 73 | 74 | @cds.external : true 75 | @Aggregation.ApplySupported : { 76 | Transformations: [ 'aggregate', 'groupby', 'filter' ], 77 | Rollup: #None 78 | } 79 | @Common.ApplyMultiUnitBehaviorForSortingAndFiltering : true 80 | @Capabilities.FilterFunctions : [ 'eq', 'ne', 'gt', 'ge', 'lt', 'le', 'and', 'or', 'contains', 'startswith', 'endswith', 'any', 'all' ] 81 | @Capabilities.SupportedFormats : [ 'application/json', 'application/pdf' ] 82 | service S4HC_ENTPROJECTPROCESSINGSTATUS_0001 {}; 83 | 84 | -------------------------------------------------------------------------------- /Applications/author-readings-mt/srv/external/S4HC_ENTPROJECTPROFILECODE_0001.cds: -------------------------------------------------------------------------------- 1 | /* checksum : 13e587f74abded43d3b4b29d2579f7fc */ 2 | @cds.external : true 3 | @cds.persistence.skip : true 4 | @Capabilities.SearchRestrictions : { 5 | Searchable: true, 6 | UnsupportedExpressions: #phrase 7 | } 8 | @Capabilities.InsertRestrictions : { Insertable: false } 9 | @Capabilities.DeleteRestrictions : { Deletable: false } 10 | @Capabilities.UpdateRestrictions : { 11 | Updatable: false, 12 | QueryOptions: { SelectSupported: true } 13 | } 14 | @Core.OptimisticConcurrency : [ ] 15 | @Capabilities.FilterRestrictions : { FilterExpressionRestrictions: [ { 16 | Property: ProjectProfileCode, 17 | AllowedExpressions: 'MultiValue' 18 | } ] } 19 | entity S4HC_ENTPROJECTPROFILECODE_0001.ProjectProfileCode { 20 | @Common.SAPObjectNodeTypeReference : 'ProjectProfileCode' 21 | @Common.Text : { $Path: 'ProjectProfileCode' } 22 | @Common.IsUpperCase : true 23 | @Common.Label : 'Project Profile' 24 | @Common.Heading : 'Prj.Prf' 25 | key ProjectProfileCode : String(7) not null; 26 | @Common.Label : 'Description' 27 | @Common.QuickInfo : 'Text for Profile' 28 | ProjectProfileCodeText : String(40) not null; 29 | @cds.ambiguous : 'missing on condition?' 30 | @Common.Composition : null 31 | _ProjectProfileCodeText : Composition of many S4HC_ENTPROJECTPROFILECODE_0001.ProjectProfileCodeText; 32 | }; 33 | 34 | @cds.external : true 35 | @cds.persistence.skip : true 36 | @Capabilities.SearchRestrictions : { 37 | Searchable: true, 38 | UnsupportedExpressions: #phrase 39 | } 40 | @Capabilities.InsertRestrictions : { Insertable: false } 41 | @Capabilities.DeleteRestrictions : { Deletable: false } 42 | @Capabilities.UpdateRestrictions : { 43 | Updatable: false, 44 | QueryOptions: { SelectSupported: true } 45 | } 46 | @Core.OptimisticConcurrency : [ ] 47 | @Capabilities.FilterRestrictions : { FilterExpressionRestrictions: [ { 48 | Property: ProjectProfileCode, 49 | AllowedExpressions: 'MultiValue' 50 | } ] } 51 | entity S4HC_ENTPROJECTPROFILECODE_0001.ProjectProfileCodeText { 52 | @Common.Label : 'Language Key' 53 | @Common.Heading : 'Language' 54 | key Language : String(2) not null; 55 | @Common.Text : { $Path: 'ProjectProfileCode' } 56 | @Common.IsUpperCase : true 57 | @Common.Label : 'Project Profile' 58 | @Common.Heading : 'Prj.Prf' 59 | key ProjectProfileCode : String(7) not null; 60 | @Common.Label : 'Description' 61 | @Common.QuickInfo : 'Text for Profile' 62 | ProjectProfileCodeText : String(40) not null; 63 | @cds.ambiguous : 'missing on condition?' 64 | _ProjectProfileCode : Association to one S4HC_ENTPROJECTPROFILECODE_0001.ProjectProfileCode on _ProjectProfileCode.ProjectProfileCode = ProjectProfileCode; 65 | }; 66 | 67 | @cds.external : true 68 | @Aggregation.ApplySupported : { 69 | Transformations: [ 'aggregate', 'groupby', 'filter' ], 70 | Rollup: #None 71 | } 72 | @Common.ApplyMultiUnitBehaviorForSortingAndFiltering : true 73 | @Capabilities.FilterFunctions : [ 'eq', 'ne', 'gt', 'ge', 'lt', 'le', 'and', 'or', 'contains', 'startswith', 'endswith', 'any', 'all' ] 74 | @Capabilities.SupportedFormats : [ 'application/json', 'application/pdf' ] 75 | service S4HC_ENTPROJECTPROFILECODE_0001 {}; 76 | 77 | -------------------------------------------------------------------------------- /Applications/author-readings-mt/srv/i18n/messages.properties: -------------------------------------------------------------------------------- 1 | # Service translation / default language 2 | 3 | #Texts for manifest.json 4 | 5 | #XTIT: Application name 6 | appTitle=Author Readings 7 | 8 | #YDES: Application description 9 | appDescription=Manage author readings 10 | 11 | # ------------------------------------------------------------------------------------- 12 | # System Messages 13 | 14 | INVALID_EMAIL = Invalid Email ID: {0}, please enter valid email 15 | INVALID_MOBILE_NUMBER = Invalid Mobile Number: {0}, please enter valid mobile number 16 | 17 | PARTICIPANT_AUTHOR_UNKNOWN = Cannot add participant: Author reading not found 18 | PARTICIPANT_FULLY_BOOKED = Cannot add participants: author reading is fully booked 19 | PARTICIPANT_AUTHOR_READING_BLOCKED = Cannot add participant: Author reading is blocked 20 | PARTICIPANT_AUTHOR_READING_IN_PREPARATION = Cannot add participant: Author reading is in preparation 21 | PARTICIPANT_ALREADY_CANCELLED = Participation has already been cancelled 22 | 23 | ACTION_BLOCK_SUCCESS = Author Reading {0} blocked successfully 24 | ACTION_BLOCK_NOT_POSSIBLE = Autor Reading {0} cannot be blocked 25 | 26 | ACTION_PUBLISH_SUCCESS = Author Reading {0} published successfully 27 | ACTION_PUBLISH_NOT_POSSIBLE = Autor Reading {0} cannot be published 28 | 29 | ACTION_CREATE_PROJECT_DRAFT = Projects cannot be created for draft author readings 30 | ACTION_CREATE_PROJECT_CONNECTION = Project cannot be created 31 | 32 | ACTION_READ_PROJECT_CONNECTION = Project cannot be retrieved 33 | 34 | ACTION_CONFIRM_PARTICIPATION_SUCCESS = Participation of participant {0} successfully confirmed 35 | ACTION_CONFIRM_PARTICIPATION_NOT_POSSIBLE = Participation of participant {0} could not be confirmed 36 | ACTION_CONFIRM_PARTICIPATION_ALREADY_DONE = Participation of participant {0} is already confirmed 37 | ACTION_CONFIRM_PARTICIPATION_FULLY_BOOKED = Participant {0} could not be confirmed; the event is fully booked 38 | ACTION_CONFIRM_PARTICIPATION_BLOCKED = The author reading event is blocked; participants can not register in this status 39 | ACTION_CONFIRM_PARTICIPATION_DRAFT = The author reading event is in draft mode; participants can not register in this status 40 | 41 | ACTION_CANCEL_PARTICIPATION_SUCCESS = Participation of participant {0} cancelled successfully 42 | ACTION_CANCEL_PARTICIPATION_NOT_POSSIBLE = Participation of participant {0} cancellation failed 43 | ACTION_CANCEL_PARTICIPATION_DRAFT = Draft participants cannot be cancelled 44 | 45 | EMIT_MESSAGE_SUCCESS = Event Message for Author Reading {0} and topic {1} emitted successully 46 | GET_DESTINATION = Reading the connection information for the remote system failed 47 | -------------------------------------------------------------------------------- /Applications/author-readings-mt/srv/i18n/messages_de.properties: -------------------------------------------------------------------------------- 1 | # Service model translation / German 2 | 3 | #Texts for manifest.json 4 | 5 | #XTIT: Application name 6 | appTitle = Autorenlesungen 7 | 8 | #YDES: Application description 9 | appDescription = Plane Autorenlesungen und Poetry Slams 10 | 11 | # ------------------------------------------------------------------------------------- 12 | # System Messages 13 | 14 | INVALID_EMAIL = Ungültige E-Mail: {0}, gebe eine gültige E-Mail-Adresse ein 15 | INVALID_MOBILE_NUMBER = Ungültige Telefonnummer: {0}, gebe eine gültige Telefonnummer ein 16 | 17 | PARTICIPANT_AUTHOR_UNKNOWN = Teilnehmer kann nicht hinzugefügt werden: Autorenlesung nicht gefunden 18 | PARTICIPANT_FULLY_BOOKED = Teilnehmer kann nicht hinzugefügt werden: Keine freien Plätze verfügbar 19 | PARTICIPANT_AUTHOR_READING_BLOCKED = Teilnehmer kann nicht hinzugefügt werden: Autorenlesung ist abgesagt 20 | PARTICIPANT_AUTHOR_READING_IN_PREPARATION = Teilnehmer kann nicht hinzugefügt werden: Autorenlesung noch nicht veröffentlicht 21 | PARTICIPANT_ALREADY_CANCELLED = Die Teilnahme wurde storniert 22 | 23 | ACTION_BLOCK_SUCCESS = Autorenlesung {0} erfolgreich abgesagt 24 | ACTION_BLOCK_NOT_POSSIBLE = Autorenlesung {0} kann nicht abgesagt werden 25 | 26 | ACTION_PUBLISH_SUCCESS = Autorenlesung {0} erfolgreich veröffentlicht 27 | ACTION_PUBLISH_NOT_POSSIBLE = Autorenlesung {0} kann nicht veröffentlicht werden 28 | 29 | ACTION_CREATE_PROJECT_DRAFT = Es können keine Projekte für Autorenlesungen in Bearbeitung erstellt werden 30 | ACTION_CREATE_PROJECT_CONNECTION = Projekt kann nicht erstellt werden 31 | 32 | ACTION_READ_PROJECT_CONNECTION = Projekt kann nicht gelesen werden 33 | 34 | ACTION_CONFIRM_PARTICIPATION_SUCCESS = Teilnahme des Teilnehmers {0} wurde gebucht 35 | ACTION_CONFIRM_PARTICIPATION_NOT_POSSIBLE = Teilnahme des Teilnehmers {0} kann nicht bestätigt werden 36 | ACTION_CONFIRM_PARTICIPATION_ALREADY_DONE = Teilnahme des Teilnehmers {0} wurde bereits bestätigt 37 | ACTION_CONFIRM_PARTICIPATION_FULLY_BOOKED = Teilnehmer {0} kann nicht bestätigt werden da das Event ausgebucht ist 38 | ACTION_CONFIRM_PARTICIPATION_BLOCKED = Das Event ist abgesagt; Teilnehmer können nicht mehr bestätigt werden 39 | ACTION_CONFIRM_PARTICIPATION_DRAFT = Das Event wird gerade geändert; Teilnehmer können in diesem Status nicht bestätigt werden 40 | 41 | ACTION_CANCEL_PARTICIPATION_SUCCESS = Teilnahme des Teilnehmers {0} erfolgreich storniert 42 | ACTION_CANCEL_PARTICIPATION_NOT_POSSIBLE = Teilnahme des Teilnehmers {0} konnte nicht strorniert werden 43 | ACTION_CANCEL_PARTICIPATION_DRAFT = Teilnehmer in Bearbeitung können nicht stornert werden 44 | 45 | EMIT_MESSAGE_SUCCESS = Event-Nachricht für Autorenlesung {0} und Topic {1} gesendet 46 | GET_DESTINATION = Die Verbindungsdaten zum ERP-System konnten nicht gelesen werden 47 | -------------------------------------------------------------------------------- /Applications/author-readings-mt/srv/reuse.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | // Include SAP Cloud SDK reuse functions 4 | const { getDestination, retrieveJwt } = require("@sap-cloud-sdk/connectivity"); 5 | 6 | // ---------------------------------------------------------------------------- 7 | // Constants 8 | // ---------------------------------------------------------------------------- 9 | 10 | const color = { 11 | grey: 0, 12 | red: 1, 13 | yellow: 2, 14 | green: 3 15 | }; 16 | 17 | const authorReadingStatusCode = { 18 | inPreparation: 0, 19 | published: 1, 20 | booked: 2, 21 | completed: 3, // not used 22 | blocked: 4, 23 | cancelled: 5 // not used 24 | }; 25 | 26 | const participantStatusCode = { 27 | inProcess: 1, 28 | confirmed: 2, 29 | cancelled: 3 30 | }; 31 | 32 | // ---------------------------------------------------------------------------- 33 | // Reuse functions 34 | // ---------------------------------------------------------------------------- 35 | 36 | // Reuse function to check the formating of an e-mail address 37 | function validateEmail(email) { 38 | const regexEmail = /^\w+([\\.-]?\w+)*@\w+([\\.-]?\w+)*(\.\w{2,3})+$/; 39 | if (email.match(regexEmail)) { 40 | return true; 41 | } else { 42 | return false; 43 | } 44 | } 45 | 46 | // Reuse function to check the formating of an phone number 47 | function validatePhone(phone) { 48 | const regexPhone = /^\+(?:[0-9] ?){6,14}[0-9]$/; 49 | if (phone.match(regexPhone)) { 50 | return true; 51 | } else { 52 | return false; 53 | } 54 | } 55 | 56 | // Emit event message to event mesh 57 | async function emitAuthorReadingEvent(req, id, eventMeshTopic) { 58 | 59 | /* 60 | // Return updated reading event data 61 | const authorReadings = await SELECT.from("sap.samples.authorreadings.AuthorReadings").where({ ID: id }); 62 | const authorReading = authorReadings[0]; 63 | 64 | try { 65 | const msg = await cds.connect.to("outbound_messaging"); 66 | await msg.emit( eventMeshTopic, { authorReading, tenant:req.user.tenant } ); 67 | console.log( "====== Inside reuse function to emit Author Reading event messages ======" ); 68 | console.log( `Event message emitted for topic ${eventMeshTopic} and author reading ${authorReading.identifier} and Tenant ID:${req.user.tenant} ` ); 69 | 70 | req.info(200, 'EMIT_MESSAGE_SUCCESS', [authorReading.identifier, eventMeshTopic]); 71 | 72 | const text = `Event notification for topic ${eventMeshTopic} emitted successully.`; 73 | let eventMessages; 74 | if (authorReading.eventMeshMessage) { 75 | eventMessages = authorReading.eventMeshMessage + "\n" + text; 76 | } else { 77 | eventMessages = text; 78 | }; 79 | console.log( "Event message log: ", eventMessages); 80 | 81 | let authorReadingUpdate = await UPDATE("sap.samples.authorreadings.AuthorReadings") 82 | .set({ eventMeshMessage: eventMessages }) 83 | .where({ ID: id }); 84 | if (authorReadingUpdate) { console.log( "Event message log update successfull") } 85 | } catch (error) { 86 | req.error(error); 87 | } 88 | */ 89 | 90 | } 91 | 92 | // Reuse function to get the ERP URL 93 | async function getDestinationURL(req, destinationName) { 94 | let destinationURL; 95 | try { 96 | // Read the destination details using the SAP Cloud SDK reusable getDestination function: 97 | // The JWT-token contains the subaccount information, such that the function works for single tenant as well as for multi-tenant apps: 98 | // - Single tenant: Get destination from the subaccount that hosts the app. 99 | // - Multi tenant: Get destination from subscriber subaccount. 100 | const destination = await getDestination({ destinationName: destinationName, jwt: retrieveJwt(req) }); 101 | 102 | if(destination){ 103 | console.log("Get ERP destination URL: " + destination.url); 104 | destinationURL = destination.url; 105 | } 106 | else{ 107 | // No destination found 108 | console.log("Get ERP destination URL: " + destinationName + " not found"); 109 | } 110 | } catch (error) { 111 | // App reacts error tolerant if the destination cannot be retrieved 112 | console.log("GET_DESTINATION" + "; " + error); 113 | } 114 | return destinationURL; 115 | } 116 | 117 | // Reuse function to check if BTP destination exists 118 | async function checkDestination(req, destinationName) { 119 | try { 120 | // Check if the destination exist using the SAP Cloud SDK reusable getDestination function: 121 | // The JWT-token contains the subaccount information, such that the function works for single tenant as well as for multi-tenant apps: 122 | // - Single tenant: Get destination from the subaccount that hosts the app. 123 | // - Multi tenant: Get destination from subscriber subaccount. 124 | const destination = await getDestination({ destinationName: destinationName, jwt: retrieveJwt(req) }); 125 | 126 | if(destination){ 127 | console.log("Check ERP destination: " + destinationName + " found"); 128 | return true; 129 | } 130 | else{ 131 | console.log("Check ERP destination: " + destinationName + " not found"); 132 | return false; 133 | } 134 | } catch (error) { 135 | // App reacts error tolerant if the destination is missing 136 | console.log("CHECK_DESTINATION" + "; " + error); 137 | } 138 | } 139 | 140 | // Reuse function to get the ERP Name 141 | async function getDestinationDescription(req, destinationName) { 142 | let destinationDescription; 143 | try { 144 | // Read the destination details using the SAP Cloud SDK reusable getDestinationDescription function: 145 | // The JWT-token contains the subaccount information, such that the function works for single tenant as well as for multi-tenant apps: 146 | // - Single tenant: Get destination from the subaccount that hosts the app. 147 | // - Multi tenant: Get destination from subscriber subaccount. 148 | const destination = await getDestination({ destinationName: destinationName, jwt: retrieveJwt(req) }); 149 | if(destination){ 150 | for(var originalProperty in destination.originalProperties){ 151 | if (originalProperty == "Description"){ 152 | destinationDescription = destination.originalProperties[originalProperty]; 153 | break; 154 | } 155 | } 156 | } 157 | } catch (error) { 158 | // App reacts error tolerant if the destination is missing 159 | console.log("GET_DESTINATION_DESCRIPTION" + "; " + error); 160 | } 161 | return destinationDescription; 162 | } 163 | 164 | 165 | // Publish constants and functions 166 | module.exports = { 167 | color, 168 | authorReadingStatusCode, 169 | participantStatusCode, 170 | validateEmail, 171 | validatePhone, 172 | emitAuthorReadingEvent, 173 | getDestinationURL, 174 | checkDestination, 175 | getDestinationDescription 176 | }; -------------------------------------------------------------------------------- /Applications/author-readings-mt/srv/service-auth.cds: -------------------------------------------------------------------------------- 1 | using {AuthorReadingManager} from './service-models'; 2 | 3 | // ---------------------------------------------------------------------------- 4 | // Required authorization roles 5 | annotate AuthorReadingManager with @(requires : [ 6 | 'AuthorReadingManagerRole', 7 | 'AuthorReadingAdminRole' 8 | ]); 9 | 10 | // ---------------------------------------------------------------------------- 11 | // Restriction per authorization role: 12 | 13 | // Managers can read all author readings, create new author readings and change their own author readings 14 | // Administrators have no restrictions 15 | annotate AuthorReadingManager.AuthorReadings with @(restrict : [ 16 | { 17 | grant : [ 18 | 'READ', 19 | 'CREATE' 20 | ], 21 | to : 'AuthorReadingManagerRole' 22 | }, 23 | { 24 | grant : ['*'], 25 | to : 'AuthorReadingManagerRole', 26 | where : 'createdBy = $user' 27 | }, 28 | { 29 | grant : ['*'], 30 | to : 'AuthorReadingAdminRole' 31 | } 32 | ]); 33 | 34 | // Managers can read all participants, add new participants, change participants they added themseves 35 | // Administrators have no restrictions 36 | annotate AuthorReadingManager.Participants with @(restrict : [ 37 | { 38 | grant : [ 39 | 'READ', 40 | 'CREATE' 41 | ], 42 | to : 'AuthorReadingManagerRole' 43 | }, 44 | { 45 | grant : ['*'], 46 | to : 'AuthorReadingManagerRole', 47 | where : 'createdBy = $user' 48 | }, 49 | { 50 | grant : ['*'], 51 | to : 'AuthorReadingAdminRole' 52 | } 53 | ]); 54 | 55 | // ByD projects: Managers and Administrators can read and create remote projects 56 | annotate AuthorReadingManager.ByDProjects with @(restrict : [ 57 | { 58 | grant : ['*'], 59 | to : 'AuthorReadingManagerRole', 60 | }, 61 | { 62 | grant : ['*'], 63 | to : 'AuthorReadingAdminRole' 64 | } 65 | ]); 66 | annotate AuthorReadingManager.ByDProjectSummaryTasks with @(restrict : [ 67 | { 68 | grant : ['*'], 69 | to : 'AuthorReadingManagerRole', 70 | }, 71 | { 72 | grant : ['*'], 73 | to : 'AuthorReadingAdminRole' 74 | } 75 | ]); 76 | annotate AuthorReadingManager.ByDProjectTasks with @(restrict : [ 77 | { 78 | grant : ['*'], 79 | to : 'AuthorReadingManagerRole', 80 | }, 81 | { 82 | grant : ['*'], 83 | to : 'AuthorReadingAdminRole' 84 | } 85 | ]); 86 | annotate AuthorReadingManager.ByDProjectsTechUser with @(restrict : [ 87 | { 88 | grant : ['*'], 89 | to : 'AuthorReadingManagerRole', 90 | }, 91 | { 92 | grant : ['*'], 93 | to : 'AuthorReadingAdminRole' 94 | } 95 | ]); 96 | 97 | // S4HC projects: Managers and Administrators can read and create remote projects 98 | annotate AuthorReadingManager.S4HCProjects with @(restrict : [ 99 | { 100 | grant : ['*'], 101 | to : 'AuthorReadingManagerRole', 102 | }, 103 | { 104 | grant : ['*'], 105 | to : 'AuthorReadingAdminRole' 106 | } 107 | ]); 108 | annotate AuthorReadingManager.S4HCEnterpriseProjectElement with @(restrict : [ 109 | { 110 | grant : ['*'], 111 | to : 'AuthorReadingManagerRole', 112 | }, 113 | { 114 | grant : ['*'], 115 | to : 'AuthorReadingAdminRole' 116 | } 117 | ]); 118 | annotate AuthorReadingManager.S4HCEntProjTeamMember with @(restrict : [ 119 | { 120 | grant : ['*'], 121 | to : 'AuthorReadingManagerRole', 122 | }, 123 | { 124 | grant : ['*'], 125 | to : 'AuthorReadingAdminRole' 126 | } 127 | ]); 128 | annotate AuthorReadingManager.S4HCEntProjEntitlement with @(restrict : [ 129 | { 130 | grant : ['*'], 131 | to : 'AuthorReadingManagerRole', 132 | }, 133 | { 134 | grant : ['*'], 135 | to : 'AuthorReadingAdminRole' 136 | } 137 | ]); 138 | annotate AuthorReadingManager.S4HCProjectsProjectProfileCode with @(restrict : [ 139 | { 140 | grant : ['*'], 141 | to : 'AuthorReadingManagerRole', 142 | }, 143 | { 144 | grant : ['*'], 145 | to : 'AuthorReadingAdminRole' 146 | } 147 | ]); 148 | annotate AuthorReadingManager.S4HCProjectsProcessingStatus with @(restrict : [ 149 | { 150 | grant : ['*'], 151 | to : 'AuthorReadingManagerRole', 152 | }, 153 | { 154 | grant : ['*'], 155 | to : 'AuthorReadingAdminRole' 156 | } 157 | ]); 158 | 159 | // C4P projects: Managers and Administrators can read and create remote projects 160 | annotate AuthorReadingManager.C4PProject with @(restrict : [ 161 | { 162 | grant : ['*'], 163 | to : 'AuthorReadingManagerRole', 164 | }, 165 | { 166 | grant : ['*'], 167 | to : 'AuthorReadingAdminRole' 168 | } 169 | ]); 170 | annotate AuthorReadingManager.C4PTask with @(restrict : [ 171 | { 172 | grant : ['*'], 173 | to : 'AuthorReadingManagerRole', 174 | }, 175 | { 176 | grant : ['*'], 177 | to : 'AuthorReadingAdminRole' 178 | } 179 | ]); -------------------------------------------------------------------------------- /Applications/author-readings-mt/test/authorreading.test.js: -------------------------------------------------------------------------------- 1 | "strict" 2 | const chai = require("chai") 3 | const chaiHttp = require("chai-http") 4 | const server = require("./index") 5 | 6 | // Configure chai 7 | const assert = chai.assert 8 | chai.use(chaiHttp) 9 | chai.should(); 10 | 11 | let app = null 12 | before(async () => { 13 | app = await server 14 | }) 15 | 16 | const API_ENDPOINT = "/authorreadingmanager" 17 | 18 | describe("API Test - GET", () => { 19 | 20 | const entities = ["AuthorReadings", "AuthorReadingStatusCodes", "Participants", "ParticipantStatusCodes", "Currencies"]; 21 | entities.forEach(entity => { 22 | it(`should be able to read ${entity}`, (done) => { 23 | chai.request(app) 24 | .get(`${API_ENDPOINT}/${entity}`) 25 | .end((error, response) => { 26 | try { 27 | response.should.have.status(200); 28 | done(); 29 | } catch (error) { 30 | done(error); 31 | } 32 | }); 33 | }) 34 | }) 35 | }) 36 | 37 | describe("API Test - Author Reading", () => { 38 | 39 | 40 | 41 | 42 | }) -------------------------------------------------------------------------------- /Applications/author-readings-mt/test/index.js: -------------------------------------------------------------------------------- 1 | const cds = require("@sap/cds") 2 | 3 | module.exports = new Promise(async (resolve) => { 4 | await cds.deploy("*").to("sqlite:test.db") 5 | cds.exec("run", "--with-mocks", "--in-memory?") 6 | cds.on("listening", () => { 7 | resolve(cds.app) 8 | }) 9 | }) -------------------------------------------------------------------------------- /Applications/author-readings-mt/xs-security.json: -------------------------------------------------------------------------------- 1 | { 2 | "scopes": [ 3 | { 4 | "name": "$XSAPPNAME.AuthorReadingManagerRole", 5 | "description": "AuthorReadingManagerRole" 6 | }, 7 | { 8 | "name": "$XSAPPNAME.AuthorReadingAdminRole", 9 | "description": "AuthorReadingAdminRole" 10 | }, 11 | { 12 | "name": "$XSAPPNAME.authorreadingsapi", 13 | "description": "authorreadingsapi" 14 | }, 15 | { 16 | "name": "$XSAPPNAME.MtxDiagnose", 17 | "description": "Diagnose MTX" 18 | }, 19 | { 20 | "name": "$XSAPPNAME.mtcallback", 21 | "description": "Subscribe to applications", 22 | "grant-as-authority-to-apps": [ 23 | "$XSAPPNAME(application,sap-provisioning,tenant-onboarding)" 24 | ] 25 | }, 26 | { 27 | "name": "$XSAPPNAME.Callback", 28 | "description": "Multi Tenancy Callback Access (approuter)", 29 | "grant-as-authority-to-apps": [ 30 | "$XSAPPNAME(application,sap-provisioning,tenant-onboarding)" 31 | ] 32 | }, 33 | { 34 | "name": "$XSAPPNAME.mtdeployment", 35 | "description": "Deploy applications" 36 | } 37 | ], 38 | "attributes": [], 39 | "role-templates": [ 40 | { 41 | "name": "AuthorReadingManagerRole", 42 | "description": "generated", 43 | "scope-references": [ 44 | "$XSAPPNAME.AuthorReadingManagerRole", 45 | "$XSAPPNAME.authorreadingsapi" 46 | ], 47 | "attribute-references": [] 48 | }, 49 | { 50 | "name": "AuthorReadingAdminRole", 51 | "description": "generated", 52 | "scope-references": [ 53 | "$XSAPPNAME.AuthorReadingAdminRole", 54 | "$XSAPPNAME.authorreadingsapi" 55 | ], 56 | "attribute-references": [] 57 | }, 58 | { 59 | "name": "MultitenancyAdministrator", 60 | "description": "Administrate multitenant applications", 61 | "scope-references": [ 62 | "$XSAPPNAME.MtxDiagnose", 63 | "$XSAPPNAME.mtdeployment", 64 | "$XSAPPNAME.mtcallback" 65 | ] 66 | } 67 | ], 68 | "role-collections": [ 69 | { 70 | "name": "AuthorReadingManagerRoleCollection", 71 | "description": "Author Reading Manager", 72 | "role-template-references": [ 73 | "$XSAPPNAME.AuthorReadingManagerRole" 74 | ] 75 | }, 76 | { 77 | "name": "AuthorReadingAdminRoleCollection", 78 | "description": "Author Readings Administrator", 79 | "role-template-references": [ 80 | "$XSAPPNAME.AuthorReadingAdminRole" 81 | ] 82 | } 83 | ], 84 | "authorities": [ 85 | "$XSAPPNAME.MtxDiagnose", 86 | "$XSAPPNAME.mtdeployment", 87 | "$XSAPPNAME.mtcallback", 88 | "$XSAPPNAME.AuthorReadingManagerRole", 89 | "$XSAPPNAME.AuthorReadingAdminRole" 90 | ] 91 | } -------------------------------------------------------------------------------- /Applications/author-readings/.cdsrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "requires": { 3 | "[development]": { 4 | "auth": { 5 | "kind": "mocked", 6 | "users": { 7 | "Kate Jacob": { 8 | "password": "welcome", 9 | "ID": "kjacob", 10 | "roles": [ 11 | "AuthorReadingManagerRole", 12 | "authenticated-user" 13 | ] 14 | }, 15 | "Peter Sellers": { 16 | "password": "welcome", 17 | "ID": "pseller", 18 | "roles": [ 19 | "AuthorReadingAdminRole", 20 | "authenticated-user" 21 | ] 22 | }, 23 | "Julia Brunner": { 24 | "password": "welcome", 25 | "ID": "jbrunner", 26 | "roles": [ 27 | "authenticated-user" 28 | ] 29 | }, 30 | "*": true 31 | } 32 | } 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /Applications/author-readings/.npmrc: -------------------------------------------------------------------------------- 1 | strict-ssl=false 2 | registry=https://registry.npmjs.com/ 3 | @sap:registry=https://registry.npmjs.com/ 4 | -------------------------------------------------------------------------------- /Applications/author-readings/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. 3 | // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp 4 | 5 | // List of extensions which should be recommended for users of this workspace. 6 | "recommendations": [ 7 | "SAPSE.vscode-cds", 8 | "dbaeumer.vscode-eslint", 9 | "esbenp.prettier-vscode", 10 | "mechatroner.rainbow-csv", 11 | "humao.rest-client", 12 | "alexcvzz.vscode-sqlite", 13 | "hbenl.vscode-mocha-test-adapter", 14 | "sdras.night-owl" 15 | ], 16 | // List of extensions recommended by VS Code that should not be recommended for users of this workspace. 17 | "unwantedRecommendations": [ 18 | 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /Applications/author-readings/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "command": "cds run --with-mocks --in-memory?", 9 | "name": "cds run", 10 | "request": "launch", 11 | "type": "node-terminal", 12 | "skipFiles": [ 13 | "/**" 14 | ] 15 | }, 16 | { 17 | "command": "cds run --profile sandbox --with-mocks --in-memory?", 18 | "name": "cds run Sandbox", 19 | "request": "launch", 20 | "type": "node-terminal", 21 | "skipFiles": [ 22 | "/**" 23 | ] 24 | }, 25 | { 26 | "command": "cds run --profile production --with-mocks --in-memory?", 27 | "name": "cds run Production", 28 | "request": "launch", 29 | "type": "node-terminal", 30 | "skipFiles": [ 31 | "/**" 32 | ] 33 | } 34 | ] 35 | } -------------------------------------------------------------------------------- /Applications/author-readings/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": { 3 | "**/.gitignore": true, 4 | "**/.git": true, 5 | "**/.vscode": true 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Applications/author-readings/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "shell", 8 | "label": "cds watch", 9 | "command": "cds", 10 | "args": ["watch"], 11 | "group": { 12 | "kind": "build", 13 | "isDefault": true 14 | }, 15 | "problemMatcher": [] 16 | }, 17 | { 18 | "type": "shell", 19 | "label": "cds run", 20 | "command": "cds", 21 | "args": ["run", "--with-mocks", "--in-memory?"], 22 | "problemMatcher": [] 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /Applications/author-readings/app/authorreadingmanager/README.md: -------------------------------------------------------------------------------- 1 | ## Application Details 2 | | | 3 | | ------------- | 4 | |**Generation Date and Time**
Tue Apr 05 2022 14:53:44 GMT+0000 (Coordinated Universal Time)| 5 | |**App Generator**
@sap/generator-fiori-elements| 6 | |**App Generator Version**
1.5.3| 7 | |**Generation Platform**
SAP Business Application Studio| 8 | |**Floorplan Used**
List Report Object Page V4| 9 | |**Service Type**
Local Cap| 10 | |**Service URL**
/authorreadingmanager/ 11 | |**Module Name**
authorreadingmanager| 12 | |**Application Title**
Manage Author Readings| 13 | |**Namespace**
| 14 | |**UI5 Theme**
sap_fiori_3_dark| 15 | |**UI5 Version**
1.100.0| 16 | |**Enable Code Assist Libraries**
False| 17 | |**Add Eslint configuration**
False| 18 | |**Main Entity**
AuthorReadings| 19 | |**Navigation Entity**
participants| 20 | 21 | ## authorreadingmanager 22 | 23 | An application to create and manage author readings. 24 | 25 | ### Starting the generated app 26 | 27 | - 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 start your CAP project and navigate to the following location in your browser: 28 | 29 | http://localhost:4004/authorreadingmanager/webapp/index.html 30 | 31 | #### Pre-requisites: 32 | 33 | 1. Active NodeJS LTS (Long Term Support) version and associated supported NPM version. (See https://nodejs.org) 34 | 35 | 36 | -------------------------------------------------------------------------------- /Applications/author-readings/app/authorreadingmanager/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "authorreadingmanager", 3 | "version": "1.1.0", 4 | "description": "An application to create and manage author readings.", 5 | "keywords": [ 6 | "ui5", 7 | "openui5", 8 | "sapui5" 9 | ], 10 | "main": "webapp/index.html", 11 | "scripts": { 12 | "deploy-config": "npx -p @sap/ux-ui5-tooling fiori add deploy-config cf", 13 | "build:cf": "ui5 build preload --clean-dest --config ui5-deploy.yaml --include-task=generateManifestBundle generateCachebusterInfo" 14 | }, 15 | "devDependencies": { 16 | "@sap/ui5-builder-webide-extension": "^1.1.9", 17 | "ui5-task-zipper": "^0.8.5", 18 | "mbt": "^1.2.24" 19 | }, 20 | "ui5": { 21 | "dependencies": [ 22 | "@sap/ui5-builder-webide-extension", 23 | "ui5-task-zipper", 24 | "mbt" 25 | ] 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Applications/author-readings/app/authorreadingmanager/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: authorreadingmanager 5 | type: application 6 | resources: 7 | configuration: 8 | propertiesFileSourceEncoding: UTF-8 9 | builder: 10 | resources: 11 | excludes: 12 | - "/test/**" 13 | - "/localService/**" 14 | customTasks: 15 | - name: webide-extension-task-updateManifestJson 16 | beforeTask: generateCachebusterInfo 17 | configuration: 18 | appFolder: webapp 19 | destDir: dist 20 | - name: ui5-task-zipper 21 | afterTask: generateCachebusterInfo 22 | configuration: 23 | archiveName: authorreadingmanager 24 | additionalFiles: 25 | - xs-app.json 26 | -------------------------------------------------------------------------------- /Applications/author-readings/app/authorreadingmanager/ui5.yaml: -------------------------------------------------------------------------------- 1 | specVersion: '2.4' 2 | metadata: 3 | name: 'authorreadingmanager' 4 | type: application 5 | server: 6 | customMiddleware: 7 | - name: fiori-tools-proxy 8 | afterMiddleware: compression 9 | configuration: 10 | ignoreCertError: false # If set to true, certificate errors will be ignored. E.g. self-signed certificates will be accepted 11 | backend: 12 | - path: /authorreadingmanager 13 | url: http://localhost:4004 14 | ui5: 15 | path: 16 | - /resources 17 | - /test-resources 18 | url: https://ui5.sap.com 19 | - name: fiori-tools-appreload 20 | afterMiddleware: compression 21 | configuration: 22 | port: 35729 23 | path: webapp 24 | delay: 300 25 | -------------------------------------------------------------------------------- /Applications/author-readings/app/authorreadingmanager/webapp/Component.js: -------------------------------------------------------------------------------- 1 | sap.ui.define(["sap/fe/core/AppComponent"], function(AppComponent) { 2 | 'use strict'; 3 | 4 | return AppComponent.extend("authorreadingmanager.Component", { 5 | metadata: { 6 | manifest: "json" 7 | } 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /Applications/author-readings/app/authorreadingmanager/webapp/i18n/i18n.properties: -------------------------------------------------------------------------------- 1 | # This is the resource bundle for authorreadingmanager 2 | 3 | #Texts for manifest.json 4 | 5 | #XTIT: Application name 6 | appTitle=Manage Author Readings 7 | 8 | #YDES: Application description 9 | appDescription=An application to create and manage author readings. 10 | 11 | flpTitle=Author Readings 12 | 13 | flpSubtitle=Create and manage author readings 14 | -------------------------------------------------------------------------------- /Applications/author-readings/app/authorreadingmanager/webapp/i18n/i18n_de.properties: -------------------------------------------------------------------------------- 1 | # This is the resource bundle for authorreadingmanager 2 | 3 | #Texts for manifest.json 4 | 5 | #XTIT: Application name 6 | appTitle = Autorenlesungen 7 | 8 | #YDES: Application description 9 | appDescription = Plane Autorenlesungen und Poetry Slams 10 | 11 | flpTitle = Autorenlesungen 12 | 13 | flpSubtitle = Plane Autorenlesungen und Poetry Slams 14 | -------------------------------------------------------------------------------- /Applications/author-readings/app/authorreadingmanager/webapp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{appTitle}} 8 | 9 | 24 | 25 | 26 | 34 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Applications/author-readings/app/authorreadingmanager/webapp/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "_version": "1.32.0", 3 | "sap.app": { 4 | "id": "authorreadingmanager", 5 | "type": "application", 6 | "i18n": "i18n/i18n.properties", 7 | "applicationVersion": { 8 | "version": "1.0.0" 9 | }, 10 | "title": "{{appTitle}}", 11 | "description": "{{appDescription}}", 12 | "dataSources": { 13 | "mainService": { 14 | "uri": "/odata/v4/authorreadingmanager/", 15 | "type": "OData", 16 | "settings": { 17 | "odataVersion": "4.0" 18 | } 19 | } 20 | }, 21 | "offline": false, 22 | "resources": "resources.json", 23 | "sourceTemplate": { 24 | "id": "ui5template.fiorielements.v4.lrop", 25 | "version": "1.0.0" 26 | }, 27 | "crossNavigation": { 28 | "inbounds": { 29 | "authorreadingmanager-inbound": { 30 | "signature": { 31 | "parameters": {}, 32 | "additionalParameters": "allowed" 33 | }, 34 | "semanticObject": "Object", 35 | "action": "display", 36 | "title": "{{flpTitle}}", 37 | "subTitle": "{{flpSubtitle}}", 38 | "icon": "" 39 | } 40 | } 41 | } 42 | }, 43 | "sap.ui": { 44 | "technology": "UI5", 45 | "icons": { 46 | "icon": "", 47 | "favIcon": "", 48 | "phone": "", 49 | "phone@2": "", 50 | "tablet": "", 51 | "tablet@2": "" 52 | }, 53 | "deviceTypes": { 54 | "desktop": true, 55 | "tablet": true, 56 | "phone": true 57 | } 58 | }, 59 | "sap.ui5": { 60 | "resources": { 61 | "js": [], 62 | "css": [] 63 | }, 64 | "dependencies": { 65 | "minUI5Version": "1.100.0", 66 | "libs": { 67 | "sap.ui.core": {}, 68 | "sap.fe.templates": {} 69 | } 70 | }, 71 | "models": { 72 | "@i18n": { 73 | "type": "sap.ui.model.resource.ResourceModel", 74 | "uri": "i18n/i18n.properties" 75 | }, 76 | "i18n": { 77 | "type": "sap.ui.model.resource.ResourceModel", 78 | "uri": "i18n/i18n.properties" 79 | }, 80 | "": { 81 | "dataSource": "mainService", 82 | "preload": true, 83 | "settings": { 84 | "synchronizationMode": "None", 85 | "operationMode": "Server", 86 | "autoExpandSelect": true, 87 | "earlyRequests": true 88 | } 89 | } 90 | }, 91 | "routing": { 92 | "routes": [ 93 | { 94 | "pattern": ":?query:", 95 | "name": "AuthorReadingsList", 96 | "target": "AuthorReadingsList" 97 | }, 98 | { 99 | "pattern": "AuthorReadings({key}):?query:", 100 | "name": "AuthorReadingsObjectPage", 101 | "target": "AuthorReadingsObjectPage" 102 | }, 103 | { 104 | "pattern": "AuthorReadings({key})/participants({key2}):?query:", 105 | "name": "ParticipantsObjectPage", 106 | "target": "ParticipantsObjectPage" 107 | } 108 | ], 109 | "targets": { 110 | "AuthorReadingsList": { 111 | "type": "Component", 112 | "id": "AuthorReadingsList", 113 | "name": "sap.fe.templates.ListReport", 114 | "options": { 115 | "settings": { 116 | "entitySet": "AuthorReadings", 117 | "initialLoad": true, 118 | "variantManagement": "Page", 119 | "navigation": { 120 | "AuthorReadings": { 121 | "detail": { 122 | "route": "AuthorReadingsObjectPage" 123 | } 124 | } 125 | } 126 | } 127 | } 128 | }, 129 | "AuthorReadingsObjectPage": { 130 | "type": "Component", 131 | "id": "AuthorReadingsObjectPage", 132 | "name": "sap.fe.templates.ObjectPage", 133 | "options": { 134 | "settings": { 135 | "editableHeaderContent": false, 136 | "entitySet": "AuthorReadings", 137 | "navigation": { 138 | "participants": { 139 | "detail": { 140 | "route": "ParticipantsObjectPage" 141 | } 142 | } 143 | } 144 | } 145 | } 146 | }, 147 | "ParticipantsObjectPage": { 148 | "type": "Component", 149 | "id": "ParticipantsObjectPage", 150 | "name": "sap.fe.templates.ObjectPage", 151 | "options": { 152 | "settings": { 153 | "editableHeaderContent": false, 154 | "entitySet": "Participants" 155 | } 156 | } 157 | } 158 | } 159 | }, 160 | "contentDensities": { 161 | "compact": true, 162 | "cozy": true 163 | } 164 | }, 165 | "sap.platform.abap": { 166 | "_version": "1.1.0", 167 | "uri": "" 168 | }, 169 | "sap.platform.hcp": { 170 | "_version": "1.1.0", 171 | "uri": "" 172 | }, 173 | "sap.fiori": { 174 | "_version": "1.1.0", 175 | "registrationIds": [], 176 | "archeType": "transactional" 177 | }, 178 | "sap.cloud": { 179 | "public": true, 180 | "service": "authorreadingmanager" 181 | } 182 | } -------------------------------------------------------------------------------- /Applications/author-readings/app/authorreadingmanager/webapp/test/flpSandbox.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {{appTitle}} 9 | 10 | 25 | 56 | 57 | 58 | 59 | 70 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /Applications/author-readings/app/authorreadingmanager/xs-app.json: -------------------------------------------------------------------------------- 1 | { 2 | "welcomeFile": "/index.html", 3 | "authenticationMethod": "route", 4 | "routes": [ 5 | { 6 | "authenticationType": "none", 7 | "csrfProtection": false, 8 | "source": "^/odata/v4/authorreadingmanager/", 9 | "destination": "launchpad" 10 | }, 11 | { 12 | "source": "^/resources/(.*)$", 13 | "target": "/resources/$1", 14 | "authenticationType": "none", 15 | "destination": "ui5" 16 | }, 17 | { 18 | "source": "^/test-resources/(.*)$", 19 | "target": "/test-resources/$1", 20 | "authenticationType": "none", 21 | "destination": "ui5" 22 | }, 23 | { 24 | "source": "^(.*)$", 25 | "target": "$1", 26 | "service": "html5-apps-repo-rt", 27 | "authenticationType": "xsuaa" 28 | } 29 | ] 30 | } -------------------------------------------------------------------------------- /Applications/author-readings/app/services.cds: -------------------------------------------------------------------------------- 1 | 2 | using from './authorreadingmanager/annotations'; -------------------------------------------------------------------------------- /Applications/author-readings/db/data/sap.common-Currencies.csv: -------------------------------------------------------------------------------- 1 | code;symbol;name;descr 2 | EUR;€;Euro;European Euro 3 | USD;$;US Dollar;United States Dollar 4 | CAD;$;Canadian Dollar;Canadian Dollar 5 | AUD;$;Australian Dollar;Australian Dollar 6 | GBP;£;British Pound;Great Britain Pound 7 | ILS;₪;Shekel;Israeli New Shekel 8 | INR;₹;Rupee;Indian Rupee 9 | QAR;﷼;Riyal;Katar Riyal 10 | SAR;﷼;Riyal;Saudi Riyal 11 | JPY;¥;Yen;Japanese Yen 12 | CNY;¥;Yuan;Chinese Yuan Renminbi -------------------------------------------------------------------------------- /Applications/author-readings/db/data/sap.common-Currencies_texts.csv: -------------------------------------------------------------------------------- 1 | code;locale;name;descr 2 | EUR;en;Euro;European Euro 3 | USD;en;US Dollar;United States Dollar 4 | CAD;en;Canadian Dollar;Canadian Dollar 5 | AUD;en;Australian Dollar;Australian Dollar 6 | GBP;en;British Pound;Great Britain Pound 7 | ILS;en;Shekel;Israeli New Shekel 8 | INR;en;Rupee;Indian Rupee 9 | QAR;en;Riyal;Katar Riyal 10 | SAR;en;Riyal;Saudi Riyal 11 | JPY;en;Yen;Japanese Yen 12 | CNY;en;Yuan;Chinese Yuan Renminbi 13 | EUR;de;Euro;Europäischer Euro 14 | USD;de;US-Dollar;US-Dollar 15 | CAD;de;Kanadischer Dollar;Kanadischer Dollar 16 | AUD;de;Australischer Dollar;Australischer Dollar 17 | GBP;de;Britisches Pfund;Großbritannien Pfund 18 | ILS;de;Schekel;Israelischer Neuer Schekel 19 | INR;de;Rupie;Indische Rupie 20 | QAR;de;Riyal;Katar Riyal 21 | SAR;de;Riyal;Saudi-Riyal 22 | JPY;de;Yen;Japanischer Yen 23 | CNY;de;Yuan;Chinesischer Yuan Renminbi -------------------------------------------------------------------------------- /Applications/author-readings/db/data/sap.samples.authorreadings-AuthorReadingStatusCodes.csv: -------------------------------------------------------------------------------- 1 | code;name;descr 2 | 0;NotReleased;Not Released 3 | 1;Published;Published 4 | 2;Booked;Booked 5 | 4;Blocked;Blocked -------------------------------------------------------------------------------- /Applications/author-readings/db/data/sap.samples.authorreadings-AuthorReadingStatusCodes_texts.csv: -------------------------------------------------------------------------------- 1 | code;locale;name;descr 2 | 0;en;NotReleased;Not Released 3 | 1;en;Published;Published 4 | 2;en;Booked;Booked 5 | 4;en;Blocked;Blocked 6 | 0;de;NotReleased;Nicht freigegeben 7 | 1;de;Published;Veröffentlicht 8 | 2;de;Booked;Gebucht 9 | 4;de;Blocked;Blockiert -------------------------------------------------------------------------------- /Applications/author-readings/db/data/sap.samples.authorreadings-AuthorReadings.csv: -------------------------------------------------------------------------------- 1 | ID;identifier;date;maxParticipantsNumber;availableFreeSlots;participantsFeeAmount;currency_code;statusCode_code;createdBy;title;description 2 | 79ceab87-300d-4b66-8cc3-f82c679b77a1;1;2023-03-03;50;48;100.00;EUR;1;anonymous;The one plus one;Author reading: Jojo Moyes reading in her novel "The one plus one" 3 | 79ceab87-300d-4b66-8cc3-f82c679b77a2;2;2023-04-07;50;47;105.00;CNY;1;anonymous;三体;Liu Cixin talks about the philosophy in his science fiction trilogy "The Three-Body Problem", "The Dark Forest" and "Death's End" 4 | 79ceab87-300d-4b66-8cc3-f82c679b77a3;3;2023-04-14;75;73;95.00;USD;1;anonymous;The Hobbit;Thorin Oakenshield reads J. R. Tolkiens "The Hobbit" supported by the Rivendell Orchestra 5 | 79ceab87-300d-4b66-8cc3-f82c679b77a4;4;2023-07-07;75;73;1000;INR;1;anonymous;A Midsommer Night's Dream;Hermia Lysander reading William Shakespeare's comedy "A Midsommer Night's Dream" 6 | 79ceab87-300d-4b66-8cc3-f82c679b77a5;5;2023-07-27;50;47;100;EUR;1;anonymous;By the Sea;Author reading: Abdulrazak Gurnah reads "By the Sea" 7 | 79ceab87-300d-4b66-8cc3-f82c679b77a6;6;2023-09-23;50;50;79;EUR;0;anonymous;Catweazle;Stuffy Gladstone reading Catweazle live 8 | 79ceab87-300d-4b66-8cc3-f82c679b77a7;7;2023-12-16;50;50;25;EUR;0;anonymous;Poetry Slam Berlin;Live! Poetry slam 2022 in Berlin 9 | 79ceab87-300d-4b66-8cc3-f82c679b77a8;8;2023-12-23;50;50;25;EUR;0;anonymous;Wacken Poetry Open Air;Open air poetry festival in Wacken -------------------------------------------------------------------------------- /Applications/author-readings/db/data/sap.samples.authorreadings-ParticipantStatusCodes.csv: -------------------------------------------------------------------------------- 1 | code;name;descr 2 | 1;InProcess;In Process 3 | 2;Confirmed;Confirmed 4 | 3;Cancelled;Cancelled -------------------------------------------------------------------------------- /Applications/author-readings/db/data/sap.samples.authorreadings-ParticipantStatusCodes_texts.csv: -------------------------------------------------------------------------------- 1 | code;locale;name;descr 2 | 1;en;InProcess;In Process 3 | 2;en;Confirmed;Confirmed 4 | 3;en;Cancelled;Cancelled 5 | 1;de;InProcess;In Bearbeitung 6 | 2;de;Confirmed;Bestätigt 7 | 3;de;Cancelled;Storniert -------------------------------------------------------------------------------- /Applications/author-readings/db/data/sap.samples.authorreadings-Participants.csv: -------------------------------------------------------------------------------- 1 | ID;parent_ID;identifier;name;email;mobileNumber;statusCode_code 2 | 79ceab87-300d-4b66-8cc3-182c679b7c01;79ceab87-300d-4b66-8cc3-f82c679b77a1;1;Carlos Garcia;carlos.garcia@sapbydesign.com;+34 789654123;2 3 | 79ceab87-300d-4b66-8cc3-282c679b7c02;79ceab87-300d-4b66-8cc3-f82c679b77a1;2;Lucas Van Brekelenkam;Lucas.VanBrekelenkam@sapbydesign.com;+31 4399357102;2 4 | 79ceab87-300d-4b66-8cc3-382c679b7c03;79ceab87-300d-4b66-8cc3-f82c679b77a5;1;Susan Winters;Susan.Winters@sapbydesign.com;;2 5 | 79ceab87-300d-4b66-8cc3-482c679b7c04;79ceab87-300d-4b66-8cc3-f82c679b77a5;2;Julia Brunner;Julia.Brunner@sapbydesign.com;+43 519369020;2 6 | 79ceab87-300d-4b66-8cc3-582c679b7c05;79ceab87-300d-4b66-8cc3-f82c679b77a5;3;Eddie Smoke;eddie.smoke@sapbydesign.com;+49 15116810562;2 7 | 79ceab87-300d-4b66-8cc3-682c679b7c06;79ceab87-300d-4b66-8cc3-f82c679b77a3;1;Bram De Jong;Bram.DeJong@sapbydesign.com;+31 40399357104;2 8 | 79ceab87-300d-4b66-8cc3-782c679b7c07;79ceab87-300d-4b66-8cc3-f82c679b77a3;2;Giuseppe Rosso;giuseppe.rossi@sapbydesign.com;+39 68747524;2 9 | 79ceab87-300d-4b66-8cc3-882c679b7c08;79ceab87-300d-4b66-8cc3-f82c679b77a4;1;Jessica Orwell;jessica.orwell@sapbydesign.com;;2 10 | 79ceab87-300d-4b66-8cc3-982c679b7c09;79ceab87-300d-4b66-8cc3-f82c679b77a4;2;Catherine Kennedy-Woods;Catherine.Kennedy-Woods@sapbydesign.com;;2 11 | 79ceab87-300d-4b66-8cc3-a82c679b7c10;79ceab87-300d-4b66-8cc3-f82c679b77a2;1;Jie Wenjie;Jie.Wenjie@sapbydesign.com;;2 12 | 79ceab87-300d-4b66-8cc3-b82c679b7c11;79ceab87-300d-4b66-8cc3-f82c679b77a2;2;Knut Evans;Knut.Evans@sapbydesign.com;;2 13 | 79ceab87-300d-4b66-8cc3-c82c679b7c12;79ceab87-300d-4b66-8cc3-f82c679b77a2;3;Richard Miao;Richard.Miao@sapbydesign.com;;2 -------------------------------------------------------------------------------- /Applications/author-readings/db/entity-models.cds: -------------------------------------------------------------------------------- 1 | namespace sap.samples.authorreadings; 2 | 3 | using { 4 | sap, 5 | managed, 6 | cuid, 7 | Currency 8 | } from '@sap/cds/common'; 9 | 10 | // Author readings 11 | entity AuthorReadings : managed, cuid { 12 | identifier : String; 13 | title : localized String(100); 14 | description : localized String(500); 15 | date : DateTime; 16 | maxParticipantsNumber : Integer; 17 | availableFreeSlots : Integer; 18 | participantsFeeAmount : Decimal(6,2); 19 | currency : Association to one sap.common.Currencies; 20 | statusCode : Association to one AuthorReadingStatusCodes; 21 | participants : Composition of many Participants on participants.parent = $self; 22 | projectID : String; 23 | projectObjectID : String; 24 | projectURL : String; 25 | projectSystem : String; 26 | eventMeshMessage : String; 27 | } 28 | 29 | // Participants (sub-node of AuthorReadings) 30 | entity Participants : managed, cuid { 31 | parent : Association to AuthorReadings; 32 | identifier : String; 33 | name : String; 34 | email : String; 35 | mobileNumber : String; 36 | statusCode : Association to one ParticipantStatusCodes; 37 | } 38 | 39 | // Author reading status codes 40 | entity AuthorReadingStatusCodes : sap.common.CodeList { 41 | @Common.Text : { 42 | $value : descr, 43 | ![@UI.TextArrangement] : #TextOnly 44 | } 45 | key code : Integer default 0 46 | } 47 | 48 | // Participant status codes 49 | entity ParticipantStatusCodes : sap.common.CodeList { 50 | @Common.Text : { 51 | $value : descr, 52 | ![@UI.TextArrangement] : #TextOnly 53 | } 54 | key code : Integer default 1 55 | } 56 | 57 | annotate AuthorReadings with @fiori.draft.enabled { 58 | ID @title : '{i18n>uuid}' @Core.Computed; 59 | identifier @title : '{i18n>identifier}' @mandatory; 60 | title @title : '{i18n>title}' @mandatory; 61 | description @title : '{i18n>description}'; 62 | date @title : '{i18n>date}' @mandatory; 63 | maxParticipantsNumber @title : '{i18n>maxParticipantsNumber}' @mandatory; 64 | availableFreeSlots @title : '{i18n>availableFreeSlots}' @readonly; 65 | participantsFeeAmount @title : '{i18n>participantsFeeAmount}' @Measures.ISOCurrency: currency_code; 66 | currency @title : '{i18n>currency}'; 67 | statusCode @title : '{i18n>statusCode}' @readonly; 68 | projectID @title : '{i18n>projectID}'; 69 | projectObjectID @title : '{i18n>projectObjectID}'; 70 | projectURL @title : '{i18n>projectURL}'; 71 | projectSystem @title : '{i18n>projectSystem}'; 72 | eventMeshMessage @title : '{i18n>eventMeshMessage}'; 73 | } 74 | 75 | annotate Participants with { 76 | ID @title : '{i18n>uuid}' @Core.Computed; 77 | parent @title : '{i18n>authorReadingUUID}'; 78 | identifier @title : '{i18n>identifier}' @mandatory; 79 | name @title : '{i18n>name}' @mandatory; 80 | email @title : '{i18n>email}'; 81 | mobileNumber @title : '{i18n>mobileNumber}'; 82 | statusCode @title : '{i18n>statusCode}' @readonly; 83 | } 84 | 85 | annotate AuthorReadingStatusCodes with { 86 | code @title : '{i18n>codeListStatusCode}'; 87 | descr @title : '{i18n>codeListStatusText}' 88 | } 89 | 90 | annotate ParticipantStatusCodes with { 91 | code @title : '{i18n>codeListStatusCode}'; 92 | descr @title : '{i18n>codeListStatusText}' 93 | } 94 | -------------------------------------------------------------------------------- /Applications/author-readings/db/i18n/i18n.properties: -------------------------------------------------------------------------------- 1 | # Entity model translation / default language 2 | 3 | # Texts for titles used in data model 4 | 5 | #XTIT 6 | AuthorReadingStatusCode = Author Reading Status 7 | ParticipantStatusCode = Participant Status 8 | 9 | # ------------------------------------------------------------------------------------- 10 | # Labels for entity AuthorReadings 11 | 12 | title = Title 13 | description = Description 14 | date = Date 15 | maxParticipantsNumber = Max Number of Participants 16 | availableFreeSlots = Available Free Slots 17 | participantsFeeAmount = Participants Free 18 | currency = Currency 19 | projectID = Project 20 | projectObjectID = Project UUID 21 | projectURL = Project URL 22 | projectSystem = Project System Type 23 | projectSystemName = Project System 24 | eventMeshMessage = Event Messages 25 | 26 | # ------------------------------------------------------------------------------------- 27 | # Labels for entity Participants 28 | 29 | authorReadingUUID = Author Reading UUID 30 | name = Name 31 | email = E-Mail 32 | mobileNumber = Phone Number 33 | 34 | # ------------------------------------------------------------------------------------- 35 | # Common labels 36 | 37 | uuid = UUID 38 | identifier = ID 39 | statusCode = Status Code 40 | codeListStatusCode = Status Code 41 | codeListStatusText = Status 42 | 43 | # ------------------------------------------------------------------------------------- 44 | # Transient Service Elements 45 | 46 | statusCriticality = Status 47 | createProjectEnabled = Project Enabled 48 | 49 | # ------------------------------------------------------------------------------------- 50 | # Service Actions 51 | 52 | publish = Publish 53 | block = Block 54 | confirmParticipation = Confirm Participation 55 | cancelParticipation = Cancel Participation 56 | createProject = Create Project 57 | 58 | # ------------------------------------------------------------------------------------- 59 | # Remote Service Elements 60 | 61 | projectTypeCodeText = Project Type 62 | projectStatusCodeText = Project Status 63 | projectCostCenter = Cost Center 64 | projectStartDateTime = Start Date 65 | projectEndDateTime = End Date 66 | 67 | # ------------------------------------------------------------------------------------- 68 | # Web Application Titles 69 | 70 | authorreading = Author Reading 71 | authorreading-plural = Author Readings 72 | 73 | participant = Participant 74 | participant-plural = Participants 75 | 76 | generalData = General Data 77 | participantData = Participant Data 78 | administativeData = Administrative Data 79 | projectData = Project Data 80 | -------------------------------------------------------------------------------- /Applications/author-readings/db/i18n/i18n_de.properties: -------------------------------------------------------------------------------- 1 | # Entity model translation / German 2 | 3 | # Texts for titles used in data model 4 | 5 | #XTIT 6 | AuthorReadingStatusCode = Status der Lesung 7 | ParticipantStatusCode = Teilnehmerstatus 8 | 9 | # ------------------------------------------------------------------------------------- 10 | # Labels for entity AuthorReadings 11 | 12 | title = Titel 13 | description = Beschreibung 14 | date = Datum 15 | maxParticipantsNumber = Maximale Teilnehmeranzahl 16 | availableFreeSlots = Freie Plätze 17 | participantsFeeAmount = Unkostenbeitrag 18 | currency = Währung 19 | projectID = Projekt 20 | projectObjectID = Projekt-ID 21 | projectURL = Projektlink 22 | projectSystem = Projektsystemtyp 23 | projectSystemName = Projektsystem 24 | eventMeshMessage = Event-Nachrichten 25 | 26 | # ------------------------------------------------------------------------------------- 27 | # Labels for entity Participants 28 | 29 | authorReadingUUID = UUID der Lesung 30 | name = Name 31 | email = E-Mail 32 | mobileNumber = Telefonnummer 33 | 34 | # ------------------------------------------------------------------------------------- 35 | # Common labels 36 | 37 | uuid = UUID 38 | identifier = ID 39 | statusCode = Statuscode 40 | codeListStatusCode = Code 41 | codeListStatusText = Statusbeschreibung 42 | 43 | # ------------------------------------------------------------------------------------- 44 | # Transient Service Elements 45 | 46 | statusCriticality = Status 47 | createProjectEnabled = Projekt offen 48 | 49 | # ------------------------------------------------------------------------------------- 50 | # Service Actions 51 | 52 | publish = Veröffentlichen 53 | block = Absagen 54 | confirmParticipation = Teilnahme bestätigen 55 | cancelParticipation = Teilnahme absagen 56 | createProject = Projekt anlegen 57 | 58 | # ------------------------------------------------------------------------------------- 59 | # Remote Service Elements 60 | 61 | projectTypeCodeText = Projekttyp 62 | projectStatusCodeText = Projektstatus 63 | projectCostCenter = Kostenstelle 64 | projectStartDateTime = Projektstart 65 | projectEndDateTime = Projektende 66 | 67 | # ------------------------------------------------------------------------------------- 68 | # Web Application Titles 69 | 70 | authorreading = Autorenlesung 71 | authorreading-plural = Autorenlesungen 72 | 73 | participant = Teilnehmer 74 | participant-plural = Teilnehmer 75 | 76 | generalData = Allgemeine Informationen 77 | participantData = Teilnehmerdaten 78 | administativeData = Administrative Daten 79 | projectData = Projektdaten 80 | -------------------------------------------------------------------------------- /Applications/author-readings/db/src/.hdiconfig: -------------------------------------------------------------------------------- 1 | { 2 | "file_suffixes": { 3 | "csv": { 4 | "plugin_name": "com.sap.hana.di.tabledata.source" 5 | }, 6 | "hdbafllangprocedure": { 7 | "plugin_name": "com.sap.hana.di.afllangprocedure" 8 | }, 9 | "hdbanalyticprivilege": { 10 | "plugin_name": "com.sap.hana.di.analyticprivilege" 11 | }, 12 | "hdbcalculationview": { 13 | "plugin_name": "com.sap.hana.di.calculationview" 14 | }, 15 | "hdbcollection": { 16 | "plugin_name": "com.sap.hana.di.collection" 17 | }, 18 | "hdbconstraint": { 19 | "plugin_name": "com.sap.hana.di.constraint" 20 | }, 21 | "hdbdropcreatetable": { 22 | "plugin_name": "com.sap.hana.di.dropcreatetable" 23 | }, 24 | "hdbflowgraph": { 25 | "plugin_name": "com.sap.hana.di.flowgraph" 26 | }, 27 | "hdbfunction": { 28 | "plugin_name": "com.sap.hana.di.function" 29 | }, 30 | "hdbgraphworkspace": { 31 | "plugin_name": "com.sap.hana.di.graphworkspace" 32 | }, 33 | "hdbhadoopmrjob": { 34 | "plugin_name": "com.sap.hana.di.virtualfunctionpackage.hadoop" 35 | }, 36 | "hdbindex": { 37 | "plugin_name": "com.sap.hana.di.index" 38 | }, 39 | "hdblibrary": { 40 | "plugin_name": "com.sap.hana.di.library" 41 | }, 42 | "hdbmigrationtable": { 43 | "plugin_name": "com.sap.hana.di.table.migration" 44 | }, 45 | "hdbprocedure": { 46 | "plugin_name": "com.sap.hana.di.procedure" 47 | }, 48 | "hdbprojectionview": { 49 | "plugin_name": "com.sap.hana.di.projectionview" 50 | }, 51 | "hdbprojectionviewconfig": { 52 | "plugin_name": "com.sap.hana.di.projectionview.config" 53 | }, 54 | "hdbreptask": { 55 | "plugin_name": "com.sap.hana.di.reptask" 56 | }, 57 | "hdbresultcache": { 58 | "plugin_name": "com.sap.hana.di.resultcache" 59 | }, 60 | "hdbrole": { 61 | "plugin_name": "com.sap.hana.di.role" 62 | }, 63 | "hdbroleconfig": { 64 | "plugin_name": "com.sap.hana.di.role.config" 65 | }, 66 | "hdbsearchruleset": { 67 | "plugin_name": "com.sap.hana.di.searchruleset" 68 | }, 69 | "hdbsequence": { 70 | "plugin_name": "com.sap.hana.di.sequence" 71 | }, 72 | "hdbstatistics": { 73 | "plugin_name": "com.sap.hana.di.statistics" 74 | }, 75 | "hdbstructuredprivilege": { 76 | "plugin_name": "com.sap.hana.di.structuredprivilege" 77 | }, 78 | "hdbsynonym": { 79 | "plugin_name": "com.sap.hana.di.synonym" 80 | }, 81 | "hdbsynonymconfig": { 82 | "plugin_name": "com.sap.hana.di.synonym.config" 83 | }, 84 | "hdbsystemversioning": { 85 | "plugin_name": "com.sap.hana.di.systemversioning" 86 | }, 87 | "hdbtable": { 88 | "plugin_name": "com.sap.hana.di.table" 89 | }, 90 | "hdbtabledata": { 91 | "plugin_name": "com.sap.hana.di.tabledata" 92 | }, 93 | "hdbtabletype": { 94 | "plugin_name": "com.sap.hana.di.tabletype" 95 | }, 96 | "hdbtrigger": { 97 | "plugin_name": "com.sap.hana.di.trigger" 98 | }, 99 | "hdbview": { 100 | "plugin_name": "com.sap.hana.di.view" 101 | }, 102 | "hdbvirtualfunction": { 103 | "plugin_name": "com.sap.hana.di.virtualfunction" 104 | }, 105 | "hdbvirtualfunctionconfig": { 106 | "plugin_name": "com.sap.hana.di.virtualfunction.config" 107 | }, 108 | "hdbvirtualpackagehadoop": { 109 | "plugin_name": "com.sap.hana.di.virtualpackage.hadoop" 110 | }, 111 | "hdbvirtualpackagesparksql": { 112 | "plugin_name": "com.sap.hana.di.virtualpackage.sparksql" 113 | }, 114 | "hdbvirtualprocedure": { 115 | "plugin_name": "com.sap.hana.di.virtualprocedure" 116 | }, 117 | "hdbvirtualprocedureconfig": { 118 | "plugin_name": "com.sap.hana.di.virtualprocedure.config" 119 | }, 120 | "hdbvirtualtable": { 121 | "plugin_name": "com.sap.hana.di.virtualtable" 122 | }, 123 | "hdbvirtualtableconfig": { 124 | "plugin_name": "com.sap.hana.di.virtualtable.config" 125 | }, 126 | "properties": { 127 | "plugin_name": "com.sap.hana.di.tabledata.properties" 128 | }, 129 | "tags": { 130 | "plugin_name": "com.sap.hana.di.tabledata.properties" 131 | }, 132 | "txt": { 133 | "plugin_name": "com.sap.hana.di.copyonly" 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /Applications/author-readings/db/undeploy.json: -------------------------------------------------------------------------------- 1 | [ 2 | "src/gen/**/*.hdbview", 3 | "src/gen/**/*.hdbindex", 4 | "src/gen/**/*.hdbconstraint" 5 | ] 6 | -------------------------------------------------------------------------------- /Applications/author-readings/event-mesh.json: -------------------------------------------------------------------------------- 1 | { 2 | "options": { 3 | "management": true, 4 | "messagingrest": true, 5 | "messaging": true 6 | }, 7 | "rules": { 8 | "queueRules": { 9 | "publishFilter": [ 10 | "sap/byd/project/*", 11 | "${namespace}/*" 12 | ], 13 | "subscribeFilter": [ 14 | "sap/byd/project/*", 15 | "${namespace}/*" 16 | ] 17 | }, 18 | "topicRules": { 19 | "publishFilter": [ 20 | "sap/byd/project/*", 21 | "${namespace}/*" 22 | ], 23 | "subscribeFilter": [ 24 | "sap/byd/project/*", 25 | "${namespace}/*" 26 | ] 27 | } 28 | }, 29 | "version": "1.1.0", 30 | "authorities": [ 31 | "$ACCEPT_GRANTED_AUTHORITIES" 32 | ] 33 | } -------------------------------------------------------------------------------- /Applications/author-readings/mta.yaml: -------------------------------------------------------------------------------- 1 | _schema-version: "3.1" 2 | ID: author-readings 3 | description: SAP Demo Application 4 | version: 1.0.0 5 | 6 | # ------------------------------------------------------------------------- 7 | # Modules 8 | 9 | modules: 10 | 11 | # Service module 12 | - name: author-readings-srv 13 | type: nodejs 14 | path: gen/srv 15 | requires: 16 | - name: author-readings-db 17 | - name: author-readings-uaa 18 | - name: author-readings-destination-service 19 | - name: author-readings-eventmesh 20 | - name: author-readings-auditlog 21 | provides: 22 | - name: srv-api 23 | properties: 24 | srv-url: ${default-url} 25 | parameters: 26 | buildpack: nodejs_buildpack 27 | 28 | # DB deployer module 29 | - name: author-readings-db-deployer 30 | type: hdb 31 | path: gen/db 32 | requires: 33 | - name: author-readings-db 34 | - name: author-readings-uaa 35 | parameters: 36 | buildpack: nodejs_buildpack 37 | 38 | # App UI content deployer module (upload web app content into the HTML5 application repository) 39 | - name: author-readings-app-content 40 | type: com.sap.application.content 41 | path: . 42 | requires: 43 | - name: author-readings-repo-host 44 | parameters: 45 | content-target: true 46 | build-parameters: 47 | build-result: resources 48 | requires: 49 | - artifacts: 50 | - authorreadingmanager.zip 51 | name: authorreadingmanager 52 | target-path: resources/ 53 | 54 | # App UI resources module 55 | - name: authorreadingmanager 56 | type: html5 57 | path: app/authorreadingmanager 58 | build-parameters: 59 | build-result: dist 60 | builder: custom 61 | commands: 62 | - npm install 63 | - npm run build:cf 64 | supported-platforms: [] 65 | 66 | # Destination content module (define destinations with service keys) 67 | - name: author-readings-destination-content 68 | type: com.sap.application.content 69 | requires: 70 | - name: author-readings-destination-service 71 | parameters: 72 | content-target: true 73 | - name: author-readings-repo-host 74 | parameters: 75 | service-key: 76 | name: author-readings-repo-host-key 77 | - name: author-readings-uaa 78 | parameters: 79 | service-key: 80 | name: author-readings-uaa-key 81 | parameters: 82 | content: 83 | instance: 84 | destinations: 85 | - Name: authorreadingmanager-repo-host-dest 86 | ServiceInstanceName: author-readings-html5-srv 87 | ServiceKeyName: author-readings-repo-host-key 88 | sap.cloud.service: authorreadingmanager 89 | - Authentication: OAuth2UserTokenExchange 90 | Name: authorreadingmanager-uaa-fiori-dest 91 | ServiceInstanceName: author-readings-uaa 92 | ServiceKeyName: author-readings-uaa-key 93 | sap.cloud.service: authorreadingmanager 94 | existing_destinations_policy: ignore 95 | build-parameters: 96 | no-source: true 97 | 98 | # ------------------------------------------------------------------------- 99 | # Resources 100 | 101 | resources: 102 | 103 | # Database 104 | - name: author-readings-db 105 | type: com.sap.xs.hdi-container 106 | parameters: 107 | service: hana 108 | service-plan: hdi-shared 109 | properties: 110 | hdi-service-name: ${service-name} 111 | 112 | # HTML5 app repository 113 | - name: author-readings-repo-host 114 | type: org.cloudfoundry.managed-service 115 | parameters: 116 | service: html5-apps-repo 117 | service-name: author-readings-html5-srv 118 | service-plan: app-host 119 | 120 | # Destination service 121 | - name: author-readings-destination-service 122 | type: org.cloudfoundry.managed-service 123 | parameters: 124 | config: 125 | HTML5Runtime_enabled: true 126 | init_data: 127 | instance: 128 | destinations: 129 | - Authentication: NoAuthentication 130 | Name: ui5 131 | ProxyType: Internet 132 | Type: HTTP 133 | URL: https://ui5.sap.com 134 | - Authentication: NoAuthentication 135 | Name: launchpad 136 | ProxyType: Internet 137 | Type: HTTP 138 | URL: ~{srv-api/srv-url} 139 | HTML5.DynamicDestination: true 140 | HTML5.ForwardAuthToken: true 141 | existing_destinations_policy: update 142 | version: 1.0.0 143 | service: destination 144 | service-name: author-readings-destination-service 145 | service-plan: lite 146 | requires: 147 | - name: srv-api 148 | 149 | # UAA service 150 | - name: author-readings-uaa 151 | type: org.cloudfoundry.managed-service 152 | parameters: 153 | config: 154 | tenant-mode: dedicated 155 | xsappname: author-readings-${space} 156 | path: ./xs-security.json 157 | service: xsuaa 158 | service-name: author-readings-uaa 159 | service-plan: application 160 | 161 | # Event Mesh service 162 | - name: author-readings-eventmesh 163 | type: org.cloudfoundry.managed-service 164 | parameters: 165 | path: ./event-mesh.json 166 | config: 167 | emname: "authorreadings" 168 | namespace: "sap/samples/authorreadings" 169 | service: enterprise-messaging 170 | service-plan: default 171 | 172 | # Audit log service 173 | - name: author-readings-auditlog 174 | type: org.cloudfoundry.managed-service 175 | parameters: 176 | service: auditlog 177 | service-plan: standard 178 | 179 | # ------------------------------------------------------------------------- 180 | # Parameters 181 | 182 | parameters: 183 | deploy_mode: html5-repo 184 | enable-parallel-deployments: true 185 | 186 | build-parameters: 187 | before-all: 188 | - builder: custom 189 | commands: 190 | - npm ci --production 191 | - npx -p @sap/cds-dk cds build --production 192 | -------------------------------------------------------------------------------- /Applications/author-readings/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "author-readings", 3 | "version": "1.1.0", 4 | "description": "SAP-SME Partner Reference Application", 5 | "repository": "https://github.com/SAP-samples/sme-partner-reference-application", 6 | "author": "SAP", 7 | "license": "SAP SAMPLE CODE LICENSE", 8 | "dependencies": { 9 | "@sap-cloud-sdk/connectivity": "^3.7.0", 10 | "@sap-cloud-sdk/http-client": "^3.7.0", 11 | "@sap/cds": "^7.3.0", 12 | "@sap/cds-dk": "^7.3.0", 13 | "express": "^4.17.1", 14 | "hdb": "^0.19.6", 15 | "passport": "^0.6.0", 16 | "cors": "^2.8.5", 17 | "@sap/xb-msg-amqp-v100": "^0.9.51", 18 | "@sap/audit-logging": "^5.7.2", 19 | "moment": "^2.29.4" 20 | }, 21 | "devDependencies": { 22 | "@sap/ux-specification": "^1.108.9", 23 | "chai": "^4.3.7", 24 | "chai-http": "^4.4.0", 25 | "mocha": "^10.2.0", 26 | "sqlite3": "^5.1.6" 27 | }, 28 | "engines": { 29 | "node": ">=16.17.1 <19.0.0" 30 | }, 31 | "scripts": { 32 | "start": "cds-serve", 33 | "test": "mocha 'test/*.test.js' --recursive --timeout 10000 --exit", 34 | "undeploy": "cf undeploy author-readings --delete-services --delete-service-keys" 35 | }, 36 | "cds": { 37 | "features": { 38 | "fetch_csrf": true, 39 | "audit_personal_data": true 40 | }, 41 | "requires": { 42 | "db": { 43 | "kind": "sql" 44 | }, 45 | "uaa": { 46 | "kind": "xsuaa" 47 | }, 48 | "byd_khproject": { 49 | "kind": "odata-v2", 50 | "model": "srv/external/byd_khproject", 51 | "[sandbox]": { 52 | "credentials": { 53 | "url": "https://{{byd-hostname}}/sap/byd/odata/cust/v1/khproject/", 54 | "authentication": "BasicAuthentication", 55 | "username": "{{user}}", 56 | "password": "{{password}}" 57 | } 58 | }, 59 | "[production]": { 60 | "credentials": { 61 | "destination": "byd", 62 | "path": "/sap/byd/odata/cust/v1/khproject" 63 | } 64 | } 65 | }, 66 | "byd_khproject_tech_user": { 67 | "kind": "odata-v2", 68 | "model": "srv/external/byd_khproject_tech_user", 69 | "[sandbox]": { 70 | "credentials": { 71 | "url": "https://{{byd-hostname}}/sap/byd/odata/cust/v1/khproject/", 72 | "authentication": "BasicAuthentication", 73 | "username": "{{user}}", 74 | "password": "{{password}}" 75 | } 76 | }, 77 | "[production]": { 78 | "credentials": { 79 | "destination": "byd-tech-user", 80 | "path": "/sap/byd/odata/cust/v1/khproject" 81 | } 82 | } 83 | }, 84 | "outbound_messaging": { 85 | "kind": "enterprise-messaging-shared", 86 | "format": "cloudevents", 87 | "publishPrefix": "sap/samples/authorreadings/", 88 | "webhook": { 89 | "waitingPeriod": 60000, 90 | "qos": 0 91 | } 92 | }, 93 | "byd_messaging": { 94 | "kind": "enterprise-messaging-shared", 95 | "queue": { 96 | "name": "sap/samples/authorreadings/bydprojectevents" 97 | }, 98 | "webhook": { 99 | "waitingPeriod": 60000, 100 | "qos": 0 101 | } 102 | }, 103 | "audit-log": { 104 | "[sandbox]": { 105 | "kind": "audit-log-to-console" 106 | }, 107 | "[production]": { 108 | "kind": "audit-log-service" 109 | } 110 | } 111 | }, 112 | "hana": { 113 | "deploy-format": "hdbtable" 114 | } 115 | }, 116 | "sapux": [ 117 | "app/authorreadingmanager" 118 | ] 119 | } -------------------------------------------------------------------------------- /Applications/author-readings/server.js: -------------------------------------------------------------------------------- 1 | // Define allowed access origins for CORS checks 2 | // In our example we allow all origins. For productive use specific origins shall be allowed only. 3 | 4 | const cds = require('@sap/cds') 5 | 6 | cds.on('bootstrap', (app) => { 7 | const cors = require('cors') 8 | app.use(cors()) 9 | app.use((req, res, next) => { 10 | res.setHeader('Access-Control-Allow-Origin', '*'); 11 | next(); 12 | }); 13 | }) 14 | 15 | cds.on('listening', () => { 16 | // add more middleware ... 17 | }) 18 | 19 | module.exports = cds.server // delegate to default server.js -------------------------------------------------------------------------------- /Applications/author-readings/srv/connector-byd.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | // Include cds libraries and reuse files 4 | const cds = require("@sap/cds"); 5 | 6 | // ---------------------------------------------------------------------------- 7 | // ByD specific reuse functions 8 | // ---------------------------------------------------------------------------- 9 | 10 | // Delegate OData requests to remote ByD project entities 11 | async function delegateODataRequests(req,remoteService) { 12 | try{ 13 | const bydProject = await cds.connect.to(remoteService); 14 | return bydProject.run(req.query); 15 | }catch (error) { 16 | console.log(error); 17 | } 18 | } 19 | 20 | // Return json-payload to create ByD projects 21 | async function projectDataRecord(authorReadingIdentifier, authorReadingTitle, authorReadingDate) { 22 | try{ 23 | // Set project ID with pattern AR-{{author reading identifier}} 24 | var generatedID = "AR-" + authorReadingIdentifier; 25 | // Set project start date 40 days before author reading date 26 | var moment = require("moment"); 27 | var generatedStartDate = moment(authorReadingDate).subtract(40, "days").toISOString().substring(0, 10) + "T00:00:00.0000000Z"; 28 | 29 | // Assemble project payload based the sample data provided by *SAP Business ByDesign Partner Demo Tenants* (reference systems) 30 | const projectRecord = { 31 | ProjectID: generatedID, 32 | EstimatedCompletionPercent: 10, 33 | ResponsibleCostCentreID: "S1111", 34 | ProjectTypeCode: "10", 35 | ProjectLanguageCode: "EN", 36 | PlannedStartDateTime: generatedStartDate, 37 | PlannedEndDateTime: authorReadingDate, 38 | ProjectSummaryTask: { 39 | ProjectName: authorReadingTitle, 40 | ResponsibleEmployeeID: "E0202", 41 | }, 42 | Task: [ 43 | { 44 | TaskID: generatedID + "-PREP", 45 | TaskName: "Event planning and preparations", 46 | PlannedDuration: "P30D", 47 | TaskRelationship: [ 48 | { 49 | DependencyTypeCode: "2", 50 | SuccessorTaskID: generatedID + "-EXE", 51 | LagDuration: "P2D", 52 | }, 53 | ], 54 | }, 55 | { 56 | TaskID: generatedID + "-EXE", 57 | TaskName: "Event administration and execution", 58 | PlannedDuration: "P5D", 59 | ConstraintEndDateTime: authorReadingDate, 60 | ScheduleActivityEndDateTimeConstraintTypeCode: "2", 61 | }, 62 | ], 63 | }; 64 | return projectRecord; 65 | }catch (error) { 66 | console.log(error); 67 | } 68 | } 69 | 70 | // Expand author readings to remote projects 71 | async function readProject(authorReadings) { 72 | try { 73 | const bydProject = await cds.connect.to('byd_khproject'); 74 | let isProjectIDs = false; 75 | const asArray = x => Array.isArray(x) ? x : [ x ]; 76 | 77 | // Read Project ID's related to ByD 78 | let projectIDs = []; 79 | for (const authorReading of asArray(authorReadings)) { 80 | // Check if the Project ID exists in the author reading record AND backend ERP is ByD => then read project information from ByD 81 | if(authorReading.projectSystem == "ByD" && authorReading.projectID ){ 82 | projectIDs.push(authorReading.projectID); 83 | isProjectIDs = true; 84 | } 85 | } 86 | 87 | // Read ByD projects data 88 | if(isProjectIDs){ 89 | 90 | // Request all associated projects 91 | const projects = await bydProject.run( SELECT.from('AuthorReadingManager.ByDProjects').where({ projectID: projectIDs }) ); 92 | 93 | // Convert in a map for easier lookup 94 | const projectsMap = {}; 95 | for (const project of projects) projectsMap[project.projectID] = project; 96 | 97 | // Assemble result 98 | for (const authorReading of asArray(authorReadings)) { 99 | authorReading.toByDProject = projectsMap[authorReading.projectID]; 100 | }; 101 | } 102 | return authorReadings; 103 | } catch (error) { 104 | // App reacts error tolerant in case of calling the remote service, mostly if the remote service is not available of if the destination is missing 105 | console.log("ACTION_READ_PROJECT_CONNECTION" + "; " + error); 106 | }; 107 | } 108 | 109 | // Publish constants and functions 110 | module.exports = { 111 | readProject, 112 | projectDataRecord, 113 | delegateODataRequests 114 | }; -------------------------------------------------------------------------------- /Applications/author-readings/srv/i18n/messages.properties: -------------------------------------------------------------------------------- 1 | # Service translation / default language 2 | 3 | #Texts for manifest.json 4 | 5 | #XTIT: Application name 6 | appTitle=Author Readings 7 | 8 | #YDES: Application description 9 | appDescription=Manage author readings 10 | 11 | # ------------------------------------------------------------------------------------- 12 | # System Messages 13 | 14 | INVALID_EMAIL = Invalid Email ID: {0}, please enter valid email 15 | INVALID_MOBILE_NUMBER = Invalid Mobile Number: {0}, please enter valid mobile number 16 | 17 | PARTICIPANT_AUTHOR_UNKNOWN = Cannot add participant: Author reading not found 18 | PARTICIPANT_FULLY_BOOKED = Cannot add participants: author reading is fully booked 19 | PARTICIPANT_AUTHOR_READING_BLOCKED = Cannot add participant: Author reading is blocked 20 | PARTICIPANT_AUTHOR_READING_IN_PREPARATION = Cannot add participant: Author reading is in preparation 21 | PARTICIPANT_ALREADY_CANCELLED = Participation has already been cancelled 22 | 23 | ACTION_BLOCK_SUCCESS = Author Reading {0} blocked successfully 24 | ACTION_BLOCK_NOT_POSSIBLE = Autor Reading {0} cannot be blocked 25 | 26 | ACTION_PUBLISH_SUCCESS = Author Reading {0} published successfully 27 | ACTION_PUBLISH_NOT_POSSIBLE = Autor Reading {0} cannot be published 28 | 29 | ACTION_CREATE_PROJECT_DRAFT = Projects cannot be created for draft author readings 30 | ACTION_CREATE_PROJECT_CONNECTION = Project cannot be created 31 | 32 | ACTION_READ_PROJECT_CONNECTION = Project cannot be retrieved 33 | 34 | ACTION_CANCEL_PARTICIPATION_SUCCESS = Participation of participant {0} cancelled successfully 35 | ACTION_CANCEL_PARTICIPATION_NOT_POSSIBLE = Participation of participant {0} cancellation failed 36 | ACTION_CANCEL_PARTICIPATION_DRAFT = Draft participants cannot be cancelled 37 | 38 | EMIT_MESSAGE_SUCCESS = Event Message for Author Reading {0} and topic {1} emitted successully 39 | GET_DESTINATION = Reading the connection information for the remote system failed 40 | -------------------------------------------------------------------------------- /Applications/author-readings/srv/i18n/messages_de.properties: -------------------------------------------------------------------------------- 1 | # Service model translation / German 2 | 3 | #Texts for manifest.json 4 | 5 | #XTIT: Application name 6 | appTitle = Autorenlesungen 7 | 8 | #YDES: Application description 9 | appDescription = Plane Autorenlesungen und Poetry Slams 10 | 11 | # ------------------------------------------------------------------------------------- 12 | # System Messages 13 | 14 | INVALID_EMAIL = Ungültige E-Mail: {0}, gebe eine gültige E-Mail-Adresse ein 15 | INVALID_MOBILE_NUMBER = Ungültige Telefonnummer: {0}, gebe eine gültige Telefonnummer ein 16 | 17 | PARTICIPANT_AUTHOR_UNKNOWN = Teilnehmer kann nicht hinzugefügt werden: Autorenlesung nicht gefunden 18 | PARTICIPANT_FULLY_BOOKED = Teilnehmer kann nicht hinzugefügt werden: Keine freien Plätze verfügbar 19 | PARTICIPANT_AUTHOR_READING_BLOCKED = Teilnehmer kann nicht hinzugefügt werden: Autorenlesung ist abgesagt 20 | PARTICIPANT_AUTHOR_READING_IN_PREPARATION = Teilnehmer kann nicht hinzugefügt werden: Autorenlesung noch nicht veröffentlicht 21 | PARTICIPANT_ALREADY_CANCELLED = Die Teilnahme wurde storniert 22 | 23 | ACTION_BLOCK_SUCCESS = Autorenlesung {0} erfolgreich abgesagt 24 | ACTION_BLOCK_NOT_POSSIBLE = Autorenlesung {0} kann nicht abgesagt werden 25 | 26 | ACTION_PUBLISH_SUCCESS = Autorenlesung {0} erfolgreich veröffentlicht 27 | ACTION_PUBLISH_NOT_POSSIBLE = Autorenlesung {0} kann nicht veröffentlicht werden 28 | 29 | ACTION_CREATE_PROJECT_DRAFT = Es können keine Projekte für Autorenlesungen in Bearbeitung erstellt werden 30 | ACTION_CREATE_PROJECT_CONNECTION = Projekt kann nicht erstellt werden 31 | 32 | ACTION_READ_PROJECT_CONNECTION = Projekt kann nicht gelesen werden 33 | 34 | ACTION_CANCEL_PARTICIPATION_SUCCESS = Teilnahme des Teilnehmers {0} erfolgreich storniert 35 | ACTION_CANCEL_PARTICIPATION_NOT_POSSIBLE = Teilnahme des Teilnehmers {0} konnte nicht strorniert werden 36 | ACTION_CANCEL_PARTICIPATION_DRAFT = Teilnehmer in Bearbeitung können nicht stornert werden 37 | 38 | EMIT_MESSAGE_SUCCESS = Event-Nachricht für Autorenlesung {0} und Topic {1} gesendet 39 | GET_DESTINATION = Die Verbindungsdaten zum ERP-System konnten nicht gelesen werden 40 | -------------------------------------------------------------------------------- /Applications/author-readings/srv/reuse.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | // Include SAP Cloud SDK reuse functions 4 | const { getDestination, retrieveJwt } = require("@sap-cloud-sdk/connectivity"); 5 | 6 | // ---------------------------------------------------------------------------- 7 | // Constants 8 | // ---------------------------------------------------------------------------- 9 | 10 | const color = { 11 | grey: 0, 12 | red: 1, 13 | yellow: 2, 14 | green: 3 15 | }; 16 | 17 | const authorReadingStatusCode = { 18 | inPreparation: 0, 19 | published: 1, 20 | booked: 2, 21 | completed: 3, // not used 22 | blocked: 4, 23 | cancelled: 5 // not used 24 | }; 25 | 26 | const participantStatusCode = { 27 | inProcess: 1, 28 | confirmed: 2, 29 | cancelled: 3 30 | }; 31 | 32 | // ---------------------------------------------------------------------------- 33 | // Reuse functions 34 | // ---------------------------------------------------------------------------- 35 | 36 | // Reuse function to check the formating of an e-mail address 37 | function validateEmail(email) { 38 | const regexEmail = /^\w+([\\.-]?\w+)*@\w+([\\.-]?\w+)*(\.\w{2,3})+$/; 39 | if (email.match(regexEmail)) { 40 | return true; 41 | } else { 42 | return false; 43 | } 44 | } 45 | 46 | // Reuse function to check the formating of an phone number 47 | function validatePhone(phone) { 48 | const regexPhone = /^\+(?:[0-9] ?){6,14}[0-9]$/; 49 | if (phone.match(regexPhone)) { 50 | return true; 51 | } else { 52 | return false; 53 | } 54 | } 55 | 56 | // Emit event message to event mesh 57 | async function emitAuthorReadingEvent(req, id, eventMeshTopic) { 58 | 59 | // Return updated reading event data 60 | const authorReadings = await SELECT.from("sap.samples.authorreadings.AuthorReadings").where({ ID: id }); 61 | const authorReading = authorReadings[0]; 62 | 63 | try { 64 | const msg = await cds.connect.to("outbound_messaging"); 65 | await msg.emit( eventMeshTopic, { authorReading, tenant:req.user.tenant } ); 66 | console.log( "====== Inside reuse function to emit Author Reading event messages ======" ); 67 | console.log( `Event message emitted for topic ${eventMeshTopic} and author reading ${authorReading.identifier} and Tenant ID:${req.user.tenant} ` ); 68 | 69 | req.info(200, 'EMIT_MESSAGE_SUCCESS', [authorReading.identifier, eventMeshTopic]); 70 | 71 | const text = `Event notification for topic ${eventMeshTopic} emitted successully.`; 72 | let eventMessages; 73 | if (authorReading.eventMeshMessage) { 74 | eventMessages = authorReading.eventMeshMessage + "\n" + text; 75 | } else { 76 | eventMessages = text; 77 | }; 78 | console.log( "Event message log: ", eventMessages); 79 | 80 | let authorReadingUpdate = await UPDATE("sap.samples.authorreadings.AuthorReadings") 81 | .set({ eventMeshMessage: eventMessages }) 82 | .where({ ID: id }); 83 | if (authorReadingUpdate) { console.log( "Event message log update successfull") } 84 | } catch (error) { 85 | req.error(error); 86 | } 87 | } 88 | 89 | // Reuse function to get the ERP URL 90 | async function getDestinationURL(req, destinationName) { 91 | let destinationURL; 92 | try { 93 | // Read the destination details using the SAP Cloud SDK reusable getDestination function: 94 | // The JWT-token contains the subaccount information, such that the function works for single tenant as well as for multi-tenant apps: 95 | // - Single tenant: Get destination from the subaccount that hosts the app. 96 | // - Multi tenant: Get destination from subscriber subaccount. 97 | const destination = await getDestination({ destinationName: destinationName, jwt: retrieveJwt(req) }); 98 | 99 | if(destination){ 100 | console.log("Get ERP destination URL: " + destination.url); 101 | destinationURL = destination.url; 102 | } 103 | else{ 104 | // No destination found 105 | console.log("Get ERP destination URL: " + destinationName + " not found"); 106 | } 107 | } catch (error) { 108 | // App reacts error tolerant if the destination cannot be retrieved 109 | console.log("GET_DESTINATION" + "; " + error); 110 | } 111 | return destinationURL; 112 | } 113 | 114 | // Reuse function to check if BTP destination exists 115 | async function checkDestination(req, destinationName) { 116 | try { 117 | // Check if the destination exist using the SAP Cloud SDK reusable getDestination function: 118 | // The JWT-token contains the subaccount information, such that the function works for single tenant as well as for multi-tenant apps: 119 | // - Single tenant: Get destination from the subaccount that hosts the app. 120 | // - Multi tenant: Get destination from subscriber subaccount. 121 | const destination = await getDestination({ destinationName: destinationName, jwt: retrieveJwt(req) }); 122 | 123 | if(destination){ 124 | console.log("Check ERP destination: " + destinationName + " found"); 125 | return true; 126 | } 127 | else{ 128 | console.log("Check ERP destination: " + destinationName + " not found"); 129 | return false; 130 | } 131 | } catch (error) { 132 | // App reacts error tolerant if the destination is missing 133 | console.log("CHECK_DESTINATION" + "; " + error); 134 | } 135 | } 136 | 137 | // Reuse function to get the ERP Name 138 | async function getDestinationDescription(req, destinationName) { 139 | let destinationDescription; 140 | try { 141 | // Read the destination details using the SAP Cloud SDK reusable getDestinationDescription function: 142 | // The JWT-token contains the subaccount information, such that the function works for single tenant as well as for multi-tenant apps: 143 | // - Single tenant: Get destination from the subaccount that hosts the app. 144 | // - Multi tenant: Get destination from subscriber subaccount. 145 | const destination = await getDestination({ destinationName: destinationName, jwt: retrieveJwt(req) }); 146 | if(destination){ 147 | for(var originalProperty in destination.originalProperties){ 148 | if (originalProperty == "Description"){ 149 | destinationDescription = destination.originalProperties[originalProperty]; 150 | break; 151 | } 152 | } 153 | } 154 | } catch (error) { 155 | // App reacts error tolerant if the destination is missing 156 | console.log("GET_DESTINATION_DESCRIPTION" + "; " + error); 157 | } 158 | return destinationDescription; 159 | } 160 | 161 | 162 | // Publish constants and functions 163 | module.exports = { 164 | color, 165 | authorReadingStatusCode, 166 | participantStatusCode, 167 | validateEmail, 168 | validatePhone, 169 | emitAuthorReadingEvent, 170 | getDestinationURL, 171 | checkDestination, 172 | getDestinationDescription 173 | }; 174 | -------------------------------------------------------------------------------- /Applications/author-readings/srv/service-auth.cds: -------------------------------------------------------------------------------- 1 | using {AuthorReadingManager} from './service-models'; 2 | 3 | // ---------------------------------------------------------------------------- 4 | // Required authorization roles 5 | annotate AuthorReadingManager with @(requires : [ 6 | 'AuthorReadingManagerRole', 7 | 'AuthorReadingAdminRole' 8 | ]); 9 | 10 | // ---------------------------------------------------------------------------- 11 | // Restriction per authorization role: 12 | 13 | // Managers can read all author readings, create new author readings and change their own author readings 14 | // Administrators have no restrictions 15 | annotate AuthorReadingManager.AuthorReadings with @(restrict : [ 16 | { 17 | grant : [ 18 | 'READ', 19 | 'CREATE' 20 | ], 21 | to : 'AuthorReadingManagerRole' 22 | }, 23 | { 24 | grant : ['*'], 25 | to : 'AuthorReadingManagerRole', 26 | where : 'createdBy = $user' 27 | }, 28 | { 29 | grant : ['*'], 30 | to : 'AuthorReadingAdminRole' 31 | } 32 | ]); 33 | 34 | // Managers can read all participants, add new participants, change participants they added themseves 35 | // Administrators have no restrictions 36 | annotate AuthorReadingManager.Participants with @(restrict : [ 37 | { 38 | grant : [ 39 | 'READ', 40 | 'CREATE' 41 | ], 42 | to : 'AuthorReadingManagerRole' 43 | }, 44 | { 45 | grant : ['*'], 46 | to : 'AuthorReadingManagerRole', 47 | where : 'createdBy = $user' 48 | }, 49 | { 50 | grant : ['*'], 51 | to : 'AuthorReadingAdminRole' 52 | } 53 | ]); 54 | 55 | // ByD projects: Managers and Administrators can read and create remote projects 56 | annotate AuthorReadingManager.ByDProjects with @(restrict : [ 57 | { 58 | grant : ['*'], 59 | to : 'AuthorReadingManagerRole', 60 | }, 61 | { 62 | grant : ['*'], 63 | to : 'AuthorReadingAdminRole' 64 | } 65 | ]); 66 | annotate AuthorReadingManager.ByDProjectSummaryTasks with @(restrict : [ 67 | { 68 | grant : ['*'], 69 | to : 'AuthorReadingManagerRole', 70 | }, 71 | { 72 | grant : ['*'], 73 | to : 'AuthorReadingAdminRole' 74 | } 75 | ]); 76 | annotate AuthorReadingManager.ByDProjectTasks with @(restrict : [ 77 | { 78 | grant : ['*'], 79 | to : 'AuthorReadingManagerRole', 80 | }, 81 | { 82 | grant : ['*'], 83 | to : 'AuthorReadingAdminRole' 84 | } 85 | ]); 86 | annotate AuthorReadingManager.ByDProjectsTechUser with @(restrict : [ 87 | { 88 | grant : ['*'], 89 | to : 'AuthorReadingManagerRole', 90 | }, 91 | { 92 | grant : ['*'], 93 | to : 'AuthorReadingAdminRole' 94 | } 95 | ]); 96 | -------------------------------------------------------------------------------- /Applications/author-readings/test/authorreading.test.js: -------------------------------------------------------------------------------- 1 | "strict" 2 | const chai = require("chai") 3 | const chaiHttp = require("chai-http") 4 | const server = require("./index") 5 | 6 | // Configure chai 7 | const assert = chai.assert 8 | chai.use(chaiHttp) 9 | chai.should(); 10 | 11 | let app = null 12 | before(async () => { 13 | app = await server 14 | }) 15 | 16 | const API_ENDPOINT = "/authorreadingmanager" 17 | 18 | describe("API Test - GET", () => { 19 | 20 | const entities = ["AuthorReadings", "AuthorReadingStatusCodes", "Participants", "ParticipantStatusCodes", "Currencies"]; 21 | entities.forEach(entity => { 22 | it(`should be able to read ${entity}`, (done) => { 23 | chai.request(app) 24 | .get(`${API_ENDPOINT}/${entity}`) 25 | .end((error, response) => { 26 | try { 27 | response.should.have.status(200); 28 | done(); 29 | } catch (error) { 30 | done(error); 31 | } 32 | }); 33 | }) 34 | }) 35 | }) 36 | 37 | describe("API Test - Author Reading", () => { 38 | 39 | 40 | 41 | 42 | }) -------------------------------------------------------------------------------- /Applications/author-readings/test/index.js: -------------------------------------------------------------------------------- 1 | const cds = require("@sap/cds") 2 | 3 | module.exports = new Promise(async (resolve) => { 4 | await cds.deploy("*").to("sqlite:test.db") 5 | cds.exec("run", "--with-mocks", "--in-memory?") 6 | cds.on("listening", () => { 7 | resolve(cds.app) 8 | }) 9 | }) -------------------------------------------------------------------------------- /Applications/author-readings/xs-security.json: -------------------------------------------------------------------------------- 1 | { 2 | "scopes": [ 3 | { 4 | "name": "$XSAPPNAME.AuthorReadingManagerRole", 5 | "description": "AuthorReadingManagerRole" 6 | }, 7 | { 8 | "name": "$XSAPPNAME.AuthorReadingAdminRole", 9 | "description": "AuthorReadingAdminRole" 10 | }, 11 | { 12 | "name": "$XSAPPNAME.emcallback", 13 | "description": "Event Mesh Callback Access", 14 | "grant-as-authority-to-apps": ["$XSSERVICENAME(author-readings-eventmesh)"] 15 | }, 16 | { 17 | "name": "$XSAPPNAME.emmanagement", 18 | "description": "Event Mesh Management Access" 19 | } 20 | ], 21 | "attributes": [], 22 | "role-templates": [ 23 | { 24 | "name": "AuthorReadingManagerRole", 25 | "description": "generated", 26 | "scope-references": [ 27 | "$XSAPPNAME.AuthorReadingManagerRole" 28 | ], 29 | "attribute-references": [] 30 | }, 31 | { 32 | "name": "AuthorReadingAdminRole", 33 | "description": "generated", 34 | "scope-references": [ 35 | "$XSAPPNAME.AuthorReadingAdminRole" 36 | ], 37 | "attribute-references": [] 38 | }, 39 | { 40 | "name": "emmanagement", 41 | "description": "Event Mesh Management Access", 42 | "scope-references": ["$XSAPPNAME.emmanagement"], 43 | "attribute-references": [] 44 | } 45 | ], 46 | "role-collections": [ 47 | { 48 | "name": "AuthorReadingManagerRoleCollection", 49 | "description": "Author Reading Manager", 50 | "role-template-references": [ 51 | "$XSAPPNAME.AuthorReadingManagerRole" 52 | ] 53 | }, 54 | { 55 | "name": "AuthorReadingAdminRoleCollection", 56 | "description": "Author Readings Administrator", 57 | "role-template-references": [ 58 | "$XSAPPNAME.AuthorReadingAdminRole" 59 | ] 60 | } 61 | ] 62 | } -------------------------------------------------------------------------------- /Tutorials/01-Prepare-BTP-Account.md: -------------------------------------------------------------------------------- 1 | # Prepare the BTP Account 2 | 3 | ## Assumptions / Preconditions 4 | 5 | Before you can start with the tutorial you need to have an own SAP BTP Global Account with an unused quota for *Cloud Foundry Runtime* and the *SAP Business Application Studio*. 6 | 7 | Furthermore you should have access to a github organization to create a new github repository for the tutorial application. 8 | 9 | ## Setup BTP Subaccount 10 | 11 | ### Create Subaccount 12 | 13 | At first navigate to your *BTP Global Account* and create a new *Multi-Environment*-Subaccount with name `AuthorReadings` and provider *Amazon Web Services (AWS)*. 14 | 15 | ### Enable Cloud Foundry Runtime 16 | By default Cloud Foundry is disabled for new BTP Subaccounts. That is because not every BTP Subaccount is meant for application development. 17 | 18 | 19 | 20 | Enable Cloud Foundry using the proposed standard settings: 21 | 22 | | Property | Value | 23 | | :------------- | :--------------------------------- | 24 | | Environment: | Cloud Foundry Runtime | 25 | | Plan: | *standard* | 26 | | Landscape: | choose an appropiate AWS landscape | 27 | | Instance Name: | *authorreadings* | 28 | | Org Name: | *authorreadings* | 29 | 30 | ### Enable SAP Business Application Studio 31 | 32 | After creating a new BTP Subaccount, only the standard services appear in the entitlements list. To enable *SAP Business Application Studio*, assign an according entitlement to the newly created BTP Subaccount. 33 | 34 | For this navigate to the BTP Global Account and go to *Entitlements* and *Entity Assignments*. Open the value help on the *Select Entities* field and mark the corresponding BTP Subaccount. 35 | 36 | 37 | 38 | Press on *Configure Entitlements* and then *Add Service Plans*. Select the *SAP Business Application Studio* entitlement and decide for an available plan. 39 | 40 | 41 | 42 | Press on *Add 1 Service Plan* and *Save*. 43 | 44 | Navigate back to your BTP Subaccount. The *SAP Business Application Studio* is now available in the list of Entitlements. Create an instance of this service within the BTP Subaccount by going to the *Service Marketplace* and look for *SAP Business Application Studio* and press *Create*. 45 | 46 | 47 | 48 | The instance appears in the list of subscriptions. 49 | 50 | 51 | 52 | Just starting it will result in an *Access Denied* because the user roles are not yet assigned for this service instance. To do so, go to *Security* and *Users*. Select your user and and go to the assigned *Role Collections*. Select all 3 roles of *SAP Business Application Studio* and confirm the assignment. 53 | 54 | 55 | 56 | Three role collections have been added by *SAP Business Application Studio* already. 57 | 58 | 59 | 60 | Now you can start the *SAP Business Application Studio*. If the access is denied wait some seconds and try again. You may need to clear your browser cache. 61 | 62 | 63 | 64 | After starting the development environment, create a new *Dev Space* for the development of this tutorial. Name it `AuthorReadings` and choose to create a *Full Stack Cloud Application*. 65 | 66 | 67 | 68 | ## Setup GIT repository 69 | 70 | Create a new github repository in a github organization of your choice as code repository of your own project and link it with your *Dev Space*. 71 | 72 | Alternatively you can clone this repository into your *Dev Space* to deploy and run the sample application as provided in this repository. 73 | -------------------------------------------------------------------------------- /Tutorials/06-Manage-Data-Privacy.md: -------------------------------------------------------------------------------- 1 | # Manage Data Privacy 2 | 3 | Using the audit log you can ensure your application is compliant to data privacy requirements. 4 | For more information see: [Cloud Application Programming - Managing Data Privacy](https://cap.cloud.sap/docs/guides/data-privacy). 5 | 6 | ## Application enablement (same for one-off and multi tenancy) 7 | 8 | Open file `./srv/service-models.cds` and add the annotations for the audit log: 9 | ```javascript 10 | // ------------------------------------------------------------------------------- 11 | // Annotations for data privacy 12 | 13 | annotate AuthorReadingManager.AuthorReadings with @PersonalData : { 14 | DataSubjectRole : 'AuthorReadings', 15 | EntitySemantics : 'DataSubject' 16 | } 17 | { 18 | ID @PersonalData.FieldSemantics : 'DataSubjectID'; 19 | identifier @PersonalData.FieldSemantics : 'DataSubjectID'; 20 | description @PersonalData.FieldSemantics : 'DataSubjectID'; 21 | participantsFeeAmount @PersonalData.IsPotentiallySensitive; 22 | } 23 | 24 | annotate AuthorReadingManager.Participants with @PersonalData : { 25 | DataSubjectRole : 'AuthorReadings', 26 | EntitySemantics : 'DataSubjectDetails' 27 | } 28 | { 29 | ID @PersonalData.FieldSemantics : 'DataSubjectID'; 30 | identifier @PersonalData.FieldSemantics : 'DataSubjectID'; 31 | parent @PersonalData.FieldSemantics : 'DataSubjectID'; 32 | name @PersonalData.IsPotentiallyPersonal; 33 | email @PersonalData.IsPotentiallySensitive; 34 | mobileNumber @PersonalData.IsPotentiallySensitive; 35 | } 36 | 37 | // Annotations for audit logging 38 | annotate AuthorReadingManager.AuthorReadings with @AuditLog.Operation : { 39 | Read : true, 40 | Insert : true, 41 | Update : true, 42 | Delete : true 43 | }; 44 | annotate AuthorReadingManager.Participants with @AuditLog.Operation : { 45 | Read : true, 46 | Insert : true, 47 | Update : true, 48 | Delete : true 49 | }; 50 | ``` 51 | 52 | Open file `./package.json` and add the dependency to the audit log npm package, check the version of th cds dependency (should be at least 5.9.4), and the configuration for the audit log: 53 | ```json 54 | "dependencies": { 55 | "@sap/cds": "^5.9.4", 56 | "@sap/audit-logging": "^5.1.0" 57 | }, 58 | "cds": { 59 | "features": { 60 | "audit_personal_data": true 61 | }, 62 | "requires": { 63 | "audit-log": { 64 | "[sandbox]": { 65 | "kind": "audit-log-to-console" 66 | }, 67 | "[production]": { 68 | "kind": "audit-log-service" 69 | } 70 | } 71 | } 72 | } 73 | ``` 74 | 75 | Open file `./mta.yaml` and add the module dependency and the audit log resource. 76 | ```yml 77 | modules: 78 | - name: author-readings-srv 79 | requires: 80 | - name: author-readings-auditlog 81 | 82 | resources: 83 | - name: author-readings-auditlog 84 | type: org.cloudfoundry.managed-service 85 | parameters: 86 | service: auditlog 87 | service-plan: standard 88 | ``` 89 | 90 | ## BTP Configuration 91 | 92 | BTP provider subaccount: 93 | 94 | Add the required entitlements to the BTP provider subaccount: 95 | - Service `Auditlog Service` with plan `standard` to write audit logs 96 | - Service `Audit Log Viewer Service` with plan `default (Application)` to view audit logs 97 | 98 | Create an instance of the audit log viewer: 99 | 1. Open menu item *Service Marketplace* and create an instance of service `Audit Log Viewer Service` with plan `default (Application)`. 100 | 101 | To actually be able to view logs additional authorizations must be added: 102 | 1. Open the menu item *Role Collections* and create a new role collection with name `AuditLog`. 103 | 2. Edit the role colection and 104 | 1. Add the roles *Auditlog_Auditor* for both applications: *Auditlog Management* and *Audit Log Viewer*. 105 | 2. Add the user group "Author_Readings_Admin". 106 | 107 | Run command `npm install` to install the audit log npm packages. 108 | 109 | Build and deploy the application and observe that an audit log service instance has been created. 110 | 111 | See chapter [ByD Integration](04-ByD-Integration.md) to add the audit log viewer to the ByD launchpad. 112 | -------------------------------------------------------------------------------- /Tutorials/07-Test-Trace-Debug.md: -------------------------------------------------------------------------------- 1 | # Test and Debug 2 | 3 | When developing a productive application further topics like finding and analysing issues become also important. For now these topics are only described high level to give an idea of the direction. 4 | 5 | ## Test 6 | 7 | The application can be manually tested locally as long as no Event Mesh based integration has been added. 8 | 9 | 1. Edit the sandbox credentials in file `package.json`: 10 | ```json 11 | "byd_khproject": { 12 | "kind": "odata-v2", 13 | "model": "srv/external/byd_khproject", 14 | "[sandbox]": { 15 | "credentials": { 16 | "url": "https://{{byd-hostname}}/sap/byd/odata/cust/v1/khproject/", 17 | "authentication": "BasicAuthentication", 18 | "username": "{{user}}", 19 | "password": "{{password}}" 20 | } 21 | } 22 | }, 23 | "byd_khproject_tech_user": { 24 | "kind": "odata-v2", 25 | "model": "srv/external/byd_khproject_tech_user", 26 | "[sandbox]": { 27 | "credentials": { 28 | "url": "https://{{byd-hostname}}/sap/byd/odata/cust/v1/khproject/", 29 | "authentication": "BasicAuthentication", 30 | "username": "{{user}}", 31 | "password": "{{password}}" 32 | } 33 | } 34 | }, 35 | ``` 36 | 37 | 2. Run command `cds watch` or `cds watch profile --sandbox` on the command line interface. This will start a NodeJS-server including the web application. 38 | 39 | After adding the event-based integration with ByD 40 | 41 | 1. Run command `cf env author-readings-srv` to get the environment properties. 42 | 43 | 2. Add a new file `default-env.json` to the project root folder. 44 | 45 | 3. Copy the sections referring to the properties `VCAP_SERVICES` and `VCAP_APPLICATION` into the new file, enclose the two property names by double quotes, and embrace it all by curly brackets. In result the file content should look like 46 | ```javascript 47 | { 48 | "VCAP_SERVICES": { 49 | //content 50 | }, 51 | "VCAP_APPLICATION": { 52 | //content 53 | } 54 | } 55 | ``` 56 | 57 | 4. Now you can test in BAS using the command `cds watch profile --production`. 58 | 59 | ## Tracing 60 | 61 | You may consider adding log statements to the service implementations, such as for example 62 | ```javascript 63 | console.log("Author reading " + authorReadingIdentifier +" is blocked via event message"); 64 | console.log("Event message log updated"); 65 | console.log("Internal error on processing ByD event notifications: " + error); 66 | ``` 67 | 68 | In result you can review your own and others log messages using command `cf logs author-readings-srv --recent` in the BAS terminal. 69 | 70 | ## Debug 71 | 72 | Local debugging can be done with the standard nodeJS debugging tools. 73 | See also [CAP Debugging](https://cap.cloud.sap/docs/tools/#debugging-with-cds-watch). 74 | -------------------------------------------------------------------------------- /Tutorials/30-Guided-Tour.md: -------------------------------------------------------------------------------- 1 | # A Guided Tour to explore the Capabilities of the Sample Application 2 | 3 | Step into the shoes of an event manager and assume your job is to organize and run author reading events and poetry slams for reading clubs, book fairs and other occasions. 4 | 5 | Your company is running its business on the SAP system *SAP Business ByDesign* (ByD) and as a project manager your home-base is the work center *Project Management*. You are using ByD projects to plan and staff events, to collect costs and to purchase required equipments. Furthermore you are using the partner application "Author reading management" to publish author reading events and poetry slams and to register participants. 6 | 7 | Let's go on a guided tour through the integrated sample solution: 8 | 9 | 1. Open ByD using the single sign-on URL (for example https://my123456-sso.sapbydesign.com). 10 | 11 | > Note: ByD delegates the user authentication to the *SAP Identity Authentication Service* which acts as corporate identity provider in our example. 12 | 13 | 2. On the ByD Launchpad you find the partner application "*Author Readings*". Click on the tile to launch the app in a new browser window. 14 | 15 | 16 | 17 | > Note: The partner app is embedded on the ByD launchpad using ByD URL mashup capabilities. Additionally you can launch other BTP apps relevant for key users and administrators such as the *Identity Authentication Service* to manage user authentications and authorizations and the *Audit Log Viewer* to review user logins, the read access log and logged changes. 18 | Launching these apps does not require to login again because they linked to your corporate IDP as well and you benefit from single sign-on. 19 | 20 | 3. In the author reading app you find multiple author readings and poetry slams; some are still in preparation and "Not Released", others are already published. 21 | 22 | > Note: You see a metadata-driven UI in-line with SAP style guides. Using the *Theme Manager* you can choose your favorite theme. Furthermore, you can customize the table layout and adopt the filter area to meet your personal preferences. 23 | The *Export to Spreadsheet*-function allows you to download the author reading data into Excel. All these capabilities are provided out-of-the-box without development efforts. 24 | 25 | 4. Click on one of the author readings with status "Published" to navigate into the author reading details. 26 | 27 | 5. Click on button "*Edit*" and change the phone number of one of the participants. Then click on button "*Save*" to publish the changes. 28 | 29 | > Note: Your changes are imediately saved to the database as "Draft". Additionally the system locks the author reading for other users to avoid concurrent changes. Only by clicking on "*Save*" your changes become visible to all users and the edit-lock gets released. This provides you sufficient time to make your changes and you may even grab a cup of coffee in between. 30 | 31 | 6. Click on button "*Create Project*". In result the system creates a project in ByD based on a project template. 32 | 33 | 34 | 35 | > Note: The app creates the project in ByD using a ByD OData service for projects with user propagation. This means your ByD user authorizations apply in the partner application as well; you cannot create a project if your user does not have write-authorizations for ByD projects. 36 | 37 | 7. After creating the project you see some brief project details in section *Project Data*. The project ID is displayed as link. Click on the project ID to navigate to the project overview. 38 | 39 | 40 | 41 | > Note: The app mixed-in live project data from ByD (no data replication with delays). The app gets the ByD project data using the ByD OData service for projects and user propagation again, and hence this data is only visible if you have the authorizations to read projects in ByD. 42 | The link to launch the ByD project overview is assembled dynamically and uses the ByD hostname of your BTP subaccount configuration as well as the project ID. 43 | By navigating back to ByD no login is required because of single sign-on. 44 | 45 | 8. On the ByD project overview click on "*View All*" to navigate to the project GANT-chart. You can see that the project has been created using a template with tasks to plan and run the event and that the project finish date has been taken over from the author reading event date. Assume your project requires additional staffing and you need to put the project on hold until clarification: Select the checkbox "*On Hold*" in section "*Basic Data*". Save the project changes. 46 | 47 | 48 | 49 | > Note: Saving the project triggers a event notification of the ByD business object *Paroject*, and ByD publishes this event notification to the *SAP Event Mesh*. You can monitor the event notifications in the ByD work center view *Application and User Management - Event Notification Monitoring* or on the *Event Mesh* application. 50 | 51 | 9. Switch back to the browser window with the author reading app and refresh the browser window. You can see that the status has been changed automatically to "Blocked" to reflect the project status and to avoid further participant registrations. 52 | 53 | > Note: On the *SAP Event Mesh* the BTP application subcribed to ByD project events and triggered the "Block"-action on the author reading instance which is associated to the project. The BTP app retrieves additonal project data from ByD based on the project key provided in the event notification payload. This "call-back" uses the ByD OData service for projects with a technical user because the event-based integration is by design an asychronous integration without business user context. 54 | 55 | > Note: The BTP app itself emits event notifications as well, if author readings are published or blocked. The events are published on the *SAP Event Mesh* to support the integration with 3rd-party applications. We added the event notifications as a short system message in section *Adminitrative Data* on the author reading details screen for demo purposes. You find the full details and the payload of the event notifications in the *Event Mesh* application. 56 | 57 | 10. Switch to the ByD launchpad and open the "*Audit Log Viewer*". In the audit log viewer change the from-date to yesterday and click on the "play"-button on the upper right corner. Then enter your name in the filter to search for your own logs. Looking for data-modification events for example, you can find the log entry of the phone number that you changed in step 5. 58 | 59 | > Note: You can see logs of three categories: Security events refer to login- and authentication events, data-access events refer to read access to personal data, and data-modification events refer to data changes. 60 | 61 | This concludes the guided tour ... I hope you had an insightful trip :-) -------------------------------------------------------------------------------- /Tutorials/72-Multi-Tenancy-Provisioning-Service-Broker.md: -------------------------------------------------------------------------------- 1 | # Configure and Consume the APIs of the BTP Application 2 | 3 | In earlier steps [Enhance the BTP Application by a Service Broker](../Tutorials/71-Multi-Tenancy-Service-Broker.md) the service broker is available as part of application deployed in the provider BTP subaccount. 4 | 5 | The service broker is used to enable access to application OData services using tenant-specific credentials and authorizations taking into account the tenant isolation in an multi-tenant application. 6 | 7 | In this tutorial we describe the steps to configure and consume the APIs of the BTP application in the consumer BTP subaccount. 8 | 9 | ## Service Broker configuration in an subscriber BTP subaccount involves following steps: 10 | 11 | In general there are two approaches to create a service broker instance in the consumer subaccount: You can use the Cloud Foundry CLI or the BTP CLI. In our example here we use the CF CLI because using the BTP CLI would require additional steps to install BTP CLI and run the BTP commands. 12 | 13 | BTP Cockpit - consumer subaccount: 14 | 15 | 1. Activate Cloud Foundry (without quota) 16 | - Open the consumer subaccount. 17 | - Create an instance of Cloud Foundry without quota. 18 | > Note: Cloud Foundry instance is required to run the cloud foundry commands for the creation of service broker instance (as shown in next steps) and user should have administrative permissions with access to Cloud Foundry space to run service broker related commands. 19 | - Provide a user with administrative permissions, with access to *Cloud Foundry org member* and *Cloud Foundry space member*. 20 | 21 | Business Application Studio: 22 | 23 | 2. Create a service broker instance 24 | - Login to the Cloud Foundry space of the consumer subaccount (command `cf login`). 25 | - Create a service broker instance using the following command 26 | `cf create-service-broker --space-scoped` (example: `cf create-service-broker author-readings-armt-s2 brokeruser e5jS3jVzchJK3b8cRR88R3CW0qMaFK7V https://armt-runtime-author-readings-servicebroker.cfapps.eu10.hana.ondemand.com --space-scoped` 27 | 28 | > Note: The broker-name-per-tenant needs to be unique in the global account; we suggest using the tenant number as suffix, for example: If the tenant name is "armt-s2" then set the broker name "service-broker-armt-s2". 29 | 30 | > Note: *broker-user* and *plain-broker-password* is generated in the earlier chapter [Enhance the BTP Application by a Service Broker](../Tutorials/71-Multi-Tenancy-Service-Broker.md); replace *plain-broker-password* with the plaintext password generated by hash-broker-password script. 31 | 32 | > Note: you delete the service broker instance using the command `cf delete-service-broker `. 33 | 34 | > Note: Space scoped brokers are registered to a specific space, and all users within that space can access the broker’s service plans. With space-scoped brokers, service visibility is not managed separately. 35 | 36 | > Note: BrokerName is an arbitrary name used to distinguish the service broker from the rest. It is independent from the broker application name. 37 | 38 | BTP Cockpit - consumer subaccount: 39 | 40 | 3. Open the CF space and navigate to the CF space *Service Marketspace*: Create an instance of the *Author Readings API*-service and choose an instance name, for example "author-readings-api". 41 | 42 | 4. Open the BTP cockpit menu item *Instances and Subscriptions* and create a *Service Key* for the newly created service broker instance 43 | - Click on *Create* button in the *Service Keys* section 44 | - Enter arbitary *Service Key Name* (e.g. "api-key") 45 | - Click on *Create* button 46 | - Click on the above created *Service Key*, check the service key json and take note of the following elements: 47 | - *endpoints.authorreadings* (in the first line of the json) as **Service Key API-Endpoint** 48 | - *uaa.clientid* as **Service Key UAA Client-ID** 49 | - *uaa.clientsecret* as **Service Key UAA Client-Secret** 50 | - *uaa.url* as **Service Key UAA-URL** 51 | 52 | With these steps you are ready to explore and test the OData services using Postman. In folder [api-samples](./api-samples/) you find a Postman collection and a Postman environment with some examples. Check the documentation of the Postman collection for further details about how to run the examples. 53 | -------------------------------------------------------------------------------- /Tutorials/api-samples/Partner Reference App (MT).postman_environment.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "8611830a-95b3-46f4-8046-a755b84e37a4", 3 | "name": "Partner Reference App (MT)", 4 | "values": [ 5 | { 6 | "key": "api_url", 7 | "value": "", 8 | "enabled": true 9 | }, 10 | { 11 | "key": "uaa_clientid", 12 | "value": "", 13 | "enabled": true 14 | }, 15 | { 16 | "key": "uaa_clientsecret", 17 | "value": "", 18 | "enabled": true 19 | }, 20 | { 21 | "key": "uaa_url", 22 | "value": "", 23 | "enabled": true 24 | }, 25 | { 26 | "key": "AuthorReadings_ID", 27 | "value": "79ceab87-300d-4b66-8cc3-f82c679b77a1", 28 | "type": "any", 29 | "enabled": true 30 | }, 31 | { 32 | "key": "AuthorReading_Identifier", 33 | "value": "1", 34 | "type": "any", 35 | "enabled": true 36 | }, 37 | { 38 | "key": "ProjectID", 39 | "value": "", 40 | "type": "default", 41 | "enabled": true 42 | }, 43 | { 44 | "key": "ProjectObjectID", 45 | "value": "", 46 | "type": "default", 47 | "enabled": true 48 | }, 49 | { 50 | "key": "ProjectURL", 51 | "value": "", 52 | "type": "default", 53 | "enabled": true 54 | }, 55 | { 56 | "key": "ProjectSystem", 57 | "value": "", 58 | "type": "default", 59 | "enabled": true 60 | } 61 | ], 62 | "_postman_variable_scope": "environment", 63 | "_postman_exported_at": "2023-08-11T12:46:35.193Z", 64 | "_postman_exported_using": "Postman/10.8.0" 65 | } -------------------------------------------------------------------------------- /Tutorials/images/20-byd-launchpad.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/20-byd-launchpad.jpg -------------------------------------------------------------------------------- /Tutorials/images/20-create-project.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/20-create-project.jpg -------------------------------------------------------------------------------- /Tutorials/images/20-project-mixin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/20-project-mixin.jpg -------------------------------------------------------------------------------- /Tutorials/images/20-project-onhold.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/20-project-onhold.jpg -------------------------------------------------------------------------------- /Tutorials/images/ByD_integration_overview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/ByD_integration_overview.jpg -------------------------------------------------------------------------------- /Tutorials/images/Dependencies_with_destination.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/Dependencies_with_destination.png -------------------------------------------------------------------------------- /Tutorials/images/Dependencies_without_destination.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/Dependencies_without_destination.png -------------------------------------------------------------------------------- /Tutorials/images/FE-Wizard-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/FE-Wizard-open.png -------------------------------------------------------------------------------- /Tutorials/images/FE-Wizard2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/FE-Wizard2.png -------------------------------------------------------------------------------- /Tutorials/images/FE-Wizard3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/FE-Wizard3.png -------------------------------------------------------------------------------- /Tutorials/images/FE-Wizard4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/FE-Wizard4.png -------------------------------------------------------------------------------- /Tutorials/images/FE-Wizard5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/FE-Wizard5.png -------------------------------------------------------------------------------- /Tutorials/images/FLP1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/FLP1.png -------------------------------------------------------------------------------- /Tutorials/images/btp_eventmesh_entitlements.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/btp_eventmesh_entitlements.jpg -------------------------------------------------------------------------------- /Tutorials/images/btp_eventmesh_service1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/btp_eventmesh_service1.jpg -------------------------------------------------------------------------------- /Tutorials/images/btp_eventmesh_service2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/btp_eventmesh_service2.jpg -------------------------------------------------------------------------------- /Tutorials/images/byd_launchpad.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/byd_launchpad.jpg -------------------------------------------------------------------------------- /Tutorials/images/enableBAS1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/enableBAS1.png -------------------------------------------------------------------------------- /Tutorials/images/enableBAS2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/enableBAS2.png -------------------------------------------------------------------------------- /Tutorials/images/enableBAS3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/enableBAS3.png -------------------------------------------------------------------------------- /Tutorials/images/enableBAS4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/enableBAS4.png -------------------------------------------------------------------------------- /Tutorials/images/enableBAS5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/enableBAS5.png -------------------------------------------------------------------------------- /Tutorials/images/enableBAS6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/enableBAS6.png -------------------------------------------------------------------------------- /Tutorials/images/enableCF1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/enableCF1.png -------------------------------------------------------------------------------- /Tutorials/images/launchpad_sitemanager1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/launchpad_sitemanager1.jpg -------------------------------------------------------------------------------- /Tutorials/images/launchpad_sitemanager3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/launchpad_sitemanager3.jpg -------------------------------------------------------------------------------- /Tutorials/images/mt_byd_integration.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/mt_byd_integration.jpg -------------------------------------------------------------------------------- /Tutorials/images/mt_byd_launchpad.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/mt_byd_launchpad.jpg -------------------------------------------------------------------------------- /Tutorials/images/mt_deployment_model.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/mt_deployment_model.jpg -------------------------------------------------------------------------------- /Tutorials/images/mt_s4hc_integration.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/mt_s4hc_integration.jpg -------------------------------------------------------------------------------- /Tutorials/images/mt_s4hc_launchpad.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/mt_s4hc_launchpad.jpg -------------------------------------------------------------------------------- /Tutorials/images/readme_bom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/readme_bom.jpg -------------------------------------------------------------------------------- /Tutorials/images/readme_btp_components.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/readme_btp_components.jpg -------------------------------------------------------------------------------- /Tutorials/images/readme_incremental-approach.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/readme_incremental-approach.jpg -------------------------------------------------------------------------------- /Tutorials/images/readme_progressive_dev.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/readme_progressive_dev.jpg -------------------------------------------------------------------------------- /Tutorials/images/readme_sample-deployment.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/readme_sample-deployment.jpg -------------------------------------------------------------------------------- /Tutorials/images/readme_sample-use-case.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/readme_sample-use-case.jpg -------------------------------------------------------------------------------- /Tutorials/images/startBAS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/startBAS.png -------------------------------------------------------------------------------- /Tutorials/images/startBAS2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/sme-partner-reference-application/2ce4a3ba9497a230fbe962a3da3b20c8e96ea675/Tutorials/images/startBAS2.png --------------------------------------------------------------------------------