diff --git a/.eslintrc b/.eslintrc index 052d4616..343e8260 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,6 +1,7 @@ { "extends": "eslint:recommended", "env": { + "browser": true, "node": true, "es6": true, "jest": true diff --git a/bookshop/test/ext.cds b/bookshop/app/index.cds similarity index 100% rename from bookshop/test/ext.cds rename to bookshop/app/index.cds index c695c857..468378a7 100644 --- a/bookshop/test/ext.cds +++ b/bookshop/app/index.cds @@ -1,3 +1,3 @@ // Incorporate pre-build extensions from... -// using from '@capire/common'; using from '../../common'; //> work-around for mediocre cds-tests +// using from '@capire/common'; diff --git a/bookshop/app/vue/app.js b/bookshop/app/vue/app.js index f63dd464..7e8fb4b2 100644 --- a/bookshop/app/vue/app.js +++ b/bookshop/app/vue/app.js @@ -1,5 +1,7 @@ /* global Vue axios */ //> from vue.html +const $ = sel => document.querySelector(sel) const GET = (url) => axios.get('/browse'+url) +const POST = (cmd,data) => axios.post('/browse'+cmd,data) const books = new Vue ({ @@ -7,7 +9,8 @@ const books = new Vue ({ data: { list: [], - info: '( click on a row to see details... )', + book: { descr:'( click on a row to see details... )' }, + order: { amount:1, succeeded:'', failed:'' } }, methods: { @@ -15,16 +18,26 @@ const books = new Vue ({ search: ({target:{value:v}}) => books.fetch (v && '$search='+v), async fetch (_filter='') { - const columns = 'ID,title,author,price', details = 'genre,currency' + const columns = 'ID,title,author,price,stock', details = 'genre,currency' const {data} = await GET(`/Books?$select=${columns}&$expand=${details}&${_filter}`) books.list = data.value }, - async inspect ({currentTarget:{id}}) { - const {data} = await GET(`/Books/${id}/descr/$value`) - books.info = data + async inspect () { + const book = books.book = books.list [event.currentTarget.rowIndex-1] + book.descr || await GET(`/Books/${book.ID}/descr/$value`) .then (({data}) => book.descr = data) + books.order = { amount:1 } + setTimeout (()=> $('form > input').focus(), 111) }, + submitOrder () { event.preventDefault() + const {book,order} = books, amount = parseInt (order.amount) || 1 + POST(`/submitOrder`, { amount, book: book.ID }) + .then (()=> books.order = { amount, succeeded: `Successfully orderd ${amount} item(s).` }) + .catch (e=> books.order = { amount, failed: e.response.data.error.message }) + GET(`/Books/${book.ID}/stock/$value`).then (res => book.stock = res.data) + } + } }) diff --git a/bookshop/app/vue/index.html b/bookshop/app/vue/index.html index 6e21ffa1..cfae7d80 100644 --- a/bookshop/app/vue/index.html +++ b/bookshop/app/vue/index.html @@ -6,13 +6,22 @@ - +
+

Capire Books

+ + @@ -27,7 +36,22 @@
Book {{ book.currency.symbol }} {{ book.price }}
-

{{ info }}

+ +
+ +
+ + +
+
+ +

{{ book.title }}

+

{{ book.descr }}

+
diff --git a/bookshop/srv/cat-service.cds b/bookshop/srv/cat-service.cds index 28986214..b596cbea 100644 --- a/bookshop/srv/cat-service.cds +++ b/bookshop/srv/cat-service.cds @@ -6,5 +6,5 @@ service CatalogService @(path:'/browse') { } excluding { createdBy, modifiedBy }; @requires_: 'authenticated-user' - action order (book : Books.ID, amount: Integer); + action submitOrder (book : Books.ID, amount: Integer); } diff --git a/bookshop/srv/cat-service.js b/bookshop/srv/cat-service.js index 25819333..99332859 100644 --- a/bookshop/srv/cat-service.js +++ b/bookshop/srv/cat-service.js @@ -1,23 +1,20 @@ const cds = require('@sap/cds') +module.exports = async function (){ -/** Service implementation for CatalogService */ -module.exports = cds.service.impl (function() { - - // Get entity definitions from reflected model - const { Books } = cds.entities - - // Add some discount for overstocked books - this.after ('READ', 'Books', each => { - if (each.stock > 111) each.title += ` -- 11% discount!` - }) + const db = await cds.connect.to('db') // connect to database service + const { Books } = db.entities // get reflected definitions // Reduce stock of ordered books if available stock suffices - this.on ('order', async (req) => { - const {UPDATE} = cds.ql(req), {book,amount} = req.data + this.on ('submitOrder', async req => { + const {book,amount} = req.data const n = await UPDATE (Books, book) - .where ('stock >=', amount) - .set ('stock -=', amount) + .with ({ stock: {'-=': amount }}) + .where ({ stock: {'>=': amount }}) n > 0 || req.error (409,`${amount} exceeds stock for book #${book}`) }) -}) + // Add some discount for overstocked books + this.after ('READ','Books', each => { + if (each.stock > 111) each.title += ` -- 11% discount!` + }) +} diff --git a/bookshop/test/requests.http b/bookshop/test/requests.http index 14416fbd..e8790f54 100644 --- a/bookshop/test/requests.http +++ b/bookshop/test/requests.http @@ -22,7 +22,7 @@ GET http://localhost:4004/admin/Authors? ### -POST http://localhost:4004/browse/order +POST http://localhost:4004/browse/submitOrder # Run that three times to get out-of-stock message Content-Type: application/json