Compare commits
10 Commits
cds.deploy
...
temporal
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b629f8faf3 | ||
|
|
5f160c0927 | ||
|
|
0c4658a3ef | ||
|
|
9479aa4cad | ||
|
|
33cd70065a | ||
|
|
450577d5a7 | ||
|
|
5a23ba0f76 | ||
|
|
064ce32b8a | ||
|
|
2c064d0200 | ||
|
|
51ee6d167c |
37
.vscode/launch.json
vendored
37
.vscode/launch.json
vendored
@@ -4,28 +4,31 @@
|
|||||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
|
||||||
"name": "Attach by Process ID",
|
|
||||||
"processId": "${command:PickProcess}",
|
|
||||||
"request": "attach",
|
|
||||||
"skipFiles": [
|
|
||||||
"<node_internals>/**"
|
|
||||||
],
|
|
||||||
"type": "pwa-node"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "bookshop",
|
"name": "bookshop",
|
||||||
"command": "cds watch bookshop",
|
"command": "npx cds watch bookshop",
|
||||||
"request": "launch",
|
|
||||||
"type": "node-terminal",
|
"type": "node-terminal",
|
||||||
"skipFiles": ["<node_internals>/**"]
|
"request": "launch",
|
||||||
|
"skipFiles": [
|
||||||
|
"<node_internals>/**",
|
||||||
|
"**/node_modules/**",
|
||||||
|
"**/cds/lib/lazy.js",
|
||||||
|
"**/cds/lib/req/cls.js",
|
||||||
|
"**/odata-v4/okra/**"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Fiori app",
|
"name": "Fiori App",
|
||||||
"command": "cds watch fiori",
|
"command": "npx cds watch fiori",
|
||||||
"request": "launch",
|
|
||||||
"type": "node-terminal",
|
"type": "node-terminal",
|
||||||
"skipFiles": ["<node_internals>/**"]
|
"request": "launch",
|
||||||
|
"skipFiles": [
|
||||||
|
"<node_internals>/**",
|
||||||
|
"**/node_modules/**",
|
||||||
|
"**/cds/lib/lazy.js",
|
||||||
|
"**/cds/lib/req/cls.js",
|
||||||
|
"**/odata-v4/okra/**"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"inputs": [
|
"inputs": [
|
||||||
@@ -33,7 +36,7 @@
|
|||||||
"type": "pickString",
|
"type": "pickString",
|
||||||
"id": "sample",
|
"id": "sample",
|
||||||
"description": "Which sample do you want to start?",
|
"description": "Which sample do you want to start?",
|
||||||
"options": ["bookshop", "fiori", "reviews", "reviews/test/bookshop"],
|
"options": [ "bookshop", "fiori", "reviews", "reviews" ],
|
||||||
"default": "bookshop"
|
"default": "bookshop"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
11
.vscode/settings.json
vendored
11
.vscode/settings.json
vendored
@@ -4,5 +4,14 @@
|
|||||||
"**/.gitignore": true,
|
"**/.gitignore": true,
|
||||||
"**/.vscode": true,
|
"**/.vscode": true,
|
||||||
"LICENSES/**": true
|
"LICENSES/**": true
|
||||||
}
|
},
|
||||||
|
"debug.javascript.terminalOptions": {
|
||||||
|
"skipFiles": [
|
||||||
|
"<node_internals>/**",
|
||||||
|
"**/node_modules/**",
|
||||||
|
"**/cds/lib/lazy.js",
|
||||||
|
"**/cds/lib/req/cls.js",
|
||||||
|
"**/odata-v4/okra/**"
|
||||||
|
]
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,4 +83,4 @@ In case you've a question, find a bug, or otherwise need support, use our [commu
|
|||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Copyright (c) 2021 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the Apache Software License, version 2.0 except as noted otherwise in the [LICENSE](LICENSES/Apache-2.0.txt) file.
|
Copyright (c) 2021 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the Apache Software License, version 2.0 except as noted otherwise in the [LICENSE](LICENSE.txt) file.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using { Currency, managed, sap } from '@sap/cds/common';
|
using { Currency, managed, temporal, sap } from '@sap/cds/common';
|
||||||
namespace sap.capire.bookshop;
|
namespace sap.capire.bookshop;
|
||||||
|
|
||||||
entity Books : managed {
|
entity Books : managed {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"description": "A simple self-contained bookshop service.",
|
"description": "A simple self-contained bookshop service.",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@capire/common": "*",
|
"@capire/common": "*",
|
||||||
"@sap/cds": ">=4",
|
"@sap/cds": "^5.0.4",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"passport": "0.4.1"
|
"passport": "0.4.1"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,27 @@
|
|||||||
using { sap.capire.bookshop as my } from '../db/schema';
|
using { sap.capire.bookshop as my } from '../db/schema';
|
||||||
service AdminService @(requires:'admin') {
|
service AdminService @(requires:'admin') {
|
||||||
entity Books as projection on my.Books;
|
|
||||||
|
entity Books as SELECT from my.Books { *,
|
||||||
|
// key ID, key validFrom
|
||||||
|
};
|
||||||
entity Authors as projection on my.Authors;
|
entity Authors as projection on my.Authors;
|
||||||
|
|
||||||
|
// @cds.redirection.target:false
|
||||||
|
// entity Books.history @(cds.temporal:false) as projection on Books {
|
||||||
|
// *,
|
||||||
|
// key ID,
|
||||||
|
// key validFrom @(cds.valid.from:false),
|
||||||
|
// validTo @(cds.valid.to:false),
|
||||||
|
// };
|
||||||
|
}
|
||||||
|
|
||||||
|
// entity NonTemporalBook as projection on my.Books {
|
||||||
|
// *,
|
||||||
|
// key ID,
|
||||||
|
// key validFrom @(cds.valid.from:false),
|
||||||
|
// validTo @(cds.valid.to:false),
|
||||||
|
// };
|
||||||
|
|
||||||
|
extend my.Books with {
|
||||||
|
history : Composition of many my.Books on history.ID = $self.ID;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ class CatalogService extends cds.ApplicationService { init(){
|
|||||||
|
|
||||||
// Reduce stock of ordered books if available stock suffices
|
// Reduce stock of ordered books if available stock suffices
|
||||||
this.on ('submitOrder', async req => {
|
this.on ('submitOrder', async req => {
|
||||||
const {book,amount} = req.data, tx = cds.tx(req)
|
const {book,amount} = req.data
|
||||||
let {stock} = await tx.read('stock').from(Books,book)
|
let {stock} = await SELECT `stock` .from (Books,book)
|
||||||
if (stock >= amount) {
|
if (stock >= amount) {
|
||||||
await tx.update (Books,book).with ({ stock: stock -= amount })
|
await UPDATE (Books,book) .with (`stock -=`, amount)
|
||||||
await this.emit ('OrderedBook', { book, amount, buyer:req.user.id })
|
await this.emit ('OrderedBook', { book, amount, buyer:req.user.id })
|
||||||
return { stock }
|
return { stock }
|
||||||
}
|
}
|
||||||
@@ -16,10 +16,8 @@ class CatalogService extends cds.ApplicationService { init(){
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Add some discount for overstocked books
|
// Add some discount for overstocked books
|
||||||
this.after ('READ','Books', each => {
|
this.after ('READ','ListOfBooks', each => {
|
||||||
if (each.stock > 111) {
|
if (each.stock > 111) each.title += ` -- 11% discount!`
|
||||||
each.title += ` -- 11% discount!`
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return super.init()
|
return super.init()
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ entity Orders_Items {
|
|||||||
up_ : Association to Orders;
|
up_ : Association to Orders;
|
||||||
product : Association to Products @assert.integrity:false; // REVISIT: this is a temporary workaround for a glitch in cds-runtime
|
product : Association to Products @assert.integrity:false; // REVISIT: this is a temporary workaround for a glitch in cds-runtime
|
||||||
amount : Integer;
|
amount : Integer;
|
||||||
title : String;
|
title : String; //> intentionally replicated as snapshot from product.title
|
||||||
price : Double;
|
price : Double;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
"sqlite3": "^5.0.0"
|
"sqlite3": "^5.0.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"cleanup": "rm -rf node_modules && rm -rf */node_modules && rm -rf */*/node_modules",
|
||||||
"registry": "node .registry/server.js",
|
"registry": "node .registry/server.js",
|
||||||
"bookshop": "cds watch bookshop",
|
"bookshop": "cds watch bookshop",
|
||||||
"fiori": "cds watch fiori",
|
"fiori": "cds watch fiori",
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
## Run all-in-one
|
## Run all-in-one
|
||||||
|
|
||||||
Open a terminal window and run the bookshop in it:
|
Open a terminal window and run the `fiori` app in it:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
npm run bookshop
|
npm run fiori
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@@ -17,8 +17,8 @@ Open two terminal windows. In the first one start the reviews service stand-alon
|
|||||||
npm run reviews-service
|
npm run reviews-service
|
||||||
```
|
```
|
||||||
|
|
||||||
In the second one start the bookshop:
|
In the second one start the `fiori` app:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
npm run bookshop
|
npm run fiori
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
const {expect} = require('../test')
|
const {expect} = require('../test')
|
||||||
const cds = require('@sap/cds/lib')
|
const cds = require('@sap/cds/lib')
|
||||||
|
|
||||||
// monkey patching older releases:
|
|
||||||
if (!cds.compile.cdl) cds.compile.cdl = cds.parse
|
|
||||||
const { parse:cdr } = cds.ql
|
const { parse:cdr } = cds.ql
|
||||||
|
|
||||||
const model = cds.compile.cdl (`
|
// should become cds.compile(...) when cds5 is released
|
||||||
|
const model = cds.compile.to.csn (`
|
||||||
entity Categories {
|
entity Categories {
|
||||||
key ID : Integer;
|
key ID : Integer;
|
||||||
name : String;
|
name : String;
|
||||||
|
|||||||
@@ -1,6 +1,2 @@
|
|||||||
|
const cds = require('@sap/cds')
|
||||||
const test = require('@sap/cds/lib/utils/tests').in(__dirname,'..')
|
module.exports = cds.test.in(__dirname,'..')
|
||||||
module.exports = Object.assign(test,{run:test})
|
|
||||||
|
|
||||||
// REVISIT: With upcoming release of @sap/cds this should become:
|
|
||||||
// module.exports = require('@sap/cds/tests').in(__dirname,'..')
|
|
||||||
|
|||||||
@@ -20,11 +20,11 @@ describe('Messaging', ()=>{
|
|||||||
|
|
||||||
let N=0, received=[], M=0
|
let N=0, received=[], M=0
|
||||||
it ('should add messaging event handlers', ()=>{
|
it ('should add messaging event handlers', ()=>{
|
||||||
srv.on('reviewed', (msg,next)=> { received.push(msg); return next() })
|
srv.on('reviewed', (msg)=> received.push(msg))
|
||||||
})
|
})
|
||||||
|
|
||||||
it ('should add more messaging event handlers', ()=>{
|
it ('should add more messaging event handlers', ()=>{
|
||||||
srv.on('reviewed', (_,next)=> { ++M; return next() })
|
srv.on('reviewed', ()=> ++M)
|
||||||
})
|
})
|
||||||
|
|
||||||
it ('should add review', async ()=>{
|
it ('should add review', async ()=>{
|
||||||
|
|||||||
Reference in New Issue
Block a user