Skip to content

lij15/my-cds-common

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SAP CAP — @sap/cds/common, CodeList & Enum Types

This example covers how to use the built-in types from @sap/cds/common, how to define custom CodeLists, and how to use enum types in CDS.


Key Concepts

CodeList type enum
Storage Separate database table No table — type constraint only
Values can change at runtime ✅ via CSV or API ❌ requires code change
Supports name / descr ✅ built-in ❌ value only
Typical use case Countries, currencies, genres, status Fixed constants: direction, priority
Frontend dropdown source GET /Genres Hardcoded in frontend

Rule of thumb: if business users need to maintain the options, use CodeList. If the values are fixed at development time and never change, use enum.


Project Structure

my-codelist/
├── db/
│   ├── schema.cds
│   └── data/
│       ├── my.codelist-Genres.csv
│       ├── my.codelist-BookStatus.csv
│       ├── my.codelist-Books.csv
│       ├── sap.common-Currencies.csv
│       ├── sap.common-Countries.csv
│       └── sap.common-Languages.csv
├── srv/
│   ├── cat-service.cds
│   └── cat-service.js
└── package.json

Data Model

db/schema.cds

namespace my.codelist;

using {
  cuid, managed,
  sap.common.CodeList,
  sap.common.Countries,
  sap.common.Currencies,
  sap.common.Languages
} from '@sap/cds/common';


// Custom CodeList: inherits code (key) + name + descr from CodeList aspect
entity Genres : CodeList {
  key code : String(20);
}

entity BookStatus : CodeList {
  key code : String(10);
}


// Main entity: uses standard types and custom CodeLists
entity Books : cuid, managed {
  title    : String(200);
  price    : Decimal(9, 2);
  stock    : Integer default 0;

  // Associations to standard reference entities
  // CAP auto-generates foreign keys: currency_code, country_code, language_code
  currency : Association to Currencies;
  country  : Association to Countries;
  language : Association to Languages;

  // Associations to custom CodeLists
  genre    : Association to Genres;
  status   : Association to BookStatus;
}


// Enum type: no database table, values are fixed at development time
type Priority : String enum {
  Low    = 'LOW';
  Medium = 'MEDIUM';
  High   = 'HIGH';
}

type Rating : Integer enum {
  OneStar   = 1;
  TwoStar   = 2;
  ThreeStar = 3;
  FourStar  = 4;
  FiveStar  = 5;
}

// Entity using enum types
entity Reviews : cuid {
  book     : Association to Books;
  comment  : String(1000);
  priority : Priority default 'MEDIUM';
  rating   : Rating;
}

Seed Data

db/data/my.codelist-Genres.csv

code,name,descr
PROG,Programming,Books about software development
ARCH,Architecture,Software architecture and design patterns
MGMT,Management,Project and team management
SCI,Science,Natural sciences and mathematics

db/data/my.codelist-BookStatus.csv

code,name,descr
AVAIL,Available,In stock and ready to ship
OOS,Out of Stock,Temporarily unavailable
DISC,Discontinued,No longer available

db/data/my.codelist-Books.csv

ID,title,price,stock,currency_code,country_code,language_code,genre_code,status_code
b1000001-0000-0000-0000-000000000001,Clean Code,38.00,10,USD,US,en,PROG,AVAIL
b1000001-0000-0000-0000-000000000002,The Pragmatic Programmer,45.00,5,USD,US,en,PROG,AVAIL
b1000001-0000-0000-0000-000000000003,Domain-Driven Design,50.00,0,USD,US,en,ARCH,OOS

Note: Use the auto-generated FK column names in CSV (currency_code, not currency).

db/data/sap.common-Currencies.csv

code,name,descr,symbol,minorUnit
USD,US Dollar,United States Dollar,$,2
EUR,Euro,European Euro,€,2
JPY,Japanese Yen,Japanese Yen,¥,0
GBP,British Pound,British Pound Sterling,£,2
CNY,Chinese Yuan,Chinese Renminbi,¥,2
KRW,Korean Won,Korean Won,₩,0

db/data/sap.common-Countries.csv

code,name,descr
US,United States,United States of America
DE,Germany,Federal Republic of Germany
JP,Japan,Japan
GB,United Kingdom,United Kingdom of Great Britain
CN,China,People's Republic of China
KR,Korea,Republic of Korea
FR,France,French Republic

db/data/sap.common-Languages.csv

