Bizbee ERP
[ SI/SM 프로젝트 ] 급여정산 파트 신규개발 및 고도화, API인증/통신 구축

#1. 급여시뮬레이션
Code
/** [급여반영] */
function openPayCreatePopup() {
if(vm.flex.getSaveData()) return alert('수정중인 데이터가 존재합니다.');
if(!vm.flex.getCheckedData('chk')) return alert('선택된 사원이 없습니다.');
var checkData = vm.flex.getCheckedData('chk').checkData;
Object.values(checkData).forEach(function(chk){
var payList = []; //반영할 사원데이터별 지급항목 list 매칭
Object.values(chk).forEach(function(payAmt, i){
//지급항목2 크기만큼 name, payCd, payAmt 매칭
for( var j=0 ; j < vm.amtData.length ; j++ ){
if( Object.keys(chk)[i] == vm.amtData[j]['colKey']){
payList.push(
{
'name': vm.amtData[j]['colKey'],
'payCd': vm.amtData[j]['payCd'],
'payAmt' : Number(payAmt) || 0
}
)
}
}
})
chk.payList = payList; //저장 사원데이터별 지급항목 list 주입
})
var param = { vm, checkData };
PopupService.open('payCreatePopup', param)
}

#2. 전표등록
Code
/** 그리드 - 전표데이터 Set */
vm.flexInitialized = function(sender, event) {
var groupRow = new wijmo.grid.GroupRow();
sender.columnFooters.rows.push(groupRow);
sender.columnFooters.setCellData(0, 1, '합계');
sender.excelFormatItem = function (xlsxFormatItemEventArgs) {
if (xlsxFormatItemEventArgs.panel.cellType == wijmo.grid.CellType.ColumnFooter) {
var col = xlsxFormatItemEventArgs.panel.columns[xlsxFormatItemEventArgs.col];
if (['totAmt', 'splyAmt', 'vatAmt'].indexOf(col.binding) != -1) {
var items = vm.flex.collectionView.items, sum = 0;
for (var i = 0; i < items.length; i++) {
sum += ((items[i].signTp == '2' ? -1 : 1) * items[i][col.binding]);
}
xlsxFormatItemEventArgs.xlsxCell.value = sum;
}
}
};
sender.itemFormatter = function(panel, r, c, cell) {
if ( panel.cellType == wijmo.grid.CellType.ColumnFooter ) {
var items = vm.flex.collectionView.items;
var binding = panel.columns[c].binding;
if (binding == 'splyAmt' || binding == 'vatAmt' || binding == 'totAmt' || binding == 'poQty') {
var dcmTp = ''
if (binding == 'splyAmt') dcmTp = splyDcm
else if (binding == 'vatAmt') dcmTp = vatDcm
else if (binding == 'totAmt') dcmTp = totDcm
else if (binding == 'poQty') dcmTp = qtyDcm
var convNum = $filter('number')(getSum(items, binding), dcmTp);
var intConvNum = Number(convNum.replace(/,/g, ''));
var strConvNum = intConvNum.toString().replace(/\B(?=(\d{3})+(?!\d))(?<!\.\d*)/g, ',');
cell.innerText = strConvNum;
}
}
if (panel.cellType == wijmo.grid.CellType.Cell) {
var item = panel.rows[r].dataItem;
var binding = panel.grid.getColumn(c).binding;
if (['signTp','poQty','splyAmt','vatAmt','totAmt'].includes(binding)) {
cell.className += item.signTp=='2'? ' text-red' : '';
}
}
function getSum(items, col){
var result = 0;
for(var i = 0 ; i < items.length ; i++ ) {
result += ( ( items[i].signTp == '2' ? -1 : 1 ) * items[i][col]);
}
return result;
}
}
}

