diff --git a/bookshop/app/travel_tree/webapp/Component.js b/bookshop/app/travel_tree/webapp/Component.js
new file mode 100644
index 00000000..5dfba605
--- /dev/null
+++ b/bookshop/app/travel_tree/webapp/Component.js
@@ -0,0 +1,6 @@
+sap.ui.define(["sap/fe/core/AppComponent"], function (Component) {
+ "use strict";
+ return Component.extend("sap.fe.cap.travel_tree.Component", {
+ metadata: { manifest: "json" },
+ });
+});
diff --git a/bookshop/app/travel_tree/webapp/View.view.xml b/bookshop/app/travel_tree/webapp/View.view.xml
new file mode 100644
index 00000000..8b7e5974
--- /dev/null
+++ b/bookshop/app/travel_tree/webapp/View.view.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/bookshop/app/travel_tree/webapp/index.html b/bookshop/app/travel_tree/webapp/index.html
new file mode 100644
index 00000000..23bc1b27
--- /dev/null
+++ b/bookshop/app/travel_tree/webapp/index.html
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bookshop/app/travel_tree/webapp/manifest.json b/bookshop/app/travel_tree/webapp/manifest.json
new file mode 100644
index 00000000..26643ae5
--- /dev/null
+++ b/bookshop/app/travel_tree/webapp/manifest.json
@@ -0,0 +1,133 @@
+{
+ "_version": "1.42.0",
+ "sap.app": {
+ "id": "sap.fe.cap.travel_tree",
+ "type": "application",
+ "title": "{{title}}",
+ "description": "{{description}}",
+ "i18n": {
+ "bundleName": "sap.fe.cap.travel_tree.i18n.i18n",
+ "supportedLocales": ["en", "de", "fr"],
+ "fallbackLocale": "en"
+ },
+ "applicationVersion": {
+ "version": "1.0.0"
+ },
+ "dataSources": {
+ "mainService": {
+ "uri": "v2/browse/",
+ "type": "OData",
+ "settings": {
+ "odataVersion": "2.0"
+ }
+ }
+ },
+ "resources": "resources.json",
+ "sourceTemplate": {
+ "id": "@sap/generator-fiori:lrop",
+ "version": "1.7.5",
+ "toolsId": "14e5ba92-7ef6-40ce-9b6b-9eff19d0c9a2"
+ },
+ "crossNavigation": {
+ "inbounds": {
+ "travel-alp-inbound": {
+ "signature": {
+ "parameters": {},
+ "additionalParameters": "allowed"
+ },
+ "semanticObject": "booking",
+ "action": "process",
+ "title": "Analyze Travels",
+ "subTitle": "Analyze travels",
+ "icon": "sap-icon://flight"
+ }
+ }
+ }
+ },
+ "sap.ui": {
+ "technology": "UI5",
+ "icons": {
+ "icon": "sap-icon://flight",
+ "favIcon": "sap-icon://flight",
+ "phone": "sap-icon://flight",
+ "phone@2": "sap-icon://flight",
+ "tablet": "sap-icon://flight",
+ "tablet@2": "sap-icon://flight"
+ },
+ "deviceTypes": {
+ "desktop": true,
+ "tablet": true,
+ "phone": true
+ }
+ },
+ "sap.ui5": {
+ "flexEnabled": true,
+ "dependencies": {
+ "minUI5Version": "1.108.10",
+ "libs": {
+ "sap.m": {},
+ "sap.ui.core": {},
+ "sap.ui.table": {},
+ "sap.ushell": {},
+ "sap.fe.templates": {}
+ }
+ },
+ "contentDensities": {
+ "compact": true,
+ "cozy": true
+ },
+ "models": {
+ "i18n": {
+ "type": "sap.ui.model.resource.ResourceModel",
+ "settings": {
+ "bundleName": "sap.fe.cap.travel_analytics.i18n.i18n",
+ "supportedLocales": ["en", "de", "fr"],
+ "fallbackLocale": "en"
+ }
+ },
+ "": {
+ "dataSource": "mainService",
+ "preload": true,
+ "settings": {
+ "synchronizationMode": "None",
+ "operationMode": "Server",
+ "autoExpandSelect": true,
+ "earlyRequests": true
+ }
+ },
+ "@i18n": {
+ "type": "sap.ui.model.resource.ResourceModel",
+ "uri": "i18n/i18n.properties"
+ }
+ },
+ "resources": {
+ "css": []
+ },
+ "routing": {
+ "config": {},
+ "routes": [
+ {
+ "pattern": ":?query:",
+ "name": "BookingTree",
+ "target": "BookingTree"
+ }
+ ],
+ "targets": {
+ "BookingTree": {
+ "type": "XML",
+ "id": "BookingTree",
+ "viewName": "sap.fe.cap.travel_tree.View",
+ "async": true
+ }
+ }
+ }
+ },
+ "sap.fiori": {
+ "registrationIds": [],
+ "archeType": "transactional"
+ },
+ "sap.cloud": {
+ "public": true,
+ "service": "sap.fe.cap.sflight"
+ }
+}
diff --git a/bookshop/db/schema.cds b/bookshop/db/schema.cds
index ec8b119a..00563f5e 100644
--- a/bookshop/db/schema.cds
+++ b/bookshop/db/schema.cds
@@ -1,31 +1,57 @@
-using { Currency, managed, sap } from '@sap/cds/common';
+using {
+ Currency,
+ managed,
+ sap
+} from '@sap/cds/common';
+
namespace sap.capire.bookshop;
entity Books : managed {
- key ID : Integer;
- title : localized String(111);
- descr : localized String(1111);
- author : Association to Authors;
- genre : Association to Genres;
- stock : Integer;
- price : Decimal;
- currency : Currency;
- image : LargeBinary @Core.MediaType : 'image/png';
+ key ID : Integer;
+ title : localized String(111);
+ descr : localized String(1111);
+ author : Association to Authors;
+ genre : Association to Genres;
+ stock : Integer;
+ price : Decimal;
+ currency : Currency;
+ image : LargeBinary @Core.MediaType: 'image/png';
}
entity Authors : managed {
- key ID : Integer;
- name : String(111);
- dateOfBirth : Date;
- dateOfDeath : Date;
- placeOfBirth : String;
- placeOfDeath : String;
- books : Association to many Books on books.author = $self;
+ key ID : Integer;
+ name : String(111);
+ dateOfBirth : Date;
+ dateOfDeath : Date;
+ placeOfBirth : String;
+ placeOfDeath : String;
+ books : Association to many Books
+ on books.author = $self;
}
-/** Hierarchically organized Code List for Genres */
+/**
+ * Hierarchically organized Code List for Genres
+ */
entity Genres : sap.common.CodeList {
- key ID : Integer;
- parent : Association to Genres;
- children : Composition of many Genres on children.parent = $self;
+ @sap.hierarchy.node.for : 'ID'
+ key ID : Integer;
+
+ @sap.hierarchy.parent.node.for: 'ID'
+ parent_ID : Integer;
+
+ children : Composition of many Genres
+ on children.parent_ID = $self.ID;
}
+
+entity GenresView as
+ select from Genres {
+ ID,
+ name,
+ parent_ID as parent,
+ @sap.hierarchy.level.for : 'ID'
+ (CASE WHEN parent_ID IS NULL THEN 0 ELSE 1 END) as level:Integer,
+ @sap.hierarchy.drill.state.for : 'ID'
+ (CASE WHEN $self.child_count>0 THEN 'collapsed' ELSE 'leaf' END) as expand:String,
+ @sap.hierarchy.node.descendant.count.for: 'ID'
+ (SELECT COUNT(1) as count FROM Genres as C WHERE C.parent_ID=Genres.ID) as child_count:Integer
+ };
diff --git a/bookshop/package.json b/bookshop/package.json
index 21b048d7..4e44e88a 100644
--- a/bookshop/package.json
+++ b/bookshop/package.json
@@ -17,7 +17,7 @@
"scripts": {
"genres": "cds serve test/genres.cds",
"start": "cds run",
- "watch": "cds watch"
+ "watch": "CDS_ENV=better-sqlite cds watch"
},
"cds": {
"requires": {
diff --git a/bookshop/srv/cat-service.cds b/bookshop/srv/cat-service.cds
index 2441db25..4ea70cf0 100644
--- a/bookshop/srv/cat-service.cds
+++ b/bookshop/srv/cat-service.cds
@@ -10,6 +10,8 @@ service CatalogService @(path:'/browse') {
author.name as author
} excluding { createdBy, modifiedBy };
+ entity GenresView as projection on my.GenresView;
+
@requires: 'authenticated-user'
action submitOrder ( book: Books:ID, quantity: Integer ) returns { stock: Integer };
event OrderedBook : { book: Books:ID; quantity: Integer; buyer: String };
diff --git a/bookshop/srv/server.js b/bookshop/srv/server.js
new file mode 100644
index 00000000..bc2ec865
--- /dev/null
+++ b/bookshop/srv/server.js
@@ -0,0 +1,4 @@
+const proxy = require('@sap/cds-odata-v2-adapter-proxy')
+const cds = require('@sap/cds')
+cds.on('bootstrap', app => app.use(proxy()))
+module.exports = cds.server