본문으로 건너뛰기

7. Asset 서비스

client.asset() 으로 접근합니다. PlantPulse 자산 모델의 핵심 — Site > Area > Line > Equipment 의 계층 트리를 관리합니다.

ID 규칙: ASSET_ 접두사 필수. 타입 코드 A/L/M이 트리 계층을 결정합니다. 자세한 내용은 도메인 ID 규칙 참고.

7.1 메서드 일람

메서드반환 타입HTTP엔드포인트
create(AssetRequestV5)AssetResponseV5 또는 nullPOST/api/v5/asset
update(asset_id, AssetRequestV5)AssetResponseV5 또는 nullPUT/api/v5/asset/{id}
delete(asset_id)booleanDELETE/api/v5/asset/{id}
get(asset_id)AssetResponseV5 또는 nullGET/api/v5/asset/{id}
list()List<AssetResponseV5>GET/api/v5/asset
exists(asset_id)booleanGET/api/v5/asset/{id}/exists

Asset 서비스는 단순화된 CRUD에 집중되어 있습니다. 트리 계층 조회는 Path 서비스 또는 클라이언트 측 필터링(list()asset_type 필터)을 사용하시면 됩니다.

7.2 Asset Type 값

asset_type의미
AArea (구역)
LLine (라인)
MEquipment (설비, Machine)

7.3 AssetRequestV5 / AssetResponseV5

필드타입설명
asset_idString자산 ID (PK, ASSET_ 필수)
asset_nameString표시명
parent_asset_idString부모 자산 ID
asset_orderString형제 간 정렬 순서
asset_typeStringA/L/M
table_typeString설비 분류 (CNC, INJECTION 등)
site_idString소속 사이트
descriptionString설명
insert_date / update_dateString(응답 전용) 시각

7.4 사용 예시

Area → Line → Equipment 트리 생성

import plantpulse.api.v5.dto.request.AssetRequestV5;

// 1) Area
AssetRequestV5 area = new AssetRequestV5();
area.setSite_id("SITE_DJ");
area.setParent_asset_id("SITE_DJ");
area.setAsset_id("ASSET_DJ_A_0001");
area.setAsset_name("조립구역");
area.setAsset_type("A");
client.asset().create(area);

// 2) Line
AssetRequestV5 line = new AssetRequestV5();
line.setSite_id("SITE_DJ");
line.setParent_asset_id("ASSET_DJ_A_0001");
line.setAsset_id("ASSET_DJ_L_0001");
line.setAsset_name("1번 조립 라인");
line.setAsset_type("L");
client.asset().create(line);

// 3) Equipment (CNC 머신)
AssetRequestV5 cnc = new AssetRequestV5();
cnc.setSite_id("SITE_DJ");
cnc.setParent_asset_id("ASSET_DJ_L_0001");
cnc.setAsset_id("ASSET_DJ_M_0001");
cnc.setAsset_name("CNC #1");
cnc.setAsset_type("M");
cnc.setTable_type("CNC");
cnc.setDescription("DMG MORI NLX-2500");
client.asset().create(cnc);

단건 조회

import plantpulse.api.v5.dto.response.AssetResponseV5;

AssetResponseV5 cnc = client.asset().get("ASSET_DJ_M_0001");
if (cnc != null) {
System.out.println(cnc.getAsset_name() + " (" + cnc.getAsset_type() + ")");
System.out.println("부모: " + cnc.getParent_asset_id());
}

전체 목록 + 타입별 필터링

V5는 listByType 메서드가 없으므로 클라이언트 측에서 필터링합니다.

import java.util.List;
import java.util.stream.Collectors;

List<AssetResponseV5> all = client.asset().list();

// Equipment만
List<AssetResponseV5> equipments = all.stream()
.filter(a -> "M".equals(a.getAsset_type()))
.collect(Collectors.toList());

// 대전공장의 Line만
List<AssetResponseV5> djLines = all.stream()
.filter(a -> "SITE_DJ".equals(a.getSite_id()))
.filter(a -> "L".equals(a.getAsset_type()))
.collect(Collectors.toList());

트리 재구성 (클라이언트 측)

import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;

// asset_id 인덱스
Map<String, AssetResponseV5> byId = new HashMap<>();
for (AssetResponseV5 a : client.asset().list()) {
byId.put(a.getAsset_id(), a);
}

// 부모-자식 매핑
Map<String, List<AssetResponseV5>> children = new HashMap<>();
for (AssetResponseV5 a : byId.values()) {
children
.computeIfAbsent(a.getParent_asset_id(), k -> new ArrayList<>())
.add(a);
}

// 사이트(SITE_DJ) 산하 트리 출력
printTree(children, "SITE_DJ", 0);

static void printTree(Map<String, List<AssetResponseV5>> children, String id, int depth) {
List<AssetResponseV5> kids = children.getOrDefault(id, List.of());
for (AssetResponseV5 c : kids) {
System.out.println(" ".repeat(depth) + c.getAsset_id() + " — " + c.getAsset_name());
printTree(children, c.getAsset_id(), depth + 1);
}
}

자산 수정

AssetRequestV5 update = new AssetRequestV5();
update.setSite_id("SITE_DJ");
update.setParent_asset_id("ASSET_DJ_L_0001");
update.setAsset_id("ASSET_DJ_M_0001");
update.setAsset_name("CNC #1 (보수 후)");
update.setAsset_type("M");
update.setTable_type("CNC");
update.setDescription("2026-05-10 베어링 교체 완료");

client.asset().update("ASSET_DJ_M_0001", update);

자산 삭제

⚠️ 자산 삭제 전에 그 자산에 연결된 모든 Tag·하위 Asset을 먼저 삭제해야 합니다.

boolean ok = client.asset().delete("ASSET_DJ_M_OLD");

7.5 활용 시나리오

시나리오 — 사이트의 Equipment 목록과 각 Tag 수

String siteId = "SITE_DJ";

List<AssetResponseV5> equipments = client.asset().list().stream()
.filter(a -> siteId.equals(a.getSite_id()))
.filter(a -> "M".equals(a.getAsset_type()))
.collect(Collectors.toList());

for (AssetResponseV5 eq : equipments) {
long tagCount = client.tag().countByAsset(eq.getAsset_id());
System.out.printf("%s — Tag %d개%n", eq.getAsset_name(), tagCount);
}

시나리오 — Line 단위 OEE 대시보드 데이터 수집

// 1) Line 목록
List<AssetResponseV5> lines = client.asset().list().stream()
.filter(a -> "L".equals(a.getAsset_type()))
.filter(a -> "SITE_DJ".equals(a.getSite_id()))
.collect(Collectors.toList());

// 2) 각 Line 산하 Equipment 조회 → 자산 경로 → 작업지시 → KPI 집계
for (AssetResponseV5 line : lines) {
List<AssetResponseV5> machines = client.asset().list().stream()
.filter(a -> line.getAsset_id().equals(a.getParent_asset_id()))
.collect(Collectors.toList());

for (AssetResponseV5 m : machines) {
long now = System.currentTimeMillis();
// 현재 작업지시는 Order 서비스로 조회
// ...
}
}

다음 단계