SAP HANA CLOUD

[SAP CAP] 간단한 북스토어 만들기

선짱 2026. 1. 28. 14:14
반응형

1. cookbook에서 기초를 다지는게 좋다. 

https://cap.cloud.sap/docs/get-started/in-a-nutshell

북스토어를 만들어보자.

 

 

Bookshop by capire 클릭 후 따라 내려가보자

 

 

db/schema.cds

using { Currency, managed, sap } from '@sap/cds/common';
namespace sap.capire.bookshop; 

entity Books : managed { 
  key ID : Integer;
  title  : localized String(111);
  descr  : localized String(1111);
  author : Association to Authors;
  genre  : Association to Genres;
  stock  : Integer;
  price  : Decimal(9,2);
  currency : Currency;
}

entity Authors : managed { 
  key ID : Integer;
  name   : String(111);
  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;
}

 

 

srv/admin-service.cds

using { sap.capire.bookshop as my } from '../db/schema';

service AdminService @(requires:'authenticated-user') { 

  entity Books as projection on my.Books;
  entity Authors as projection on my.Authors;

    // 주문 기능도 여기 추가
  action submitOrder(book: Integer, quantity: Integer);

}

 

 

srv/cat-service.cds

using { sap.capire.bookshop as my } from '../db/schema';
service CatalogService @(path:'/browse') { 

  @readonly entity Books as select from my.Books {*,
    author.name as author
  } excluding { createdBy, modifiedBy };

  @requires: 'authenticated-user'
  action submitOrder (book: Books:ID, quantity: Integer);
}

 

만들고 터미널에서 cds watch 하면 'http://localhost:4004' 터미널이 나온다.

들어가서 확인해보자

 

 

이런 화면을 볼 수있다.

 

이제 데이터를 넣어보자.

 

db/data/sap.capire.bookshop-Books.csv

ID,title,author_ID,stock
201,Wuthering Heights,101,12
207,Jane Eyre,107,11
251,The Raven,150,333
252,Eleonora,150,555
271,Catweazle,170,22

 

 


db/data/sap.capire.bookshop-Authors.csv

ID,name
101,Emily Brontë
107,Charlotte Brontë
150,Edgar Allen Poe
170,Richard Carpenter

 

 

경로에 데이터값을 넣어주면된다.

위원님 말로는 서버 끄면 없어진다고함.

 

 

이렇게 지정해줘도 되지만 터미널에 cds add data 라는 명령어를 써주면 저절로 임시 데이터가 들어가짐

cds add data --records 10 이라고 적어주면 자동으로 10줄의 데이터가 들어감.

 

만약 실제 DB에 넣고 싶다면  package.json에 설정 추가하면됨.

json   {
     "cds": {
       "requires": {
         "db": {
           "kind": "sqlite",
           "credentials": { "url": "db.sqlite" }
         }
       }
     }
   }

 

cds deploy 실행 .
프로젝트 루트에 db.sqlite 파일 생성
스키마를 실제 DB에 배포
CSV 데이터를 DB에 로드

 

 

서비스에 커스텀 로직을 추가해보자

이벤트 핸들러 추가해주면 기본 CRUD + 커스텀 비즈니스 로직 실행이 된다.

 

srv/cat-service.js

const cds = require('@sap/cds')  //CAP 프레임워크 가져오기

class CatalogService extends cds.ApplicationService { init() { //서비스 정의
  const { Books } = cds.entities('CatalogService') //book의 엔티티 가져오기

  this.after ('each', Books, book => {  //이벤트 핸들러 등록
    if (book.stock > 111) {   //재고가 111개 넘어가면
      book.title += ` -- 11% discount!`   //할인 띄워줘라
    } 
  }) 

  return super.init()
}}
module.exports = CatalogService   //클래스 내보내기

 

재고가 111개가 넘을시 할인 문구를 띄워준다.

 

여기서 재고가 주문량보다 많거나 같을때 재고를 수량만큼 빼는 로직을 넣어주겠다.

코드를 추가해보자.

const cds = require('@sap/cds')  //CAP 프레임워크 가져오기

class CatalogService extends cds.ApplicationService { async init() { //비동기 작업때문에 async 적어줘야함.

  const db = await cds.connect.to('db') 
  const { Books } = cds.entities('CatalogService') //book의 엔티티 가져오기

  this.on ('submitOrder', async req => {  //this.on은 submitOrder 액션 나오면 바로 실행해
    const {book,quantity} = req.data  //req.data = 사용자가 보낸 데이터
    const n = await UPDATE (Books, book)   //DB 업데이트. Books 테이블에서 ID가 book인 책을 업데이트
      .with ({ stock: {'-=': quantity }}) //재고가 주문량보다 많거나 같을 때만 재고를 수량만큼 빼기
      .where ({ stock: {'>=': quantity }})
      //n > 0 = 업데이트 성공 (1행 이상 변경). n = 0 = 업데이트 실패 → 에러 발생. 409 = HTTP 상태 코드 (Conflict - 재고 부족)
    n > 0 || req.error (409,`${quantity} exceeds stock for book #${book}`) 
  })

  this.after ('each', Books, book => {  //이벤트 핸들러 등록
    if (book.stock > 111) {   //재고가 111개 넘어가면
      book.title += ` -- 11% discount!`   //할인 띄워줘라
    } 
  }) 

  return super.init()
}}
module.exports = CatalogService   //클래스 내보내기

 

반응형