First push

This commit is contained in:
nkaputnik
2022-07-26 09:47:56 +02:00
parent 9617e576f0
commit 9c2a7598f2
16 changed files with 414 additions and 10438 deletions

View File

@@ -0,0 +1,2 @@
using from '..\..\schema';

View File

@@ -1,43 +1,49 @@
using { Currency, managed, sap, extensible } from '@sap/cds/common';
using {
Currency,
managed,
sap,
extensible
} from '@sap/cds/common';
namespace sap.capire.bookshop;
@Extensibility.Any.Enabled : true
entity Books : managed, extensible {
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';
authorName: String;
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';
authorName : String;
}
@Extensibility : {
Fields.Enabled : true,
Relations.Enabled : false,
Annotations.Enabled : true,
Logic.Enabled : true,
Logic.constraints: true,
Logic.calculations: true,
Logic.Handler : [create, update, delete, read]
}
entity Authors : managed, extensible {
key ID : Integer;
name : String(111);
dateOfBirth : Date;
dateOfDeath : Date;
placeOfBirth : String;
placeOfDeath : String;
virtual age: Integer;
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 */
entity Genres : sap.common.CodeList {
key ID : Integer;
parent : Association to Genres;
children : Composition of many Genres on children.parent = $self;
extend Authors with {
virtual age : Integer;
}
/**
* 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;
}

View File

@@ -1,13 +1,16 @@
async function run() {
//debugger
//while (true) {}
//process.exit()
//1.substring()
let res = await cds.read(SELECT.one`title`.from(`Books`).where(`ID=201`))
// let res = await specialselect
let res = await SELECT.one`title`.from(`Books`).where(`ID=201`)
let { title } = res
const data = req.data
data.modifiedBy = "Custom Event handler read changed this!"
data.placeOfDeath = " --- Somewhere over " + title + " --- create in Sandbox"
return data
let Author = req.data
Author.modifiedBy = "Custom Event handler changed this!"
Author.placeOfDeath = " --- Somewhere over " + title + " --- create in Sandbox"
//await this.emit("createdAuthor", { Author })
return Author
}
output = run()
run()

View File

@@ -1,5 +1,28 @@
function getYear(v) {
return parseInt(v.substr(0, 4))
}
function getMonth(v) {
return parseInt(v.substr(5, 2))
}
function getDay(v) {
return parseInt(v.substr(8, 2))
}
function getAge(from, to) {
if (from === undefined || from == null) return 0
if (to === undefined || to == null) to = new Date().toISOString()
let year = getYear(to) - getYear(from) - 1
if (
getMonth(to) > getMonth(from) ||
(getMonth(to) === getMonth(from) && getDay(to) >= getDay(from))
) {
year++
}
return year
}
const result_ = Array.isArray(result) ? result : [result]
for (const row of result_) {
row.modifiedBy += " --- read in sandbox"
row.age = 27
row.age = getAge(row.dateOfBirth, row.dateOfDeath)
}

View File

@@ -0,0 +1,9 @@
async function run() {
const {author, newName} = req.data
let a = await SELECT `name`.from(`Authors`).where({ID: author})
if(!a) return req.error (404, `Can't rename a non-existing author`)
await UPDATE (`Authors`,author).with ({ name: newName })
//await this.emit ('renamedAuthor', { author, newName })
output.msg = 'Success'
}
run()

View File

@@ -0,0 +1,5 @@
async function run() {
let {Author} = req.data
Author.placeOfBirth += ' --- modified in custom event'
}
run()

76
bookshop/notebook.md Normal file
View File

@@ -0,0 +1,76 @@
```swift
using { Currency, managed, sap } from '@sap/cds/common';
namespace sap.capire.bookshop;
/*
Annotations available:
Entity level
@expression.constraint : [{if: 'expression evaluates to bool'}, on: ['INSERT, UPDATE, DELETE'], error: 'Transaction Rollback and error message', warning: 'Transaction proceeds and warning message']
@expression.computed : [{expression: 'ability to access request payload and modify it', on: ['INSERT, UPDATE']}]
@event : [{if: 'expression evaluates to bool', on: ['INSERT, UPDATE, DELETE, READ'], when: 'before or after, default before', emit: 'Event Name', to: 'Messaging target, optional'}]
@expresion.code :[{file: 'file name', on:['insert', 'update'], when: 'before or after, default before'},
{source: 'each => { if (each.stock > 111) {each.title += ` -- 11% discount!`; each.price= each.price*0.9}', on:['insert', 'update'], when: 'before or after'}]
Atribute Level
@assert.constraint : {if: 'stock>=0 OR stock <1000', error: 'i18n/error102'};
@event : {if: 'expression evaluates to bool', on: ['INSERT, UPDATE, DELETE, READ'], when: 'before or after', emit: 'Event Name', to: 'Messaging target, optional' }
Functions available:
EXISTS(association target)
COUNT,AVG,MIN,MAX,SUM: Composition items, arrays etc
OLD: before image
EACH: loop over composition items
Events covered:
CRUD --> Longhand and Shorthand supported?
Upsert as one event?
Before and after:
Before can change change request payload and stop transaction
After should trigger only asynchronous messages
Specific Events for status changes? I think expression based event emitter suffices
*/
//Entity level annotations
@expression.constraint : [{if: 'stock>100 AND price>15)', on: ['INSERT', 'UPDATE'], error: 'No Book over price 15 should have more than 100 stock' }, // error, rollback transactions
{if: 'stock>90 AND price>15)', on: ['I', 'U'], warning: 'No Book over price 15 should have more than 100 stock' }] //warning, proceed with transaction but report warning back to UI
@expression.computed : {expression: 'if(stock>100) then price=price*0.9', on: ['INSERT']} //ability to modify the payload of the request, but nothing beyond it
@expresion.code :[{file: 'sap.capire.bookshop-Books-beforeInsert', on:['insert', 'update'], when: 'before'}, //naming can be arbitrary?
{source: 'each => { if (each.stock > 111) {each.title += ` -- 11% discount!`; each.price= each.price*0.9}', on:['insert', 'update'], when: 'before'}] //alternative
@event : { if:'price>200', emit: 'Expensive Book', to: 'RulesEngine'}
entity Books : managed {
key ID : Integer;
title : localized String(111); @event : {if: 'old.title="Hello"', emit: 'Hello changed' } //old refers to before Image. No "to" clause means message is emitted to any subscriber interested
descr : localized String(1111);
author : Association to Authors @assert.constraint: 'exists(author)'; //function calls need to evaluate to bool
genre : Association to Genres;
stock : Integer @assert.constraint : {if: 'stock>=0 OR stock <1000', error: 'Stock not within permitted parameters'}; //when operand is used, no auto-insert
price : Decimal(9,2) @assert.constraint : '>0'; //insert operand on left side by default
currency : Currency;
image : LargeBinary @Core.MediaType : 'image/png';
stockWorth: Decimal(9,2) @expression.computed : 'stock*price'; //persisted on write. Overhead in runtime, but performance benefit on read. Payload ignored?
// stockWorth2 = stock*price; -- long term goal from compiler team, not persisted on write, but calculated on read
stockWorth3 : Decimal @expression.computed: 'if (stock*price>1000) then stockWorth3=stock.price else stockworth3=1000'; //which altenative?
stockWorth4 : Decimal @expression.computed: {if: '(stock*price>1000)', then: 'stockWorth3=stock.price', else: 'stockworth3=1000'};
}
//@assert.expression: 'dateOfBirth<dateOfDeath'
entity Authors : managed {
key ID : Integer;
name : String(111);
dateOfBirth : Date ;
dateOfDeath : Date @expression.constraint: '>dateOfBirth';
placeOfBirth : String;
placeOfDeath : String;
books : Association to many Books on books.author = $self;
}
/** 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;
}
```

Binary file not shown.

View File

@@ -2,10 +2,27 @@ using {sap.capire.bookshop as my} from '../db/schema';
service AdminService // @(requires : 'admin')
{
entity Books as projection on my.Books;
entity Authors as projection on my.Authors;
action renameAuthor(author : Authors:ID, newName : String);
entity Books as projection on my.Books actions {
action increaseStock(count : Integer);
function stock() returns Integer;
};
@Extensibility : {
Fields.Enabled : true,
Fields.Quota: 100,
Relations.Enabled : false,
Annotations.Enabled : true,
Logic.Enabled : true,
Logic.constraints: true,
Logic.calculations: true,
Logic.Handler : [create, update, delete, read]
}
entity Authors as projection on my.Authors;
action renameAuthor(author : Authors:ID, newName : String) returns {
msg : String
};
function getStock(book: Books:ID) returns Integer;
event newBook : {
book : Books:ID;
name : Books:title

View File

@@ -39,7 +39,7 @@ annotate AdminService.Authors with @(UI : {
// Workaround to avoid errors for unknown db-specific calculated fields above
extend sap.capire.bookshop.Authors with {
virtual age : Integer;
//virtual age : Integer;
virtual lifetime : String;
}

View File

@@ -50,6 +50,10 @@
}
},
"sap.ui5": {
"flexEnabled": true,
"config": {
"experimentalCAPScenario": true
},
"dependencies": {
"minUI5Version": "1.81.0",
"libs": {

View File

@@ -22,6 +22,10 @@
}
},
"sap.ui5": {
"flexEnabled": true,
"config": {
"experimentalCAPScenario": true
},
"dependencies": {
"libs": {
"sap.fe.templates": {}

View File

@@ -53,6 +53,10 @@
}
},
"sap.ui5": {
"flexEnabled": true,
"config": {
"experimentalCAPScenario": true
},
"dependencies": {
"minUI5Version": "1.81.0",
"libs": {

View File

@@ -10,7 +10,21 @@
<script>
window["sap-ushell-config"] = {
defaultRenderer: "fiori2",
applications: {}
applications: {},
bootstrapPlugins: {
RuntimeAuthoringPlugin: {
component: "sap.ushell.plugins.rta",
config: {
validateAppVersion: false,
},
},
PersonalizePlugin: {
component: "sap.ushell.plugins.rta-personalize",
config: {
validateAppVersion: false,
},
},
}
};
</script>
@@ -22,7 +36,11 @@
data-sap-ui-frameOptions="allow"
></script>
<script>
sap.ui.getCore().attachInit(()=> sap.ushell.Container.createRenderer().placeAt("content"))
sap.ui.getCore().attachInit(()=> sap.ushell.Container.createRenderer().placeAt("content"));
sap.ui
.getCore()
.getConfiguration()
.setFlexibilityServices([{ connector: "SessionStorageConnector" }]);
</script>
</head>

View File

@@ -36,7 +36,10 @@
}
},
"db": {
"kind": "sql"
"kind": "sqlite",
"credentials": {
"database": "sqlite.db"
}
},
"db-ext": {
"[development]": {
@@ -51,4 +54,4 @@
}
}
}
}
}

10582
package-lock.json generated

File diff suppressed because it is too large Load Diff