# 고급

**주로 외부 서버에서 데이터를 조회하여 같이 표현해주고 싶을 때 사용됩니다. 사용자가 작성한 Apex Class를 이용해 데이터소스를 가져오기 때문에 내부 데이터소스에 비해 자유롭게 데이터를 가져올 수 있는 장점이 있습니다.**

<figure><img src="/files/OE34qi4D0hlZeENfi65H" alt=""><figcaption></figcaption></figure>

예를 들어 외부 서버에서 실시간 재고를 가져와 화면에 같이 표시하고 싶은 경우 Apex Class에서 Rest API 코드를 작성하여 외부 데이터소스에 지정하면 Line-Item Configurator에서 해당 데이터를 보실 수 있습니다.

* [**속성**](#undefined)

  External 데이터소스를 사용하기 위한 각 속성입니다.
* [**Apex Class 작성**](#apex-class)

  External 데이터소스를 사용하기 전 Apex Class를 먼저 작성해야 합니다. Package에서 제공하는 `SBLD.DataSourceService.Fetchable` 인터페이스를 작성하려는 Apex Class에 `implements` 하여 구현합니다.
* [**예시**](#undefined-1)

  준비중입니다.

***

### 속성

External 데이터소스를 사용하기 위한 각 속성입니다.

<table><thead><tr><th width="261">항목</th><th width="388">설명</th><th>필수</th></tr></thead><tbody><tr><td>Apex Class Name</td><td>외부데이터를 가져올 때 사용하는 클래스의 이름입니다.</td><td><mark style="color:red;">✔️</mark></td></tr><tr><td>Key Field</td><td>DataSource를 통해 가져온 데이터를 매핑시키기 위한 field API 이름을 나타냅니다.</td><td><mark style="color:red;">✔️</mark></td></tr><tr><td>Parent Field Parameters</td><td>DataSource의 Type이 External일 경우 Parent Object의 Field 중 Parameter로 넘겨줄 Field를 나타냅니다.</td><td></td></tr><tr><td>Lookup Field Parameters</td><td>DataSource의 Type이 External일 경우 Lookup Object의 Field 중 Parameter로 넘겨줄 Field를 나타냅니다.</td><td></td></tr><tr><td>Active</td><td>DataSource의 활성, 비활성 여부입니다.</td><td><mark style="color:red;">✔️</mark></td></tr></tbody></table>

### Apex Class 작성

External 데이터소스를 사용하기 전 Apex Class를 먼저 작성해야 합니다. Package에서 제공하는 `SBLD.DataSourceService.Fetchable` 인터페이스를 작성하려는 Apex Class에 `implements` 하여 구현합니다.

`SBLD.DataSourceService.Fetchable` 클래스를 `implements` 하여 `execute()` 메서드를 구현합니다.

{% code title="DataSourceServiceMock.cls" lineNumbers="true" %}

```apex
global with sharing class DataSourceServiceMock implements SBLD.DataSourceService.Fetchable {
    /***
     * @description SBLD.DataSourceService.Fetchable execute() 정의
     * @param param SBLD.DataSourceService.Parameter형 파라미터
     *              DataSource에서 설정한 
     * @return Map<Object, SObject>
     ****/
    global SBLD.DataSourceService.Result execute(SBLD.DataSourceService.Parameter param) {
        SBLD.DataSourceService.Result result = new SBLD.DataSourceService.Result();
        /**
         *  @method DataSourceService.Parameter gets()
         *  @param  String 형 Parent, Lookup 중 선택 (대소문자 구분 없음)
         *  @return List<SObject>
         **/
        SObject parentRecord = null;
        List<SObject> lookupRecords = new List<SObject>();
        // Parent 관련 파라미터를 가져옵니다.
        if(param.gets('parent')<>null && !param.gets('parent').isEmpty()) {
            parentRecord = param.gets('parent')[0];
        }
        // Lookup 관련 파라미터를 가져옵니다.
        if(param.gets('lookup')<>null && !param.gets('lookup').isEmpty()) {
            listLookupParameters = param.gets('lookup');
        }
        /**
         * 성공 시, External 결과값을 설정합니다.
         **/
        for(SObject sobj : lookupRecords) {
            /**
             * Internal의 Action과 동일하게 DataSource의 값을 
             * Lookup 또는 Line-Item 필드에 매핑하는 작업을 
             **/
            SBLD.DataSourceServiceAction action = new SBLD.DataSourceServiceAction();
            // 1. External에 설정한 External Key 값
            action.setKeyValue(sobj.get('Id')); // Product Code
            // 2. External에서 가져온 값을 Lookup 또는 Junction 필드에 매핑합니다.
            Map<String, Object> mapPopulatedField = sobj.getPopulatedFieldsAsMap();
            for(String fieldName : mapPopulatedField.keySet()) {
                action.putSourceToTargetField(mapPopulatedField.get(fieldName), fieldName);
            }
            // 3. DataSourceService.Result에 Action을 추가합니다.
            result.addAction(action);
        }
        return result;
    }
}
```

{% endcode %}

`SBLD.DataSourceService.Parameter`에서 `gets()` 메서드를 통해 Line-Item Configurator의 Parent 또는 Lookup 정보를 가져올 수 있습니다.

{% code lineNumbers="true" %}

```apex
global SBLD.DataSourceService.Result execute(SBLD.DataSourceService.Parameter param) {
    SObject parentRecord = null;
    List<SObject> lookupRecords = new List<SObject>();
    // Parent 관련 파라미터를 가져옵니다.
    if(param.gets('parent')<>null && !param.gets('parent').isEmpty()) {
        parentRecord = param.gets('parent')[0];
    }
    // Lookup 관련 파라미터를 가져옵니다.
    if(param.gets('lookup')<>null && !param.gets('lookup').isEmpty()) {
        listLookupParameters = param.gets('lookup');
    }
    ...
}
```

{% endcode %}

Line-Item Configurator로 결과값을 전달하기 위해 아래 클래스를 이용합니다.

### **SBLD.DataSourceServiceAction Class**

대상(Lookup 또는 Line-Item)의 행마다 Action을 지정합니다. Action은 데이터소스 값을 Lookup 또는 Line-Item 필드에 매핑하는 작업입니다.

* **setKeyValue(Object keyValue)**\
  Lookup 또는 Line-Item의 대상 레코드를 찾기 위한 Key값을 설정합니다.
* **putSourceToTargetField(Object sourceValue, String targetField)**\
  데이터소스 값을 Lookup 또는 Line-Item 필드에 할당합니다.

### **SBLD.DataSourceService.Result Class**

매핑이 완료된 Action을 리턴 값에 추가하는 작업입니다.

* **addAction(SBLD.DataSourceServiceAction action)**\
  SBLD.DataSourceService.Result 인스턴스에 Action을 추가합니다.

{% code lineNumbers="true" %}

```apex
...
SBLD.DataSourceService.Result result = new SBLD.DataSourceService.Result();
for(Object objResponse : listResponses) {
    Map<String, Object> mapResponse = (Map<String, Object>)objResponse;

    SBLD.DataSourceServiceAction action = new SBLD.DataSourceServiceAction();
    // 데이터소스에서 설정한 Key 필드에 알맞는 값
    action.setKeyValue(mapResponse.get('Id')); // Product Code
    // 데이터소스에서 가져온 값을 Lookup 또는 Line-Item 필드에 넣기
    action.putSourceToTargetField(mapResponse.get('inventory'), 'Inventory__c');
    // SBLD.DataSourceService.Result에 Action을 추가한다.
    result.addAction(action);
}
return result;
```

{% endcode %}

### 예시

준비중입니다.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://help.smallbuilder.com/ko/smallbuilder-line-items/builder/setup/datasource/external.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