#3. 근태환경설정
Code
/** 카카오맵 */
function initKakao() {
kakao.maps.load(function() {
var kakaoMapDiv = vm.context.find('#kakaoMapDivPopup')[0];
var latlng = new kakao.maps.LatLng(DEFAULT_GPS.LATITUDE, DEFAULT_GPS.LONGTITUDE);
var mapOpts = { center : latlng, level : 4 }
var map = new kakao.maps.Map(kakaoMapDiv, mapOpts);
//gps 위도경도,반경값이 있으면 마커,반경 표시
if (searchAddrGps.latitude !='' && searchAddrGps.longitude !=''){
latlng = new kakao.maps.LatLng(searchAddrGps.latitude, searchAddrGps.longitude);
map.setCenter(latlng);
// 마커 표시
var marker = new kakao.maps.Marker({
map: map,
position: latlng
});
marker.setMap(map);
//반경표시
var circle = new kakao.maps.Circle({
center: marker.getPosition(),
radius: Number(searchGpsScope),
strokeWeight: 1, // 선의 두께
strokeColor: '#00a0e9', // 선의 색깔
strokeOpacity: 0.1, // 선 불투명도
});
circle.setMap(map);
}
})
}
#4. API인증/통신 - 전자결재 서비스 구축
Code
@Component
public class ApiWorksDecryptUtil {
/**
* @param 암호화된 토큰
* @param ApiElecApprParam(복호화키 사용 파라미터)
* @return (String)복호화된 토큰
* */
public String decrypt(String encodedText, ApiElecApprParam param) throws Exception {
String secretKeyStr = generateKey("ERP" + param.getCorpCd());
SecretKeySpec secretKey = new SecretKeySpec(secretKeyStr.getBytes("UTF-8"), "AES");
IvParameterSpec IV = new IvParameterSpec(secretKeyStr.substring(0, 16).getBytes());
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
c.init(Cipher.DECRYPT_MODE, secretKey, IV);
byte[] decodeByte = Hex.decodeHex(encodedText.toCharArray());
return new String(c.doFinal(decodeByte), "UTF-8");
};
/** 복호화용 키생성 (salt + 회사코드 + 시스템명) */
private String generateKey(String inputText) throws Exception {
if (!StringUtils.hasText(inputText)) {
throw new NullPointerException("inputText IS null");
}
return padLeftZeros(inputText.toUpperCase(), 32);
}
/** 키생성규칙 - 32자 padLeft zero */
private String padLeftZeros(String inputString, int length) {
if (inputString.length() >= length) { return inputString; }
StringBuilder sb = new StringBuilder();
while (sb.length() < length - inputString.length()) {
sb.append('0');
}
sb.append(inputString);
return sb.toString();
}
}
@Component
@RequiredArgsConstructor
public class ApiWorksWebClientUtil {
private final ErpServerRegService serverService;
private final ConnectMapper ConnectMapper;
/** 토큰발급 및 조회 */
public String getToken(ApiWorksElecApprParam param) {
HttpHeaders headers = setHeaders();
String worksRelUrl = setWorksRel(param);
WebClient webClient = WebClient
.builder()
.baseUrl(worksRelUrl)
.build();
ResponseEntity<String> responseToken = webClient.post()
.uri("/api/getToken")
.headers(httpHeaders -> httpHeaders.addAll(headers))
.body(BodyInserters.fromValue(param))
.retrieve()
.toEntity(String.class)
.block();
assert responseToken != null;
return responseToken;
}
String setWorksRel(ApiWorksElecApprParam param) {
String worksRelUrl = serverService.get(null).get("Url");
String worksCorpCd = ConnectMapper.selectWorksCorpCd(param.getCorpCd());
param.setCorpCd(worksCorpCd);
param.setMemberId("ADMIN");
return worksRelUrl;
}
private HttpHeaders setHeaders() {
HttpServletRequest req = getRequest();
HttpHeaders headers = new HttpHeaders();
headers.add("ip", ErpUtil.getIpAddress(req));
return headers;
}
}