code,name,descr
en,English,English
de,German,Deutsch
ja,Japanese,日本語
zh,Chinese,中文
ko,Korean,한국어
fr,French,Français

sap.common entities (Currencies, Countries, Languages) are not pre-loaded by CAP automatically. You must provide CSV files named sap.common-{EntityName}.csv in db/data/.


Service Definition

srv/cat-service.cds

using my.codelist as db from '../db/schema';

service CatalogService {

  entity Books      as projection on db.Books;
  entity Reviews    as projection on db.Reviews;

  // Custom CodeLists — expose for frontend dropdowns
  entity Genres     as projection on db.Genres;
  entity BookStatus as projection on db.BookStatus;

  // Standard reference entities are auto-exposed by CAP
  // because Books has Associations to Currencies/Countries/Languages
  // No need to declare them here — they appear automatically
}

Do NOT manually re-declare Currencies, Countries, or Languages in the service. CAP auto-exposes them via the Associations on Books. Declaring them again causes a name collision error.


Service Implementation

srv/cat-service.js

const cds = require('@sap/cds')

module.exports = class CatalogService extends cds.ApplicationService {
  async init() {
    const { Books, Reviews } = this.entities

    // Validate enum values on Review creation
    this.before('CREATE', Reviews, req => {
      const { rating, priority } = req.data
      console.log('rating:', rating, 'priority:', priority)

      const validRatings = [1, 2, 3, 4, 5]
      if (rating != null && !validRatings.includes(rating)) {
        return req.error(400, `rating must be 1-5, received: ${rating}`)
      }

      const validPriorities = ['LOW', 'MEDIUM', 'HIGH']
      if (priority && !validPriorities.includes(priority)) {
        return req.error(400, `priority must be LOW/MEDIUM/HIGH, received: ${priority}`)
      }
    })

    // Log FK codes after READ (expand is needed to get full objects)
    this.after('READ', Books, books => {
      if (!books) return
      const list = Array.isArray(books) ? books : [books]
      for (const book of list) {
        console.log(`"${book.title}" — currency: ${book.currency_code}, genre: ${book.genre_code}`)
      }
    })

    return super.init()
  }
}

Running the Project

cds watch

On startup, confirm CSV files are loaded:

> init from db/data/sap.common-Currencies.csv
> init from db/data/sap.common-Countries.csv
> init from db/data/sap.common-Languages.csv
> init from db/data/my.codelist-Genres.csv
> init from db/data/my.codelist-Books.csv

HTTP Request Examples

Read standard reference data

GET /odata/v4/catalog/Currencies
GET /odata/v4/catalog/Countries
GET /odata/v4/catalog/Currencies/USD

Read books with all associations expanded

GET /odata/v4/catalog/Books?$expand=genre,currency,country,language

Response includes full nested objects for each association:

{
  "ID": "b1000001-...",
  "title": "Clean Code",
  "currency": { "code": "USD", "name": "US Dollar", "symbol": "$" },
  "country":  { "code": "US",  "name": "United States" },
  "genre":    { "code": "PROG","name": "Programming" }
}

Create a review — valid enum values

POST /odata/v4/catalog/Reviews
Content-Type: application/json

{
  "book_ID": "b1000001-0000-0000-0000-000000000001",
  "comment": "Excellent book!",
  "rating": 5,
  "priority": "HIGH"
}

Create a review — trigger enum validation error

POST /odata/v4/catalog/Reviews
Content-Type: application/json

{
  "book_ID": "b1000001-0000-0000-0000-000000000001",
  "comment": "Test",
  "rating": 10,
  "priority": "URGENT"
}
# → 400 rating must be 1-5

Gotchas

sap.common data is NOT pre-loaded — CSV files are required

// ❌ Wrong assumption: CAP loads Currencies/Countries/Languages automatically
// ✅ You must provide:
db/data/sap.common-Currencies.csv
db/data/sap.common-Countries.csv
db/data/sap.common-Languages.csv

Do not manually re-expose auto-exposed entities

// ❌ Causes name collision error
@readonly entity Currencies as projection on db.Currencies;

// ✅ CAP auto-exposes them via Associations — just leave them out

Use FK column names in CSV, not the association field name

// ❌ Wrong
currency,country,language

// ✅ Correct — FK columns auto-generated by CAP
currency_code,country_code,language_code

book.currency is undefined without $expand

// currency is only populated when client sends $expand=currency
// The FK code is always available without expand:
console.log(book.currency_code)  // "USD" — always present
console.log(book.currency)       // undefined unless $expand=currency

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors