본문 바로가기

안녕하세요!

SAP/CAP

[ CAP ] objcect 페이지의 default 값 대입해 UI 비동기 갱신하기


 

schema.cds


 

entity Contacts


 

 

entity Contacts : cuid {
    name                        : String;
    phone                       : String;
    building                    : String;
    country                     : Country;
    street                      : String;
    city                        : String;
    postCode                    : String;
    addressLabel                : String;
    photoUrl                    : String;
}

 

schema.cdsaspect rootBasis에 여러 속성을 설정해두면 다른 entity에서 재사용할 수 있게 된다.

contact의 경우에는 entity Contacts와 일대일 연결을 시켜주어
Contacts가 가지는 uuid에 연결된 유니크한 속성값들이 조인된다.

여기서 특이한 점 중 하나는 addressLabel은 데이터 값이 특정되어 나타나는 것이 아니라,
여러 데이터 값들의 조합되어 나타내기 위한 용도로 사용된다.

이는 service.js로 다시 돌아가서 살펴보자.

 

 

async() 비동기 함수에서 사용할 매개변수를 response로 선언한다.

hasOwnProperty() 메서드는 괄호 안에 들어가는 객체의 속성 값 소유 여부를 판단한다.
즉, contact라는 프로퍼티가 있는 지에 대해 확인하고 이에 대해 true 혹은 false를 반환하는 것이다.

hasOwnProperty()는 사실상 없어도 되는 속성이긴 하나, 가독성을 위해 사용하기도 한다.
반면에 이 메서드는 속성 값 자체에 대해 확인하는 것이 아니라, 이 값이 있는지 정도만 판단하기 때문에
undefined나 null 값도 true로 반환하기에 정확한 값을 도출하는 데에 어려움이 있을 수 있다.

다시 돌아와 contact라는 객체의 속성을 지니면서도 contact 속성 중 addressLabel의 값이 null일 때를 가정하여,
변수 contact에는 service.cds에서 사용키로 하였던 entity Contacts에서 contact의 ID를 킷값으로 둔다(?)
contact에 포함시킬 속성 값들은 bulilding, postCode, city, country의 name 등이다.

 

