Compare commits

...
4 Commits
Author SHA1 Message Date
ChooSeongBin 938fae0359 Merge branch 'sb' 2026-07-29 09:01:43 +09:00
ChooSeongBin 852d48c1b7 소스정리 2026-07-29 09:01:27 +09:00
hyunjaeeun 318a741c19 충전사업자 관리 html 기능컬럼 추가 2026-07-28 17:44:44 +09:00
hyunjaeeun 69a0529b7c 충전사업자 html코드 추가 2026-07-28 17:20:48 +09:00
9 changed files with 473 additions and 1 deletions
@@ -1,6 +1,7 @@
package net.jwsi.jcms.vpp.api;
import lombok.RequiredArgsConstructor;
import net.jwsi.jcms.vpp.charger.Chgr;
import net.jwsi.jcms.vpp.provider.ProviderDto;
import net.jwsi.jcms.vpp.station.StationDto;
import org.springframework.core.ParameterizedTypeReference;
@@ -44,4 +45,17 @@ public class ApiClient {
.retrieve()
.body(new ParameterizedTypeReference<ApiResponse<List<ProviderDto>>>() {});
}
public ApiResponse<List<Chgr>> fetchChgr(String baseUrl, String token) {
URI uri = UriComponentsBuilder.fromUriString(baseUrl)
.path("/api/charge/list")
.build()
.toUri();
return restClient.post()
.uri(uri)
.header("Authorization", "Bearer " + token)
.retrieve()
.body(new ParameterizedTypeReference<ApiResponse<List<Chgr>>>() {});
}
}
@@ -0,0 +1,27 @@
package net.jwsi.jcms.vpp.charger;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import net.jwsi.jcms.base.BaseStEntity;
@NoArgsConstructor
@Setter
@Getter
@ToString
@Entity(name = "vpp_chgr")
public class Chgr extends BaseStEntity {
@Id
private String chgrId; //충전기 id(pk)
private String providerId; //충전사업자 id(pk) @Id
private String stId; //충전소 id(pk) @Id
private String stNm; //충전소 명
private String chgrNm; //충전기 명
private String speedTpCd; //충전기속도 코드
private String chgrTypeCd; //충전기타입 코드
}
@@ -0,0 +1,26 @@
package net.jwsi.jcms.vpp.charger;
import net.jwsi.jcms.base.BaseController;
import net.jwsi.jcms.exception.JsonDataException;
import org.springframework.stereotype.Controller;
import java.util.List;
@Controller
public class ChgrController extends BaseController<Chgr,String,ChgrRepository,ChgrService> {
public ChgrController(ChgrService service) {
super(service);
}
@Override
protected void chkSelectList(List list) throws JsonDataException {
}
@Override
protected void chkSelect(Chgr data) throws JsonDataException {
}
}
@@ -0,0 +1,8 @@
package net.jwsi.jcms.vpp.charger;
import net.jwsi.jcms.base.BaseRecStRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface ChgrRepository extends BaseRecStRepository<Chgr,String> {
}
@@ -0,0 +1,66 @@
package net.jwsi.jcms.vpp.charger;
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 org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@Slf4j
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;
}
@Override
protected Integer getUserId() {
return HttpUtil.getUserId();
}
@Override
protected String getUserName(Integer id) {
return LoginUtil.getUserName(id);
}
@Override
protected Chgr newSearchParam(Chgr chgr) {
if(chgr == null){ chgr = new Chgr();}
return chgr;
}
@Override
protected EnumSqlType useSqlTyp() {
return EnumSqlType.SPECIFICATION;
}
@Override
protected Specification<Chgr> getSpecification(Chgr chgr) {
return null;
}
@Override
protected Page<Chgr> _selectPage(Chgr chgr) {
return null;
}
@Override
protected List<Chgr> _selectList(Chgr chgr) {
return null;
}
}
@@ -0,0 +1,4 @@
package net.jwsi.jcms.vpp.charger;
public class ChgrSpecification {
}
@@ -0,0 +1,34 @@
package net.jwsi.jcms.vpp.charger;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class ResponseDto {
private String providerId;
private String stId;
private String stNm;
private String chgrId;
private String chgrNm;
private String speedTp;
private String chgrType;
private double gpsXpos;
private double gpsYpos;
private String locInfo;
private String memshOnly;
private String installYy;
private String simulRechg;
private String simulChgrId;
public Chgr toEntity(){
Chgr chgr = new Chgr();
chgr.setChgrId(this.chgrId);
chgr.setStId(this.stId);
chgr.setStNm(this.stNm);
chgr.setChgrNm(this.chgrNm);
chgr.setSpeedTpCd(this.speedTp);
chgr.setChgrTypeCd(this.chgrType);
return chgr;
}
}
@@ -9,7 +9,6 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -28,6 +27,7 @@ public class StationController extends BaseController<Station,String,StationRepo
@GetMapping("list")
public String list() {
stationService.getStations();
return path + "list";
}
@PostMapping("list.json")
@@ -0,0 +1,293 @@
<!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:140px">충전사업자명</span>
<input type="text" id="providerNmLike" name="providerNmLike" 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:140px">사업자번호</span>
<input type="text" id="bizTaxIdLike" name="bizTaxIdLike" 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:140px">대표자</span>
<input type="text" id="ceoLike" name="ceoLike" 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:140px">전화번호</span>
<input type="text" id="telLike" name="telLike" 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:140px">팩스번호</span>
<input type="text" id="faxLike" name="faxLike" class="form-control" placeholder="팩스번호 입력" maxlength="50">
</div>
</div>
</div>
</div>
<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>
</div>
</div>
<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="none">
const rootPath = "/cms/provider/";
let datatable;
$(document).ready(function() {
const className = "dt-head-center dt-body-center";
datatable = newDataTable(
"#datatable",
rootPath + "list.json",
function(d) {
if (strUtil.isNotEmpty($('#providerNmLike').val())) {d.providerNm = $('#providerNmLike').val();}
if (strUtil.isNotEmpty($('#bizTaxIdLike').val())) {d.bizTaxId = $('#bizTaxIdLike').val();}
if (strUtil.isNotEmpty($('#ceoLike').val())) {d.ceo = $('#ceoLike').val();}
if (strUtil.isNotEmpty($('#telLike').val())) {d.tel = $('#telLike').val();}
if (strUtil.isNotEmpty($('#faxLike').val())) {d.fax = $('#faxLike').val();}
return d;
},
{
order: [],
columns: [
{title: "충전사업자 명", name: "PROVIDER_NM", data: "providerNm", className, orderable: false},
{title: "사업자번호", name: "biz_tax_id", data: "bizTaxId", className, orderable: false},
{title: "대표자", name: "CEO", data: "ceo", className, orderable: false},
{title: "전화번호", name: "TEL", data: "tel", className, orderable: false},
{title: "팩스번호", name: "FAX", data: "fax", className, orderable: false},
{title: "기능", orderable: false, width: "140px", className,
render: (data, type, row) => { return mkRowDataFunctions( { providerId: row['providerId'] },row['providerNm'], true, true, true);}
}
],
allCheck: false,
});
});
const showModal = (mode, ids, title) => {
if(!checkRole(mode)) { alert("권한이 없습니다."); return; }
let modalInputArray = [
new ModalInput({
inputType: ModalInputType.hidden,
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: "providerNm",
inputName: "providerNm",
inputLabel: "충전사업자 명",
inputPlaceholder: "충전사업자 명",
isReq: false,
isEnable: true,
minLen: 0,
maxLen: 50,
}),
new ModalInput({
inputType: ModalInputType.text,
inputId: "bizTaxId",
inputName: "bizTaxId",
inputLabel: "사업자번호",
inputPlaceholder: "사업자번호",
isReq: false,
isEnable: true,
minLen: 0,
maxLen: 20,
}),
new ModalInput({
inputType: ModalInputType.text,
inputId: "ceo",
inputName: "ceo",
inputLabel: "대표자",
inputPlaceholder: "대표자",
isReq: false,
isEnable: true,
minLen: 0,
maxLen: 50,
}),
new ModalInput({
inputType: ModalInputType.text,
inputId: "tel",
inputName: "tel",
inputLabel: "전화번호",
inputPlaceholder: "전화번호",
isReq: false,
isEnable: true,
minLen: 0,
maxLen: 30,
}),
new ModalInput({
inputType: ModalInputType.text,
inputId: "fax",
inputName: "fax",
inputLabel: "팩스번호",
inputPlaceholder: "팩스번호",
isReq: false,
isEnable: true,
minLen: 0,
maxLen: 30,
}),
new ModalInput({
inputType: ModalInputType.textarea,
inputId: "email",
inputName: "email",
inputLabel: "이메일",
inputPlaceholder: "이메일",
isReq: false,
isEnable: true,
minLen: 0,
maxLen: 250,
}),
new ModalInput({
inputType: ModalInputType.text,
inputId: "mgrNm",
inputName: "mgrNm",
inputLabel: "담당자 명",
inputPlaceholder: "담당자 명",
isReq: false,
isEnable: true,
minLen: 0,
maxLen: 50,
}),
new ModalInput({
inputType: ModalInputType.text,
inputId: "mgrTel",
inputName: "mgrTel",
inputLabel: "담당자 전화번호",
inputPlaceholder: "담당자 전화번호",
isReq: false,
isEnable: true,
minLen: 0,
maxLen: 30,
}),
new ModalInput({
inputType: ModalInputType.text,
inputId: "emgncyTel",
inputName: "emgncyTel",
inputLabel: "긴급 전화번호",
inputPlaceholder: "긴급 전화번호",
isReq: false,
isEnable: true,
minLen: 0,
maxLen: 30,
}),
new ModalInput({
inputType: ModalInputType.text,
inputId: "zipCode",
inputName: "zipCode",
inputLabel: "우편번호",
inputPlaceholder: "우편번호",
isReq: false,
isEnable: true,
minLen: 0,
maxLen: 7,
}),
new ModalInput({
inputType: ModalInputType.textarea,
inputId: "addrRdM",
inputName: "addrRdM",
inputLabel: "주소 도로명 메인",
inputPlaceholder: "주소 도로명 메인",
isReq: false,
isEnable: true,
minLen: 0,
maxLen: 255,
}),
new ModalInput({
inputType: ModalInputType.textarea,
inputId: "addrRdD",
inputName: "addrRdD",
inputLabel: "주소 도로명 상세",
inputPlaceholder: "주소 도로명 상세",
isReq: false,
isEnable: true,
minLen: 0,
maxLen: 255,
}),
new ModalInput({
inputType: ModalInputType.textarea,
inputId: "remark",
inputName: "remark",
inputLabel: "비고",
inputPlaceholder: "비고",
isReq: false,
isEnable: true,
minLen: 0,
maxLen: 250,
})
];
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 = '90px';
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() {
$("#providerNmLike").val("");
$("#bizTaxIdLike").val("");
$("#ceoLike").val("");
$("#telLike").val("");
$("#faxLike").val("");
datatable.ajax.reload();
});
</script>
</section>
</body>
</html>