diff --git a/suppliers/app/_i18n/i18n.properties b/suppliers/app/_i18n/i18n.properties
new file mode 100644
index 00000000..05cd38b5
--- /dev/null
+++ b/suppliers/app/_i18n/i18n.properties
@@ -0,0 +1,31 @@
+Books = Books
+Book = Book
+ID = ID
+Title = Title
+Author = Author
+AuthorID = Author ID
+Stock = Stock
+Name = Name
+AuthorName = Author's Name
+DateOfBirth = Date of Birth
+DateOfDeath = Date of Death
+PlaceOfBirth = Place of Birth
+PlaceOfDeath = Place of Death
+Age = Age
+Authors = Authors
+Order = Order
+Orders = Orders
+Price = Price
+
+Genre = Genre
+Genres = Genres
+SubGenres = Sub Genres
+
+NumCode = Numeric Code
+MinorUnit = Minor Unit
+Exponent = Exponent
+
+Supplier = Supplier
+SupplierName = Supplier Name
+Id = Id
+Name = Name
\ No newline at end of file
diff --git a/suppliers/app/_i18n/i18n_de.properties b/suppliers/app/_i18n/i18n_de.properties
new file mode 100644
index 00000000..ee3b52f1
--- /dev/null
+++ b/suppliers/app/_i18n/i18n_de.properties
@@ -0,0 +1,18 @@
+Books = Bücher
+Book = Buch
+ID = ID
+Title = Titel
+Authors = Autoren
+Author = Autor
+AuthorID = ID des Autors
+AuthorName = Name des Autors
+Age = Alter
+Name = Name
+Stock = Bestand
+Order = Bestellung
+Orders = Bestellungen
+Price = Preis
+Supplier = Lieferant
+SupplierName = Lieferantenname
+Id = Id
+Name = Name
\ No newline at end of file
diff --git a/suppliers/app/admin-fiori.html b/suppliers/app/admin-fiori.html
new file mode 100644
index 00000000..6c229e6b
--- /dev/null
+++ b/suppliers/app/admin-fiori.html
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+ Bookshop
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/suppliers/app/admin/fiori-service.cds b/suppliers/app/admin/fiori-service.cds
new file mode 100644
index 00000000..da70b9b4
--- /dev/null
+++ b/suppliers/app/admin/fiori-service.cds
@@ -0,0 +1,121 @@
+//using { AdminService } from '../../db/schema';
+
+////////////////////////////////////////////////////////////////////////////
+//
+// Books Object Page
+//
+
+annotate AdminService.Books with @(
+ UI: {
+ Facets: [
+ {$Type: 'UI.ReferenceFacet', Label: '{i18n>General}', Target: '@UI.FieldGroup#General'},
+ {$Type: 'UI.ReferenceFacet', Label: '{i18n>Translations}', Target: 'texts/@UI.LineItem'},
+ {$Type: 'UI.ReferenceFacet', Label: '{i18n>Details}', Target: '@UI.FieldGroup#Details'},
+ {$Type: 'UI.ReferenceFacet', Label: '{i18n>Supplier}', Target: '@UI.FieldGroup#Supplier'},
+ {$Type: 'UI.ReferenceFacet', Label: '{i18n>Admin}', Target: '@UI.FieldGroup#Admin'},
+ ],
+ FieldGroup#General: {
+ Data: [
+ {Value: title},
+ {Value: author_ID},
+ {Value: genre_ID},
+ {Value: descr},
+ ]
+ },
+ FieldGroup#Details: {
+ Data: [
+ {Value: stock},
+ {Value: price},
+ {Value: currency_code, Label: '{i18n>Currency}'},
+ ]
+ },
+ FieldGroup#Supplier: {
+ Data: [
+ {Value: supplier_ID, Label: '{i18n>Id}'},
+ {Value: supplier.name, Label: '{i18n>Name}'}
+ ]
+ },
+ FieldGroup#Admin: {
+ Data: [
+ {Value: createdBy},
+ {Value: createdAt},
+ {Value: modifiedBy},
+ {Value: modifiedAt}
+ ]
+ }
+ }
+);
+
+annotate AdminService.Authors with @(
+ UI: {
+ HeaderInfo: {
+ Description: {Value: lifetime}
+ },
+ Facets: [
+ {$Type: 'UI.ReferenceFacet', Label: '{i18n>Details}', Target: '@UI.FieldGroup#Details'},
+ {$Type: 'UI.ReferenceFacet', Label: '{i18n>Books}', Target: 'books/@UI.LineItem'},
+ ],
+ FieldGroup#Details: {
+ Data: [
+ {Value: placeOfBirth},
+ {Value: placeOfDeath},
+ {Value: dateOfBirth},
+ {Value: dateOfDeath},
+ {Value: age, Label: '{i18n>Age}'},
+ ]
+ },
+ }
+);
+
+
+
+////////////////////////////////////////////////////////////
+//
+// Draft for Localized Data
+//
+
+annotate sap.capire.bookshop.Books with @fiori.draft.enabled;
+annotate AdminService.Books with @odata.draft.enabled;
+
+annotate AdminService.Books.texts with @(
+ UI: {
+ Identification: [{Value:title}],
+ SelectionFields: [ locale, title ],
+ LineItem: [
+ {Value: locale, Label: 'Locale'},
+ {Value: title, Label: 'Title'},
+ {Value: descr, Label: 'Description'}
+ ]
+ }
+);
+
+// Add Value Help for Locales
+annotate AdminService.Books.texts {
+ locale @ValueList:{entity:'Languages',type:#fixed}
+}
+// In addition we need to expose Languages through AdminService
+using { sap } from '@sap/cds/common';
+extend service AdminService {
+ entity Languages as projection on sap.common.Languages;
+}
+
+annotate AdminService.Books with {
+ supplier @(
+ Common: {
+ Label: '{i18n>Supplier}',
+ ValueList: {
+ Label: '{i18n>Supplier}',
+ CollectionPath: 'Suppliers',
+ Parameters: [
+ { $Type: 'Common.ValueListParameterInOut',
+ LocalDataProperty: supplier_ID,
+ ValueListProperty: 'ID'
+ },
+ { $Type: 'Common.ValueListParameterDisplayOnly',
+ ValueListProperty: 'name'
+ }
+ ]
+ }
+ }
+ );
+}
diff --git a/suppliers/app/admin/webapp/Component.js b/suppliers/app/admin/webapp/Component.js
new file mode 100644
index 00000000..c3137017
--- /dev/null
+++ b/suppliers/app/admin/webapp/Component.js
@@ -0,0 +1,8 @@
+sap.ui.define(["sap/fe/core/AppComponent"], function(AppComponent) {
+ "use strict";
+ return AppComponent.extend("admin.Component", {
+ metadata: { manifest: "json" }
+ });
+});
+
+/* eslint no-undef:0 */
\ No newline at end of file
diff --git a/suppliers/app/admin/webapp/i18n/i18n.properties b/suppliers/app/admin/webapp/i18n/i18n.properties
new file mode 100644
index 00000000..28b03dff
--- /dev/null
+++ b/suppliers/app/admin/webapp/i18n/i18n.properties
@@ -0,0 +1,11 @@
+# This is the resource bundle of itelo
+# __ldi.translation.uuid=c3431418-9caf-11e8-98d0-529269fb1459
+
+# JCI app descriptor contains lower case TITLE
+appTitle=Bookshop Sample
+
+# JCI app descriptor contains lower case DESCRIPTION
+appSubTitle=CAP Sample Application
+
+# JCI app descriptor contains lower case DESCRIPTION
+appDescription=CDS Sample Service
diff --git a/suppliers/app/admin/webapp/manifest.json b/suppliers/app/admin/webapp/manifest.json
new file mode 100644
index 00000000..25047c29
--- /dev/null
+++ b/suppliers/app/admin/webapp/manifest.json
@@ -0,0 +1,128 @@
+{
+ "_version": "1.8.0",
+ "sap.app": {
+ "id": "admin",
+ "type": "application",
+ "title": "Manage Books",
+ "description": "Sample Application",
+ "i18n": "i18n/i18n.properties",
+ "dataSources": {
+ "AdminService": {
+ "uri": "/admin/",
+ "type": "OData",
+ "settings": {
+ "odataVersion": "4.0"
+ }
+ }
+ },
+ "-sourceTemplate": {
+ "id": "ui5template.basicSAPUI5ApplicationProject",
+ "-id": "ui5template.smartTemplate",
+ "-version": "1.40.12"
+ }
+ },
+ "sap.ui5": {
+ "dependencies": {
+ "libs": {
+ "sap.fe.templates": {}
+ }
+ },
+ "models": {
+ "i18n": {
+ "type": "sap.ui.model.resource.ResourceModel",
+ "uri": "i18n/i18n.properties"
+ },
+ "": {
+ "dataSource": "AdminService",
+ "settings": {
+ "synchronizationMode": "None",
+ "operationMode": "Server",
+ "autoExpandSelect" : true,
+ "earlyRequests": true,
+ "groupProperties": {
+ "default": {
+ "submit": "Auto"
+ }
+ }
+ }
+ }
+ },
+ "routing": {
+ "routes": [
+ {
+ "pattern": ":?query:",
+ "name": "BooksList",
+ "target": "BooksList"
+ },
+ {
+ "pattern": "Books({key}):?query:",
+ "name": "BooksDetails",
+ "target": "BooksDetails"
+ },
+ {
+ "pattern": "Books({key}/author({key2}):?query:",
+ "name": "AuthorsDetails",
+ "target": "AuthorsDetails"
+ }
+ ],
+ "targets": {
+ "BooksList": {
+ "type": "Component",
+ "id": "BooksList",
+ "name": "sap.fe.templates.ListReport",
+ "options": {
+ "settings" : {
+ "entitySet" : "Books",
+ "navigation" : {
+ "Books" : {
+ "detail" : {
+ "route" : "BooksDetails"
+ }
+ }
+ }
+ }
+ }
+ },
+ "BooksDetails": {
+ "type": "Component",
+ "id": "BooksDetailsList",
+ "name": "sap.fe.templates.ObjectPage",
+ "options": {
+ "settings" : {
+ "entitySet" : "Books",
+ "navigation" : {
+ "Authors" : {
+ "detail" : {
+ "route" : "AuthorsDetails"
+ }
+ }
+ }
+ }
+ }
+ },
+ "AuthorsDetails": {
+ "type": "Component",
+ "id": "AuthorsDetailsList",
+ "name": "sap.fe.templates.ObjectPage",
+ "options": {
+ "settings" : {
+ "entitySet" : "Authors"
+ }
+ }
+ }
+ }
+ },
+ "contentDensities": {
+ "compact": true,
+ "cozy": true
+ }
+ },
+ "sap.ui": {
+ "technology": "UI5",
+ "fullWidth": false
+ },
+ "sap.fiori": {
+ "registrationIds": [],
+ "archeType": "transactional"
+ }
+}
\ No newline at end of file
diff --git a/suppliers/app/common.cds b/suppliers/app/common.cds
new file mode 100644
index 00000000..a37b2b05
--- /dev/null
+++ b/suppliers/app/common.cds
@@ -0,0 +1,264 @@
+/*
+ Common Annotations shared by all apps
+*/
+
+using { sap.capire.bookshop as my } from '@capire/bookshop';
+using { sap.common } from '@capire/common';
+
+////////////////////////////////////////////////////////////////////////////
+//
+// Books Lists
+//
+annotate my.Books with @(
+ Common.SemanticKey: [title],
+ UI: {
+ Identification: [{Value:title}],
+ SelectionFields: [ ID, author_ID, price, currency_code, supplier_ID, supplier.name ],
+ LineItem: [
+ {Value: ID},
+ {Value: title},
+ {Value: author.name, Label:'{i18n>Author}'},
+ {Value: genre.name},
+ {Value: stock},
+ {Value: price},
+ {Value: currency.symbol, Label:' '},
+ {Value: supplier_ID},
+ {Value: supplier.name}
+ ]
+ }
+) {
+ author @ValueList.entity:'Authors';
+};
+
+////////////////////////////////////////////////////////////////////////////
+//
+// Books Details
+//
+annotate my.Books with @(
+ UI: {
+ HeaderInfo: {
+ TypeName: '{i18n>Book}',
+ TypeNamePlural: '{i18n>Books}',
+ Title: {Value: title},
+ Description: {Value: author.name}
+ },
+ }
+);
+
+
+
+////////////////////////////////////////////////////////////////////////////
+//
+// Books Elements
+//
+annotate my.Books with {
+ ID @title:'{i18n>ID}' @UI.HiddenFilter;
+ title @title:'{i18n>Title}';
+ genre @title:'{i18n>Genre}' @Common: { Text: genre.name, TextArrangement: #TextOnly };
+ author @title:'{i18n>Author}' @Common: { Text: author.name, TextArrangement: #TextOnly };
+ price @title:'{i18n>Price}' @Measures.ISOCurrency: currency_code;
+ stock @title:'{i18n>Stock}';
+ descr @UI.MultiLineText;
+ supplier_ID @title:'{i18n>Supplier}';
+}
+
+annotate my.Suppliers with {
+ name @title:'{i18n>SupplierName}';
+}
+
+////////////////////////////////////////////////////////////////////////////
+//
+// Genres List
+//
+annotate my.Genres with @(
+ Common.SemanticKey: [name],
+ UI: {
+ SelectionFields: [ name ],
+ LineItem:[
+ {Value: name},
+ {Value: parent.name, Label: 'Main Genre'},
+ ],
+ }
+);
+
+////////////////////////////////////////////////////////////////////////////
+//
+// Genre Details
+//
+annotate my.Genres with @(
+ UI: {
+ Identification: [{Value:name}],
+ HeaderInfo: {
+ TypeName: '{i18n>Genre}',
+ TypeNamePlural: '{i18n>Genres}',
+ Title: {Value: name},
+ Description: {Value: ID}
+ },
+ Facets: [
+ {$Type: 'UI.ReferenceFacet', Label: '{i18n>SubGenres}', Target: 'children/@UI.LineItem'},
+ ],
+ }
+);
+
+////////////////////////////////////////////////////////////////////////////
+//
+// Genres Elements
+//
+annotate my.Genres with {
+ ID @title: '{i18n>ID}';
+ name @title: '{i18n>Genre}';
+}
+
+////////////////////////////////////////////////////////////////////////////
+//
+// Authors List
+//
+annotate my.Authors with @(
+ Common.SemanticKey: [name],
+ UI: {
+ Identification: [{Value:name}],
+ SelectionFields: [ name ],
+ LineItem:[
+ {Value: ID},
+ {Value: name},
+ {Value: dateOfBirth},
+ {Value: dateOfDeath},
+ {Value: placeOfBirth},
+ {Value: placeOfDeath},
+ ],
+ }
+);
+
+////////////////////////////////////////////////////////////////////////////
+//
+// Author Details
+//
+annotate my.Authors with @(
+ UI: {
+ HeaderInfo: {
+ TypeName: '{i18n>Author}',
+ TypeNamePlural: '{i18n>Authors}',
+ Title: {Value: name},
+ Description: {Value: dateOfBirth}
+ },
+ Facets: [
+ {$Type: 'UI.ReferenceFacet', Target: 'books/@UI.LineItem'},
+ ],
+ }
+);
+
+
+////////////////////////////////////////////////////////////////////////////
+//
+// Authors Elements
+//
+annotate my.Authors with {
+ ID @title:'{i18n>ID}' @UI.HiddenFilter;
+ name @title:'{i18n>Name}';
+ dateOfBirth @title:'{i18n>DateOfBirth}';
+ dateOfDeath @title:'{i18n>DateOfDeath}';
+ placeOfBirth @title:'{i18n>PlaceOfBirth}';
+ placeOfDeath @title:'{i18n>PlaceOfDeath}';
+}
+
+////////////////////////////////////////////////////////////////////////////
+//
+// Languages List
+//
+annotate common.Languages with @(
+ Common.SemanticKey: [code],
+ Identification: [{Value:code}],
+ UI: {
+ SelectionFields: [ name, descr ],
+ LineItem:[
+ {Value: code},
+ {Value: name},
+ ],
+ }
+);
+
+////////////////////////////////////////////////////////////////////////////
+//
+// Language Details
+//
+annotate common.Languages with @(
+ UI: {
+ HeaderInfo: {
+ TypeName: '{i18n>Language}',
+ TypeNamePlural: '{i18n>Languages}',
+ Title: {Value: name},
+ Description: {Value: descr}
+ },
+ Facets: [
+ {$Type: 'UI.ReferenceFacet', Label: '{i18n>Details}', Target: '@UI.FieldGroup#Details'},
+ ],
+ FieldGroup#Details: {
+ Data: [
+ {Value: code},
+ {Value: name},
+ {Value: descr}
+ ]
+ },
+ }
+);
+
+////////////////////////////////////////////////////////////////////////////
+//
+// Currencies List
+//
+annotate common.Currencies with @(
+ Common.SemanticKey: [code],
+ Identification: [{Value:code}],
+ UI: {
+ SelectionFields: [ name, descr ],
+ LineItem:[
+ {Value: descr},
+ {Value: symbol},
+ {Value: code},
+ ],
+ }
+);
+
+////////////////////////////////////////////////////////////////////////////
+//
+// Currency Details
+//
+annotate common.Currencies with @(
+ UI: {
+ HeaderInfo: {
+ TypeName: '{i18n>Currency}',
+ TypeNamePlural: '{i18n>Currencies}',
+ Title: {Value: descr},
+ Description: {Value: code}
+ },
+ Facets: [
+ {$Type: 'UI.ReferenceFacet', Label: '{i18n>Details}', Target: '@UI.FieldGroup#Details'},
+ {$Type: 'UI.ReferenceFacet', Label: '{i18n>Extended}', Target: '@UI.FieldGroup#Extended'},
+ ],
+ FieldGroup#Details: {
+ Data: [
+ {Value: name},
+ {Value: symbol},
+ {Value: code},
+ {Value: descr}
+ ]
+ },
+ FieldGroup#Extended: {
+ Data: [
+ {Value: numcode},
+ {Value: minor},
+ {Value: exponent}
+ ]
+ },
+ }
+);
+
+////////////////////////////////////////////////////////////////////////////
+//
+// Currencies Elements
+//
+annotate common.Currencies with {
+ numcode @title:'{i18n>NumCode}';
+ minor @title:'{i18n>MinorUnit}';
+ exponent @title:'{i18n>Exponent}';
+}
diff --git a/suppliers/app/services.cds b/suppliers/app/services.cds
new file mode 100644
index 00000000..595023e9
--- /dev/null
+++ b/suppliers/app/services.cds
@@ -0,0 +1,12 @@
+/*
+ This model controls what gets served to Fiori frontends...
+*/
+
+using from './admin/fiori-service';
+using from './browse/fiori-service';
+using from './common';
+
+using from '@capire/common';
+
+// only works in case of embedded orders service
+using from '@capire/orders/app/orders/fiori-service';
diff --git a/suppliers/srv/mashup.cds b/suppliers/srv/mashup.cds
index 3d2e9799..a6e28b0e 100644
--- a/suppliers/srv/mashup.cds
+++ b/suppliers/srv/mashup.cds
@@ -8,6 +8,7 @@ using { API_BUSINESS_PARTNER as S4 } from './external/API_BUSINESS_PARTNER.csn';
@cds.autoexpose // or expose explicitly in Catalog and AdminService
@cds.persistence: {table,skip:false} // add persistency
+@readonly
entity sap.capire.bookshop.Suppliers as projection on S4.A_BusinessPartner {
// TODO: Aliases not supported in Java, yet?
key BusinessPartner as ID,
diff --git a/suppliers/srv/mashup.js b/suppliers/srv/mashup.js
index 0c903d40..981634ac 100644
--- a/suppliers/srv/mashup.js
+++ b/suppliers/srv/mashup.js
@@ -31,8 +31,10 @@ module.exports = async()=>{ // called by server.js
if (!replicated) await replicate (supplierId, 'initial');
};
- if (supplierId) return Promise.all ([ next(), replicateIfNotExists() ])
- else return next() //> don't forget to pass down the interceptor stack
+ if (supplierId)
+ return (await Promise.all ([ next(), replicateIfNotExists() ]))[0]
+ else
+ return next() //> don't forget to pass down the interceptor stack
})
})