이제 addressLabel의 값을 초기화 해야 하므로,
response.contact.addressLabel에 템플릿 리터럴의 백틱(`)안에 변수 값을 표현하기 위해서
달러($), 중괄호({}) 안에 아까 포함시켜 두었던 contact의 속성 값들을 나열한다.

데이터 값을 갱신시켜 주기 위해서 UPDATE() 메서드를 사용해
entity Contacts와연결돼 있는 contact의 ID를 매개로 하여 addressLabel에 주솟값을 저장한다.

 

RootEntites.csv


 

 

참고로 RootEntities에 관한 데이터 테이블은 위와 같다.

반응형

service.js


 

resetEntities


 

 

srv.on("resetEntities", async req => { 
        //Delete current data
        await cleanUpDatabaseEntities();
        //Create new entities
        const countRootEntities = 4;
        const childEntity2IDs = await createChildEntities2(countRootEntities);
        const rootEntities = [];
        const imageUrls = ['sap-icon://lab','/media/crate.png','/media/bigBen.png','sap-icon://cart']
        const contacts = await SELECT.from(Contacts).columns('ID');
        const unitOfMeasures = await SELECT.from(UnitOfMeasureCodeList).columns('code');
        const currencies = await SELECT.from(Currencies).columns('code');
        const criticaityCodes = await SELECT.from(Criticality).columns('code');
        const countries = await SELECT.from(Countries).columns('code');

 

rootEntities를 빈 배열함수로 선언해주어, 추후에 반복문에서 default로 변경될 변수들의 데이터 값을 정의할 것이다.

imageUrls에는 각 Root Entities가 가지는 이미지 네 개를 sap에서 제공해주는 아이콘 이미지 url로 삽입해 준다.

unitOfMeasures는 common.cds에 정의해 두었던 entity UnitOfMeasureCodeList에서
킷값인 column(열) code를 기준으로 두고 선택한 값을 비동기로 인스턴스화 한다.

currencies에서도 마찬가지로 code 열을 기준의 데이터 값으로 초기화 해준다.

criticalityCodescountries도 위와 같이 초기화 되도록 한다.

 

for 반복문


 

 

이제 for 반복문을 돌려 각기 다른 default 데이터 값을 가지는 Root Entity들을 생성할 것이다.

우선 contatc_ID의 값을 정할 때,
i가 0에서 counRootEntities, 즉 4 미만까지 for 반복문을 돌면서
i의 값이 contacts.length보다 작을때에는 contacts[0], 즉 데이터 테이블에서 첫 번째 행에 있는 값을 가리키게 되고,
만약 이외의 경우라면 contacts[i]에 해당되는 i 값을 대입하여 그에 맞는 속성 값들을 호출하게 된다.

imageUrl, uom_code, isoCurrency_code, criticality_code, country_code 모두 위와 같이
for문을 돌려 데이터 테이블에 입력돼 있는 고정된 속성 값을 가지게 된다.

 

 

    //Reseting all entities to there default state
    srv.on("resetEntities", async req => { 
        //Delete current data
        await cleanUpDatabaseEntities();
        //Create new entities
        const countRootEntities = 4;
        const childEntity2IDs = await createChildEntities2(countRootEntities);
        const rootEntities = [];
        const imageUrls = ['sap-icon://lab','/media/crate.png','/media/bigBen.png','sap-icon://cart']
        const contacts = await SELECT.from(Contacts).columns('ID');
        const unitOfMeasures = await SELECT.from(UnitOfMeasureCodeList).columns('code');
        const currencies = await SELECT.from(Currencies).columns('code');
        const criticaityCodes = await SELECT.from(Criticality).columns('code');
        const countries = await SELECT.from(Countries).columns('code');
        for(let i = 0; i < countRootEntities; i++) {
            const date = new Date();
            let date2 = new Date(date.toISOString());
            date2.setMonth(date2.getMonth()+3);
            let uuid = cds.utils.uuid();
            rootEntities.push({
                ID: uuid,
                contact_ID: (i >= contacts.length) ? contacts[0].ID : contacts[i].ID,
                childEntity2_ID: childEntity2IDs[i],
                imageUrl: (i >= imageUrls.length) ? imageUrls[0] : imageUrls[i],
                uom_code: (i >= unitOfMeasures.length) ? unitOfMeasures[0].code : unitOfMeasures[i].code,
                isoCurrency_code: (i >= currencies.length) ? currencies[0].code : currencies[i].code,
                criticality_code: (i >= criticaityCodes.length) ? criticaityCodes[0].code : criticaityCodes[i].code,
                country_code: (i >= countries.length) ? countries[0].code : countries[i].code,
                //Calculating values, just to have values for the UI. The generation has no special logic behind it.
                stringProperty: (i===0) ? `Root entity ${i+1} and delete not possible` : (i===1) ? `Root entity ${i+1} and update not possible` : `Root entity ${i+1}`,
                deletePossible: (i===0) ? false : true,
                updateHidden: (i===1) ? true : false,
                dimensions: ((i+1)*2===6) ? i*2 : (i+1)*2, //manipulate values, that two entities have one dimension for demonstrating aggregation on ALP floorplan
                validFrom: date.toISOString().substring(0,11),
                validTo: date2.toISOString().substring(0,11),
                time: `${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`,
                timeStamp: date.toISOString(),
                fieldWithUoM: i*49+49,
                fieldWithPrice: i*100,
                fieldWithCriticality: determineFieldWithCriticalityValue((i === criticaityCodes.length) ? criticaityCodes[0] : criticaityCodes[i]),
                integerValue: 20+2*i,
                forecastValue: 20+2*i+(10*i),
                targetValue: 20+2*i+(10*(i+2)),
                starsValue: (Math.random()*40)/10, //Value has to be between 0 and 4
                //Fixed properties
                email: 'test.test@sap.com',
                telephone: '+49-6227-12383-2',
                fieldWithURL: 'https://www.sap.com;',
                fieldWithURLtext: 'SAP',
                description: 'Lorem ipsum dolor sit amet, \n consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.',
                //Compositions to many:
                childEntities1: await createChildEntities1(3,uuid),
                childEntities3: await createChildEntities3(2,uuid),
                chartEntities: await createChartEntities(10,uuid),
            });
        }
        await cds.tx(req).run(INSERT.into(RootEntities).entries(rootEntities));
        return req.notify(`All entitiy data has been reseted!`);
    });

 

stringProperty의 경우 삼항연산자를 사용하고 있다.

해석해 보자면, i가 0일 때에는 Root entity 1 and delete not possible을,
i가 1일 때에는 Root entity 2 and update not possible을
그 외의 i의 값이 대입되었을 때는 Root entity 3 등으로 표현하게 된다.

dimensions는 콘텐츠가 논리적으로 연결된 분류 그룹(특성)을 하나의 용어로 그룹화 한다.
즉, 하나의 같은 차원에서 서로 다른 Root Entity의 값들의 집합을 한눈에 볼 수 있도록 한다. 
i의 값이 2일 때는 dimensions가 4의 값을 가지게 되고,
i의 값이 그 외의 값일 때에는 dimensions는 (i+1)*2의 값을 갖게 된다.

 

toISOString()는 Date를 ISOString(yyyy-mm-ddThh:mm:ss) 형식의 문자열로 변환해주는 함수이다. 

여기서 substring(0, 11)은 y부터 T까지의 값만 출력함을 알려준다.

createChildEntities1


 


 

 

    async function createChildEntities1(amount, parent_ID) {
        let childEntities1 = [];
        for(let i = 0; i < amount; i++) {
            let grandChildEntities = [];
            for(let i = 1; i <= amount; i++) {
                grandChildEntities.push({
                    field: `grandchild ${i}`
                });
            }

 

childEntities 배열함수를 함수 내에 선언한다.

for 반복문 안에 childEntities1에 생성할 더 깊은 루트의 grandChildEntities 배열함수를 선언한다.
이차원 for 반복문을 만들어 배열함수 grandChildEntities에 필드를 생성하되,
백틱(`)을 사용해 i 값의 변화에 따 grandchild 1, grandchild 2, grandchild 3 형태의 값으로 출력되도록 한다.

 


 

 

            childEntities1.push({
                ID: cds.utils.uuid(),
                parent_ID: parent_ID,
                //Calculating values, just to have values for the UI. The generation has no special logic behind it.
                fieldWithPerCent: (Math.random()+0.1)*100,
                booleanProperty: (Math.random() > 0.5) ? true : false,
                criticalityValue_code: (i%2===0) ? 1 : (i%3===0) ? 2 : (i%5===0) ? 3 : 0,
                field: `child entity ${i}`,
                grandChildren: grandChildEntities,
            });
        }
        return childEntities1;
    }

 

fieldWithPerCent 값은 0~1 사이의 수를 생성하는 Math.random() 메서드를 사용해 백분율을 출력한다.

booleanProperty의 경우, 위와 마찬가지로 Math.random() 메서드를 사용하면서,
이항연산자를 활용해 boolen 값을 출력한다.

criticalityCalue_code는 i가 2의 배수인 경우에는 code 1 Negative를,
i가 3인 경우에 code 2 Critical을, i가 5일 경우 code 3 Positive를 보여주게 된다.
그 외에 충돌되거나, 없는 비굣값일 경우에는 code 0 Neutral을 출력한다.

 

 

[ CAP ] CDS UI로 여러 가지 Chart 만들기

schema.cds entity ChartDataEntities entity ChartDataEntities : cuid { parent : Association to one RootEntities; criticality : Association to one Criticality; integerValue : Integer; integerValueWithUoM : Integer; uom : UnitOfMeasure; forecastValue : Intege

pythonchoboman.tistory.com

Next Stage : [ CAP ] CDS UI로 여러 가지 Chart 만들기

 

728x90
반응형

loading