Listings Kopecz/SAP Cloud Application Model, Teil 2

Listing 1: Das Domänenmodell in der Datei db/schema.cds
using { Currency, Country } from '@sap/cds/common';
namespace ix.cap;

entity Products {
    key ID       : Integer;
      name      : localized String(100) not null;
      price       : Decimal(9,2);
      retail       : Decimal(9,2);
      virtual margin : Decimal(9,2);  // a calculated field
      currency : Currency;
      supplier  : Association to Suppliers;
}

entity Suppliers {
    key ID       : Integer;
      name      : String(100);
      country   : Country;
      rating      : Integer @assert.range: [ 1, 4 ];
      products : Association to many Products 
                         on products.supplier = $self;
}

-----

Listing 2: Das Servicemodell in der Datei srv/services.cds
// Import domain model
using ix.cap as domain from '../db/schema';

// Expose all operations on Products and Suppliers
service CatalogService {
    entity Products as projection on domain.Products;
    entity Suppliers as projection on domain.Suppliers;
}

// Expose restricted, non-updatable views
@path: '/cat/de'
service BrowseCatalogDE {
    entity Products as select * from domain.Products 
      where supplier.country.code = 'DE';
    entity Suppliers as select * from domain.Suppliers
      where country.code = 'DE'; 
}

-----

Listing 3: Terminalausgabe als Reaktion auf das Kommando cds watch (Ausgabe gekürzt)
iX$ cds watch
cds serve all --with-mocks --in-memory?
[cds] - model loaded from 3 file(s):
    db\schema.cds
    srv\services.cds
    node_modules\@sap\cds\common.cds
[cds] - connect to db > sqlite { database: ':memory:' }
    > filling ix.cap.Products from db\data\ix.cap-Products.csv
    > filling ix.cap.Products_texts from db\data\ix.cap-Products_texts.csv
    > filling ix.cap.Suppliers from db\data\ix.cap-Suppliers.csv
    > filling sap.common.Countries from db\data\sap.common-Countries.csv
    > filling sap.common.Countries_texts from db\data\sap.common-Countries_texts.csv
    > filling sap.common.Currencies from db\data\sap.common-Currencies.csv
    > filling sap.common.Currencies_texts from db\data\sap.common-Currencies_texts.csv
/> successfully deployed to sqlite in-memory db
[cds] - serving CatalogService { at: '/cat/de' }
[cds] - serving CatalogService { at: '/catalog' }
[cds] - launched in: 1.098s
[cds] - server listening on { url: 'http://localhost:4004' }
[ terminate with ^C ]

-----

Listing 4: Registrieren und Implementieren von Ereignissen mit JavaScript in der Datei srv/services.js
module.exports = (srv)=>{

    // Extract the 'Products' service entity
    const { Products } = srv.entities;

    /* Compute margin after reading from the
      database through GET requests */
    srv.after ('READ', Products, (each)=>{
      let num = each.retail - each.price;
      each.margin = num.toFixed(2);  // comply to Decimals(9,2)
    })

    /* Issue warning for negative margin before
      processing a POST/PUT/PATCH request */
    srv.before (['CREATE', 'UPDATE'], Products, (req)=>{
      let margin = req.data.retail - req.data.price;
      if (margin < 0) {
        req.warn("Negative margin for product " + req.data.ID);
      }
    })
  }

-----

Listing 5: HTTP Requests zum Anlegen und Ändern eines Produkts
### Create Product
POST http://localhost:4004/cat/de/Products 
Content-Type: application/json;IEEE754Compatible=true

{
    "ID": 701,
    "name": "New Flat Screen",
    "price": "189.51",
    "retail": "211.34",
    "currency_code": "EUR",
    "supplier_ID": 301
}

### Update Product
PATCH http://localhost:4004/cat/de/Products(701) 
Content-Type: application/json;IEEE754Compatible=true

{
    "price": "189.51",
    "retail": "111.34"
}

-----

Listing 6: Projektdeskriptor package.json konfigurieren
{
    "name": "ix-sample",
    "version": "1.0.0",
    "dependencies": {
      "@sap/cds": "^4",
      "express": "^4",
      "@sap/hana-client": "^2.6.61"
    },
    "devDependencies": {
      "sqlite3": "^5"
    },
    "scripts": {
      "start": "npx cds run"
    },
    "cds": {
      "hana": {
        "deploy-format": "hdbtable"
      },
      "requires": {
        "db": {"kind": "hana"}
      }
    }
}

