Compare commits

...
2 Commits
Author SHA1 Message Date
ChooSeongBin bcfdfe52a9 chgrCurrState 소스정리 2026-07-29 17:19:42 +09:00
ChooSeongBin 14f96f037c api token 소스정리 2026-07-29 15:32:46 +09:00
18 changed files with 736 additions and 93 deletions
Binary file not shown.
@@ -2,15 +2,14 @@ package net.jwsi.jcms.vpp.api;
import lombok.RequiredArgsConstructor;
import net.jwsi.jcms.vpp.chgr.ChgrResponseDto;
import net.jwsi.jcms.vpp.chgrCurrState.ChgrCurrState;
import net.jwsi.jcms.vpp.chgrHist.ChgrHistResponseDto;
import net.jwsi.jcms.vpp.provider.ProviderDto;
import net.jwsi.jcms.vpp.station.StationDto;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClient;
import org.springframework.web.util.UriComponentsBuilder;
import java.net.URI;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -19,64 +18,50 @@ import java.util.Map;
@RequiredArgsConstructor
public class ApiClient {
private final RestClient restClient;
private final RestClient externalApiClient;
public ApiResponse<List<StationDto>> fetchStations(String baseUrl, String token) {
URI uri = UriComponentsBuilder.fromUriString(baseUrl)
.path("/api/st/list")
.build()
.toUri();
return restClient.post()
.uri(uri)
.header("Authorization", "Bearer " + token)
public ApiResponse<List<StationDto>> fetchStations() {
return externalApiClient.post()
.uri("/api/st/list")
.body(Collections.emptyMap())
.retrieve()
.body(new ParameterizedTypeReference<ApiResponse<List<StationDto>>>() {});
}
public ApiResponse<List<ProviderDto>> fetchProviders(String baseUrl, String token) {
URI uri = UriComponentsBuilder.fromUriString(baseUrl)
.path("/api/provider/list")
.build()
.toUri();
return restClient.get()
.uri(uri)
.header("Authorization", "Bearer " + token)
public ApiResponse<List<ProviderDto>> fetchProviders() {
return externalApiClient.get()
.uri("/api/provider/list")
.retrieve()
.body(new ParameterizedTypeReference<ApiResponse<List<ProviderDto>>>() {});
}
public ApiResponse<List<ChgrResponseDto>> fetchChgr(String baseUrl, String token) {
URI uri = UriComponentsBuilder.fromUriString(baseUrl)
.path("/api/charger/list")
.build()
.toUri();
return restClient.post()
.uri(uri)
.header("Authorization", "Bearer " + token)
public ApiResponse<List<ChgrResponseDto>> fetchChgr() {
return externalApiClient.post()
.uri("/api/charger/list")
.body(Collections.emptyMap())
.retrieve()
.body(new ParameterizedTypeReference<ApiResponse<List<ChgrResponseDto>>>() {});
}
public ApiResponse<List<ChgrHistResponseDto>> fetchChgrHist(String baseUrl, String token) {
URI uri = UriComponentsBuilder.fromUriString(baseUrl)
.path("/api/charge/hist")
.build()
.toUri();
public ApiResponse<List<ChgrHistResponseDto>> fetchChgrHist(String startDt, String pageSize) {
Map<String, String> requestBody = Map.of(
"startDt", "2026-07-29",
"pageSize","50"
"startDt", startDt,
"pageSize", pageSize
);
return restClient.post()
.uri(uri)
.header("Authorization", "Bearer " + token)
return externalApiClient.post()
.uri("/api/charge/hist")
.body(requestBody)
.retrieve()
.body(new ParameterizedTypeReference<ApiResponse<List<ChgrHistResponseDto>>>() {});
}
public ApiResponse<List<ChgrCurrState>> fetchChgrCurrState() {
return externalApiClient.post()
.uri("/api/charge/stateInfo")
.body(Collections.emptyMap())
.retrieve()
.body(new ParameterizedTypeReference<ApiResponse<List<ChgrCurrState>>>() {});
}
}
@@ -0,0 +1,13 @@
package net.jwsi.jcms.vpp.api;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.util.List;
@NoArgsConstructor
@Getter
public class ApiToken {
private String jwt;
private List<String> roles;
}
@@ -0,0 +1,63 @@
package net.jwsi.jcms.vpp.api;
import net.jwsi.jcms.vpp.utils.JwtUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClient;
import org.springframework.web.util.UriComponentsBuilder;
import java.net.URI;
import java.time.LocalDateTime;
import java.util.Map;
@Service
public class ExternalApiService {
private final RestClient authRestClient = RestClient.create();
@Value("${jcms.api.base-url}")
private String baseUrl;
@Value("${jcms.api.user-id}")
private String
apiUserId;
@Value("${jcms.api.user-pwd}")
private String apiUserPwd;
private String cachedToken;
private LocalDateTime tokenExpiryTime;
public synchronized String getAccessToken() {
if (cachedToken != null && tokenExpiryTime != null && LocalDateTime.now().plusMinutes(1).isBefore(tokenExpiryTime)) {
return cachedToken;
}
URI uri = UriComponentsBuilder.fromUriString(baseUrl)
.path("/api/auth/token")
.build()
.toUri();
Map<String, String> requestBody = Map.of(
"userId", apiUserId,
"pwd", apiUserPwd
);
ApiResponse<ApiToken> response = authRestClient.post()
.uri(uri)
.body(requestBody)
.retrieve()
.body(new ParameterizedTypeReference<ApiResponse<ApiToken>>() {});
if (response != null && response.getData() != null) {
ApiToken tokenDto = response.getData();
this.cachedToken = tokenDto.getJwt();
this.tokenExpiryTime = JwtUtil.getExpirationTime(this.cachedToken);
return this.cachedToken;
}
throw new IllegalStateException("외부 API 토큰 발급에 실패했습니다.");
}
}
@@ -1,23 +1,25 @@
package net.jwsi.jcms.vpp.api;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestClient;
import java.time.Duration;
@Configuration
public class RestClientConfig {
@Bean
public RestClient restClient() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout((int) Duration.ofSeconds(5).toMillis());
factory.setReadTimeout((int) Duration.ofSeconds(30).toMillis());
@Value("${jcms.api.base-url}")
private String baseUrl;
@Bean
public RestClient externalApiClient(ExternalApiService externalApiService) {
return RestClient.builder()
.requestFactory(factory)
.baseUrl(baseUrl)
.requestInterceptor((request, body, execution) -> {
String token = externalApiService.getAccessToken();
request.getHeaders().set("Authorization", "Bearer " + token);
return execution.execute(request, body);
})
.build();
}
}
@@ -8,7 +8,6 @@ import net.jwsi.jcms.utils.HttpUtil;
import net.jwsi.jcms.utils.LoginUtil;
import net.jwsi.jcms.vpp.api.ApiClient;
import net.jwsi.jcms.vpp.api.ApiResponse;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.scheduling.annotation.Scheduled;
@@ -22,11 +21,6 @@ import java.util.stream.Collectors;
public class ChgrService extends BaseService<Chgr,String,ChgrRepository> {
private final ApiClient apiClient;
@Value("${jcms.api.base-url}")
private String baseUrl;
@Value("${jcms.api.token}")
private String apiToken;
public ChgrService(ChgrRepository repository, ApiClient apiClient) {
super(repository);
this.apiClient = apiClient;
@@ -34,7 +28,7 @@ public class ChgrService extends BaseService<Chgr,String,ChgrRepository> {
@Transactional
@Scheduled(cron = "0 0 0 * * *")
public void getCharger() {
ApiResponse<List<ChgrResponseDto>> response = apiClient.fetchChgr(baseUrl, apiToken);
ApiResponse<List<ChgrResponseDto>> response = apiClient.fetchChgr();
if (response == null || !Integer.valueOf(200).equals(response.getCode())) {
String msg = (response != null) ? response.getMessage() : "응답 없음";
@@ -0,0 +1,74 @@
package net.jwsi.jcms.vpp.chgrCurrState;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import net.jwsi.jcms.base.BaseStEntity;
@NoArgsConstructor
@Getter
@Setter
@ToString
@Entity(name = "vpp_chgr_curr_state")
@IdClass(ChgrCurrStateId.class)
public class ChgrCurrState extends BaseStEntity {
@Transient
private ChgrCurrStateId oldId__;
@Id
@Column(name = "provider_id")
private String providerId; // provider_id (PK)
@Id
@Column(name = "st_id")
private String stId; // st_id (PK)
@Id
@Column(name = "chgr_id")
private String chgrId; // chgr_id (PK)
@Column(name = "state_dt")
private String stateDt;
@Column(name = "op_mode")
private String opMode;
@Column(name = "ch1_rechg_state_cd")
private String ch1RechgStateCd;
@Column(name = "ch1_door_state_cd")
private String ch1DoorStateCd;
@Column(name = "ch1_plug_state_cd")
private String ch1PlugStateCd;
@Column(name = "ch2_rechg_state_cd")
private String ch2RechgStateCd;
@Column(name = "ch2_door_state_cd")
private String ch2DoorStateCd;
@Column(name = "ch2_plug_state_cd")
private String ch2PlugStateCd;
@Column(name = "ch3_rechg_state_cd")
private String ch3RechgStateCd;
@Column(name = "ch3_door_state_cd")
private String ch3DoorStateCd;
@Column(name = "ch3_plug_state_cd")
private String ch3PlugStateCd;
@Column(name = "integrated_kwh")
private Double integratedKwh;
@Column(name = "dc_power_wh")
private Double dcPowerWh;
@Column(name = "ac_power_wh")
private Double acPowerWh;
}
@@ -0,0 +1,63 @@
package net.jwsi.jcms.vpp.chgrCurrState;
import net.jwsi.jcms.base.BaseController;
import net.jwsi.jcms.exception.JsonDataException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
import java.util.Map;
@Controller
@RequestMapping("/cms/chgrCurrState")
public class ChgrCurrStateController extends BaseController<ChgrCurrState,ChgrCurrStateId,ChgrCurrStateRepository,ChgrCurrStateService> {
private final ChgrCurrStateService chgrCurrStateService;
private final String path = "/system/chgrCurrState/";
public ChgrCurrStateController(ChgrCurrStateService service, ChgrCurrStateService chgrCurrStateService) {
super(service);
this.chgrCurrStateService = chgrCurrStateService;
}
@GetMapping("list")
public String list(){
chgrCurrStateService.getChgrCurrState();
return path+"list";
}
@PostMapping("list.json")
@ResponseBody
public Map<String,Object> list(ChgrCurrState chgrCurrState){
return svcSelectList(chgrCurrState);
}
@PostMapping("view.json")
@ResponseBody
public Map<String, Object> viewData(ChgrCurrState chgrCurrState) throws JsonDataException {
return svcSelectOne(chgrCurrState);
}
@PostMapping("insert.json")
@ResponseBody
public Map<String, Object> insert(ChgrCurrState chgrCurrState) throws JsonDataException {
return svcInsert(chgrCurrState);
}
@PostMapping("update.json")
@ResponseBody
public Map<String, Object> update(ChgrCurrState chgrCurrState) throws JsonDataException {
return svcUpdate(chgrCurrState);
}
@Override
protected void chkSelectList(List<ChgrCurrState> list) throws JsonDataException {
}
@Override
protected void chkSelect(ChgrCurrState data) throws JsonDataException {
}
}
@@ -0,0 +1,19 @@
package net.jwsi.jcms.vpp.chgrCurrState;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Getter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public class ChgrCurrStateId implements Serializable {
private String providerId;
private String stId;
private String chgrId;
}
@@ -0,0 +1,8 @@
package net.jwsi.jcms.vpp.chgrCurrState;
import net.jwsi.jcms.base.BaseRecStRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface ChgrCurrStateRepository extends BaseRecStRepository<ChgrCurrState,ChgrCurrStateId> {
}
@@ -0,0 +1,87 @@
package net.jwsi.jcms.vpp.chgrCurrState;
import jakarta.transaction.Transactional;
import lombok.extern.slf4j.Slf4j;
import net.jwsi.jcms.base.BaseService;
import net.jwsi.jcms.base.EnumSqlType;
import net.jwsi.jcms.utils.HttpUtil;
import net.jwsi.jcms.utils.LoginUtil;
import net.jwsi.jcms.vpp.api.ApiClient;
import net.jwsi.jcms.vpp.api.ApiResponse;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@Slf4j
public class ChgrCurrStateService extends BaseService<ChgrCurrState,ChgrCurrStateId,ChgrCurrStateRepository> {
private final ApiClient apiClient;
public ChgrCurrStateService(ChgrCurrStateRepository repository, ApiClient apiClient) {
super(repository);
this.apiClient = apiClient;
}
@Transactional
@Scheduled(cron = "0 0 0 * * *")
public void getChgrCurrState() {
ApiResponse<List<ChgrCurrState>> response = apiClient.fetchChgrCurrState();
if (response == null || !Integer.valueOf(200).equals(response.getCode())) {
String msg = (response != null) ? response.getMessage() : "응답 없음";
throw new RuntimeException("API 호출 실패: " + msg);
}
List<ChgrCurrState> list = response.getData();
if (list == null || list.isEmpty()) {
log.info("가져온 충전소 데이터가 없습니다.");
}
List<ChgrCurrState> savedStations = super.repository.saveAll(list);
log.info("총 {}건의 충전소 데이터가 DB에 동기화되었습니다.", savedStations.size());
}
@Override
protected Integer getUserId() {
return HttpUtil.getUserId();
}
@Override
protected String getUserName(Integer id) {
return LoginUtil.getUserName(id);
}
@Override
protected ChgrCurrState newSearchParam(ChgrCurrState chgrCurrState) {
if(chgrCurrState == null){
chgrCurrState = new ChgrCurrState();
}
return chgrCurrState;
}
@Override
protected EnumSqlType useSqlTyp() {
return EnumSqlType.SPECIFICATION;
}
@Override
protected Specification<ChgrCurrState> getSpecification(ChgrCurrState chgrCurrState) {
return null;
}
@Override
protected Page<ChgrCurrState> _selectPage(ChgrCurrState chgrCurrState) {
return null;
}
@Override
protected List<ChgrCurrState> _selectList(ChgrCurrState chgrCurrState) {
return null;
}
}
@@ -40,7 +40,7 @@ public class ChgrHist extends BaseStEntity {
@Column(name = "RECHG_TIME")
private String rechgTime; // 충전시간
@Column(name = "RECH_GWH")
@Column(name = "RECHG_WH")
private Integer rechGwh; // 충전량
@Column(name = "RECHG_AMT")
@@ -8,13 +8,12 @@ import net.jwsi.jcms.utils.HttpUtil;
import net.jwsi.jcms.utils.LoginUtil;
import net.jwsi.jcms.vpp.api.ApiClient;
import net.jwsi.jcms.vpp.api.ApiResponse;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.time.LocalDate;
import java.util.List;
@Slf4j
@@ -23,11 +22,6 @@ public class ChgrHistService extends BaseService<ChgrHist, Integer, ChgrHistRepo
private final ApiClient apiClient;
@Value("${jcms.api.base-url}")
private String baseUrl;
@Value("${jcms.api.token}")
private String apiToken;
public ChgrHistService(ChgrHistRepository repository, ApiClient apiClient) {
super(repository);
@@ -37,7 +31,9 @@ public class ChgrHistService extends BaseService<ChgrHist, Integer, ChgrHistRepo
@Transactional
@Scheduled(cron = "0 */10 * * * *")
public void getChgrHist() throws IllegalAccessException {
ApiResponse<List<ChgrHistResponseDto>> response = apiClient.fetchChgrHist(baseUrl, apiToken);
String startDt = LocalDate.now().toString();
ApiResponse<List<ChgrHistResponseDto>> response = apiClient.fetchChgrHist(startDt, "50");
if (response == null || !Integer.valueOf(200).equals(response.getCode())) {
String msg = (response != null) ? response.getMessage() : "응답 없음";
@@ -46,21 +42,30 @@ public class ChgrHistService extends BaseService<ChgrHist, Integer, ChgrHistRepo
List<ChgrHistResponseDto> dtoList = response.getData();
if (dtoList == null || dtoList.isEmpty()) {
log.info("가져온 충전 데이터가 없습니다.");
log.info("가져온 충전이력 데이터가 없습니다.");
return;
}
List<ChgrHist> entityList = dtoList.stream()
.map(ChgrHistResponseDto::toEntity)
.toList();
List<ChgrHist> updateList = new ArrayList<>();
int insertCount = 0;
int updateCount = 0;
for (ChgrHist h : entityList) {
update(h);
updateList.add(h);
Integer id = BaseService.getId(h);
if (id != null && super.repository.existsById(id)) {
super.update(h);
updateCount++;
} else {
super.insert(h);
insertCount++;
}
}
log.info("총 {}건의 충전소 데이터가 DB에 동기화되었습니다.", updateList.size());
log.info("충전이력 동기화 완료 (신규 추가: {}건 / 기존 업데이트: {}건)", insertCount, updateCount);
}
@Override
@@ -8,15 +8,11 @@ import net.jwsi.jcms.utils.HttpUtil;
import net.jwsi.jcms.utils.LoginUtil;
import net.jwsi.jcms.vpp.api.ApiClient;
import net.jwsi.jcms.vpp.api.ApiResponse;
import net.jwsi.jcms.vpp.station.Station;
import net.jwsi.jcms.vpp.station.StationDto;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
@@ -26,12 +22,6 @@ public class ProviderService extends BaseService<Provider, String, ProviderRepos
private final ApiClient apiClient;
@Value("${jcms.api.base-url}")
private String baseUrl;
@Value("${jcms.api.token}")
private String apiToken;
public ProviderService(ProviderRepository repository, ApiClient apiClient) {
super(repository);
this.apiClient = apiClient;
@@ -40,7 +30,7 @@ public class ProviderService extends BaseService<Provider, String, ProviderRepos
@Transactional
@Scheduled(cron = "0 0 0 * * *")
public void getProviders() {
ApiResponse<List<ProviderDto>> response = apiClient.fetchProviders(baseUrl, apiToken);
ApiResponse<List<ProviderDto>> response = apiClient.fetchProviders();
if (response == null || !Integer.valueOf(200).equals(response.getCode())) {
String msg = (response != null) ? response.getMessage() : "응답 없음";
@@ -6,15 +6,13 @@ import net.jwsi.jcms.base.BaseService;
import net.jwsi.jcms.base.EnumSqlType;
import net.jwsi.jcms.utils.HttpUtil;
import net.jwsi.jcms.utils.LoginUtil;
import net.jwsi.jcms.vpp.api.ApiResponse;
import net.jwsi.jcms.vpp.api.ApiClient;
import org.springframework.beans.factory.annotation.Value;
import net.jwsi.jcms.vpp.api.ApiResponse;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
@@ -23,11 +21,7 @@ import java.util.stream.Collectors;
public class StationService extends BaseService<Station,String,StationRepository> {
private final ApiClient apiClient;
@Value("${jcms.api.base-url}")
private String baseUrl;
@Value("${jcms.api.token}")
private String apiToken;
public StationService(StationRepository repository, ApiClient apiClient) {
super(repository);
this.apiClient = apiClient;
@@ -36,7 +30,7 @@ public class StationService extends BaseService<Station,String,StationRepository
@Transactional
@Scheduled(cron = "0 0 0 * * *")
public void getStations() {
ApiResponse<List<StationDto>> response = apiClient.fetchStations(baseUrl, apiToken);
ApiResponse<List<StationDto>> response = apiClient.fetchStations();
if (response == null || !Integer.valueOf(200).equals(response.getCode())) {
String msg = (response != null) ? response.getMessage() : "응답 없음";
@@ -0,0 +1,38 @@
package net.jwsi.jcms.vpp.utils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Base64;
public class JwtUtil {
private static final ObjectMapper objectMapper = new ObjectMapper();
public static LocalDateTime getExpirationTime(String jwtToken) {
try {
String[] parts = jwtToken.split("\\.");
if (parts.length < 2) {
throw new IllegalArgumentException("올바르지 않은 JWT 토큰 형식입니다.");
}
String payloadJson = new String(Base64.getUrlDecoder().decode(parts[1]), StandardCharsets.UTF_8);
JsonNode payloadNode = objectMapper.readTree(payloadJson);
if (!payloadNode.has("exp")) {
throw new IllegalStateException("토큰에 exp(만료시간) 필드가 존재하지 않습니다.");
}
long expSeconds = payloadNode.get("exp").asLong();
return LocalDateTime.ofInstant(Instant.ofEpochSecond(expSeconds), ZoneId.systemDefault());
} catch (Exception e) {
throw new RuntimeException("토큰 만료 시간 추출 실패", e);
}
}
}
+4 -3
View File
@@ -19,12 +19,12 @@ jcms:
manager-path: cms
attr:
main-url: /cms/main
new-user-st: 9 # 1: ??, 9:????
new-user-st: 9
cms-name: VPP
cms-title: VPP
cms-bg-color: '#499'
cms-image-url: /public/images/logo_jcms3.png
copyright: Copyright 2026 ??????????? Inc.
copyright: Copyright 2026 주식회사 진우시스템 Inc.
authenticated-patten: /cms/**, /system/**, /api/**
pass-url: /cms/main
public-url: ''
@@ -33,4 +33,5 @@ jcms:
days: 30
api:
base-url: ${API_BASE_URL:http://dev.jinwoosi.co.kr:8072}
token: ${API_TOKEN}
user-id: ${API_USER_ID:apiuser}
user-pwd: ${API_USER_PWD:apiuser}
@@ -0,0 +1,307 @@
<!DOCTYPE html>
<html xmlns:th="http://thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/cmsLayout}">
<body>
<section layout:fragment="Content">
<div class="w-100" style="margin-bottom: .3rem;">
<div th:replace="~{common/fragments/searchBox :: SearchBoxFragment(~{ :: #searchBoxContent}, ~{ :: #searchBoxFooter})}">
<div id="searchBoxContent">
<div class="row px-2">
<div class="col-lg-4 col-sm-6 col-xs-12 pb-1">
<div class="input-group">
<span class="input-group-text" style="width:180px">provider_id</span>
<input type="text" id="providerIdLike" name="providerIdLike" class="form-control" placeholder="provider_id 입력" maxlength="50">
</div>
</div>
<div class="col-lg-4 col-sm-6 col-xs-12 pb-1">
<div class="input-group">
<span class="input-group-text" style="width:180px">st_id</span>
<input type="text" id="stIdLike" name="stIdLike" class="form-control" placeholder="st_id 입력" maxlength="50">
</div>
</div>
<div class="col-lg-4 col-sm-6 col-xs-12 pb-1">
<div class="input-group">
<span class="input-group-text" style="width:180px">chgr_id</span>
<input type="text" id="chgrIdLike" name="chgrIdLike" class="form-control" placeholder="chgr_id 입력" maxlength="50">
</div>
</div>
<div class="col-lg-4 col-sm-6 col-xs-12 pb-1">
<div class="input-group">
<span class="input-group-text" style="width:180px">상태 일시</span>
<input type="text" id="stateDtLike" name="stateDtLike" class="form-control" placeholder="상태 일시 입력" maxlength="50">
</div>
</div>
<div class="col-lg-4 col-sm-6 col-xs-12 pb-1">
<div class="input-group">
<span class="input-group-text" style="width:180px">op_mode</span>
<input type="text" id="opModeLike" name="opModeLike" class="form-control" placeholder="op_mode_cd 입력" maxlength="50">
</div>
</div>
<div class="col-lg-4 col-sm-6 col-xs-12 pb-1">
<div class="input-group">
<span class="input-group-text" style="width:180px">ch1_rechg_state_cd</span>
<select id="ch1RechgStateCdLike" name="ch1RechgStateCdLike" class="form-control"></select>
</div>
</div>
<div class="col-lg-4 col-sm-6 col-xs-12 pb-1">
<div class="input-group">
<span class="input-group-text" style="width:180px">ch1_door_state_cd</span>
<select id="ch1DoorStateCdLike" name="ch1DoorStateCdLike" class="form-control"></select>
</div>
</div>
<div class="col-lg-4 col-sm-6 col-xs-12 pb-1">
<div class="input-group">
<span class="input-group-text" style="width:180px">ch1_plug_state_cd</span>
<select id="ch1PlugStateCdLike" name="ch1PlugStateCdLike" class="form-control"></select>
</div>
</div>
</div> <!-- row 닫힘 -->
</div> <!-- searchBoxContent 닫힘 -->
<div id="searchBoxFooter">
<div class="row float-end">
<div class="col-xs-12">
<button type="button" class="btn btn-sm btn-info" id="searchBtn">검색</button>
<button type="button" class="btn btn-sm btn-info" id="resetBtn">리셋</button>
<th:block th:if="${menuRole?.roleWrite eq true}">
<button type="button" class="btn btn-sm btn-primary pl-2" onclick="showModal(ModalMode.REGISTER, {}, '');">등록</button>
</th:block>
</div>
</div>
</div> <!-- searchBoxFooter 닫힘 -->
</div> <!-- SearchBoxFragment 닫힘 -->
</div> <!-- w-100 닫힘 -->
<div class="w-100">
<div class="box box-primary">
<div class="form">
<table id="datatable" class="table table-striped table-hover dataTable" style="width:100%;"></table>
</div>
</div>
</div>
<!-- 권한 변수 선언 -->
<script th:inline="javascript">
const menuRoleWrite = /*[[${menuRole != null ? menuRole.roleWrite : false}]]*/ false;
const menuRoleModify = /*[[${menuRole != null ? menuRole.roleModify : false}]]*/ false;
const menuRoleDel = /*[[${menuRole != null ? menuRole.roleDel : false}]]*/ false;
</script>
<script th:inline="none">
const rootPath = "/cms/chgrCurrState/";
let datatable;
const ch1RechgStateCdCdList = getCdDtlList("rechgState");
const ch1DoorStateCdCdList = getCdDtlList("doorState");
const ch1PlugStateCdCdList = getCdDtlList("plugState");
$(document).ready(function() {
setSearchCdDtlOptions("ch1RechgStateCdLike", ch1RechgStateCdCdList);
setSearchCdDtlOptions("ch1DoorStateCdLike", ch1DoorStateCdCdList);
setSearchCdDtlOptions("ch1PlugStateCdLike", ch1PlugStateCdCdList);
const className = "dt-head-center dt-body-center";
datatable = newDataTable(
"#datatable",
rootPath + "list.json",
function(d) {
if (strUtil.isNotEmpty($('#providerIdLike').val())) {d.providerId = $('#providerIdLike').val();}
if (strUtil.isNotEmpty($('#stIdLike').val())) {d.stId = $('#stIdLike').val();}
if (strUtil.isNotEmpty($('#chgrIdLike').val())) {d.chgrId = $('#chgrIdLike').val();}
if (strUtil.isNotEmpty($('#stateDtLike').val())) {d.stateDt = $('#stateDtLike').val();}
if (strUtil.isNotEmpty($('#opModeLike').val())) {d.opMode = $('#opModeLike').val();}
if (strUtil.isNotEmpty($('#ch1RechgStateCdLike').val())) {d.ch1RechgStateCd = $('#ch1RechgStateCdLike').val();}
if (strUtil.isNotEmpty($('#ch1DoorStateCdLike').val())) {d.ch1DoorStateCd = $('#ch1DoorStateCdLike').val();}
if (strUtil.isNotEmpty($('#ch1PlugStateCdLike').val())) {d.ch1PlugStateCd = $('#ch1PlugStateCdLike').val();}
return d;
},
{
order: [],
columns: [
{title: "사업자 ID", name: "provider_id", data: "providerId", className},
{title: "충전소 ID", name: "st_id", data: "stId", className},
{title: "충전기 ID", name: "chgr_id", data: "chgrId", className},
{title: "상태 일시", name: "state_dt", data: "stateDt", className, orderable: false},
{title: "운영모드", name: "op_mode", data: "opMode", className, orderable: false},
{title: "CH1 상태", orderable: false, className,
render: (data, type, row) => {
let s1 = getCdDtlDtColNm(ch1RechgStateCdCdList, row["ch1RechgStateCd"]) || "";
let s2 = getCdDtlDtColNm(ch1DoorStateCdCdList, row["ch1DoorStateCd"]) || "";
let s3 = getCdDtlDtColNm(ch1PlugStateCdCdList, row["ch1PlugStateCd"]) || "";
return `<div class="d-flex justify-content-center gap-1">${s1} ${s2} ${s3}</div>`;
}
},
{title: "integrated_kwh", name: "integrated_kwh", data: "integratedKwh", className, visible: false},
{title: "dc_power_wh", name: "dc_power_wh", data: "dcPowerWh", className, visible: false},
{title: "ac_power_wh", name: "ac_power_wh", data: "acPowerWh", className, visible: false},
{title: "기능", orderable:false, width:"110px",
render: (data, type, row) => {
return mkRowDataFunctions({providerId: row['providerId'], stId: row['stId'], chgrId: row['chgrId']}, row['stId'], true, menuRoleModify, menuRoleDel);
}
}
],
allCheck: false,
});
});
const showModal = (mode, ids, title) => {
if(!checkRole(mode)) { alert("권한이 없습니다."); return; }
let modalInputArray = [
new ModalInput({
inputType: ModalInputType.text,
inputId: "providerId",
inputName: "providerId",
hasOldPk: true,
inputLabel: "provider_id",
inputPlaceholder: "provider_id",
isReq: false,
isEnable: true,
minLen: 0,
maxLen: 20,
}),
new ModalInput({
inputType: ModalInputType.text,
inputId: "stId",
inputName: "stId",
hasOldPk: true,
inputLabel: "st_id",
inputPlaceholder: "st_id",
isReq: false,
isEnable: true,
minLen: 0,
maxLen: 20,
}),
new ModalInput({
inputType: ModalInputType.text,
inputId: "chgrId",
inputName: "chgrId",
hasOldPk: true,
inputLabel: "chgr_id",
inputPlaceholder: "chgr_id",
isReq: false,
isEnable: true,
minLen: 0,
maxLen: 20,
}),
new ModalInput({
inputType: ModalInputType.textarea,
inputId: "stateDt",
inputName: "stateDt",
inputLabel: "상태 일시",
inputPlaceholder: "상태 일시",
isReq: false,
isEnable: true,
minLen: 0,
maxLen: 250,
}),
new ModalInput({
inputType: ModalInputType.textarea,
inputId: "opMode",
inputName: "opMode",
inputLabel: "op_mode_cd",
inputPlaceholder: "op_mode_cd",
isReq: false,
isEnable: true,
minLen: 0,
maxLen: 250,
}),
new ModalInput({
inputType: ModalInputType.select,
inputId: "ch1RechgStateCd",
inputName: "ch1RechgStateCd",
inputLabel: "ch1_rechg_state_cd",
inputPlaceholder: "ch1_rechg_state_cd",
isReq: false,
isEnable: true,
itemArray: toCdDtlItemArray(ch1RechgStateCdCdList),
}),
new ModalInput({
inputType: ModalInputType.select,
inputId: "ch1DoorStateCd",
inputName: "ch1DoorStateCd",
inputLabel: "ch1_door_state_cd",
inputPlaceholder: "ch1_door_state_cd",
isReq: false,
isEnable: true,
itemArray: toCdDtlItemArray(ch1DoorStateCdCdList),
}),
new ModalInput({
inputType: ModalInputType.select,
inputId: "ch1PlugStateCd",
inputName: "ch1PlugStateCd",
inputLabel: "ch1_plug_state_cd",
inputPlaceholder: "ch1_plug_state_cd",
isReq: false,
isEnable: true,
itemArray: toCdDtlItemArray(ch1PlugStateCdCdList),
}),
new ModalInput({
inputType: ModalInputType.text,
inputId: "integratedKwh",
inputName: "integratedKwh",
inputLabel: "integrated_kwh",
inputPlaceholder: "integrated_kwh",
isReq: false,
isEnable: true,
}),
new ModalInput({
inputType: ModalInputType.text,
inputId: "dcPowerWh",
inputName: "dcPowerWh",
inputLabel: "dc_power_wh",
inputPlaceholder: "dc_power_wh",
isReq: false,
isEnable: true,
}),
new ModalInput({
inputType: ModalInputType.text,
inputId: "acPowerWh",
inputName: "acPowerWh",
inputLabel: "ac_power_wh",
inputPlaceholder: "ac_power_wh",
isReq: false,
isEnable: true,
})
];
if(!rootPath){ alert("rootPath를 지정하십시요."); return; }
const insertUrl = rootPath+"insert.json";
const updateUrl = rootPath+"update.json";
const loadUrl = rootPath+"view.json";
const deleteUrl = rootPath+"delete.json";
const modalWidth = 500;
const labelWidth = '140px';
if(mode === ModalMode.REGISTER) {
newModal(new ModalInfo({modalTitle: "등록", inputArray: modalInputArray, modalWidth}), mode, 'main', {insertUrl, labelWidth, callBack: () => { defaultCallback(); }})
} else if(mode===ModalMode.VIEW || mode===ModalMode.VIEW_ONLY || mode===ModalMode.MODIFY) {
newModal(new ModalInfo({modalTitle: "상세정보", inputArray: modalInputArray, modalWidth}), mode, 'main', {loadUrl, updateUrl, ids, labelWidth, callBack: () => { defaultCallback(); }})
} else if(mode === ModalMode.DELETE) {
newDelete(deleteUrl, ids, title, () => { defaultCallback(); });
}
const defaultCallback = () => {
datatable.ajax.reload();
}
};
$("#searchBtn").click(function() {
datatable.ajax.reload();
});
$("#resetBtn").click(function() {
$("#providerIdLike").val("");
$("#stIdLike").val("");
$("#chgrIdLike").val("");
$("#stateDtLike").val("");
$("#opModeLike").val("");
$("#ch1RechgStateCdLike").val("");
$("#ch1DoorStateCdLike").val("");
$("#ch1PlugStateCdLike").val("");
datatable.ajax.reload();
});
</script>
</section>
</body>
</html>