3. 실제 구현
: 이번시간에는 앞에서 설명한 대로 실제 중복체크기능을 어떻게 구현할지 소스를 보면서 설명하도록 하겠습니다.
1) javascript(product.js)에서 로직 추가
var fnObj = {}; var ACTIONS = axboot.actionExtend(fnObj, { PAGE_SEARCH: function (caller, act, data) { axboot.ajax({ type: "GET", url: ["product"], data: caller.searchView.getData(), callback: function (res) { //중복기능추가용: 조회할때 기존 조회건인지를 확인하기 위해 __searched__ 속성을 더 붙여준다. for ( var i = 0; i < res.list.length; i++) { res.list[i].__searched__= true; } caller.gridView01.setData(res); } }); return false; }, PAGE_SAVE: function (caller, act, data) { var saveList = [].concat(caller.gridView01.getData("modified")); saveList = saveList.concat(caller.gridView01.getData("deleted")); axboot.ajax({ type: "PUT", url: ["product"], data: JSON.stringify(saveList), callback: function (res) { ACTIONS.dispatch(ACTIONS.PAGE_SEARCH); axToast.push(LANG("onsave")); }, options: { onError: function(err){ //{"message":"신규로 추가하신 [제품코드]코드는 이미 등록된 제품코드입니다."} axDialog.alert({ title: "Error", theme: "primary", width:450, msg: err.message }); } } }); }, ITEM_ADD: function (caller, act, data) { caller.gridView01.addRow(); }, ITEM_DEL: function (caller, act, data) { caller.gridView01.delRow("selected"); } }); var CODE = {}; //추가 // fnObj 기본 함수 스타트와 리사이즈 fnObj.pageStart = function () { // var _this = this; axboot .call({ type: "GET", url: "/api/v1/commonCodes", data: {groupCd: "ORIGIN"}, callback: function (res) { var originList = []; res.list.forEach(function (n) { originList.push({ CD: n.code, NM: n.name + "(" + n.code + ")" }); }); this.originList = originList; } }) .done(function () { CODE = this; // this는 call을 통해 수집된 데이터들. //위쪽 추가 _this.pageButtonView.initView(); // this --> _this 로 변경 _this.searchView.initView(); // this --> _this 로 변경 _this.gridView01.initView(); // this --> _this 로 변경
ACTIONS.dispatch(ACTIONS.PAGE_SEARCH); }); //추가 }; fnObj.pageResize = function () { }; fnObj.pageButtonView = axboot.viewExtend({ initView: function () { axboot.buttonClick(this, "data-page-btn", { "search": function () { ACTIONS.dispatch(ACTIONS.PAGE_SEARCH); }, "save": function () { ACTIONS.dispatch(ACTIONS.PAGE_SAVE); } }); } }); //== view 시작 /** * searchView */ fnObj.searchView = axboot.viewExtend(axboot.searchView, { initView: function () { this.target = $(document["searchView0"]); this.target.attr("onsubmit", "return ACTIONS.dispatch(ACTIONS.PAGE_SEARCH);"); this.filter = $("#filter"); }, getData: function () { return { pageNumber: this.pageNumber, pageSize: this.pageSize, filter: this.filter.val() } } }); /** * gridView */ var list = []; fnObj.gridView01 = axboot.viewExtend(axboot.gridView, { initView: function () { var _this = this; this.originList = CODE.originList; //추가
this.target = axboot.gridBuilder({ showRowSelector: true, frozenColumnIndex: 0, sortable: true, multipleSelect: true, target: $('[data-ax5grid="grid-view-01"]'), columns: [ {key: "prdtCd", label: "제품코드", width: 100, align: "center", editor: "text"}, {key: "prdtNm", label: "제품명", width: 200, align: "center", editor: "text"}, { key: "origin", label: "원산지", width: 100,align: "center", editor: { type: "select", config: { columnKeys: { optionValue: "CD", optionText: "NM" }, options: this.originList //추가 /* [ {"CD":"KR","NM":"한국(KR)"}, {"CD":"US","NM":"미국(US)"}, {"CD":"JP","NM":"일본(JP)"} ] */
} } }, {key: "purchasePrice", label: "매입가격", width: 150, align: "right", editor: "number"}, {key: "salesPrice", label: "판매가격", width: 150, align: "right", editor: "number"} ], body: { onClick: function () { this.self.select(this.dindex, {selectedClear: true}); } } }); axboot.buttonClick(this, "data-grid-view-01-btn", { "add": function () { ACTIONS.dispatch(ACTIONS.ITEM_ADD); }, "delete": function () { ACTIONS.dispatch(ACTIONS.ITEM_DEL); } }); }, getData: function (_type) { var _list = this.target.getList(_type);
if (_type == "modified" || _type == "deleted") { list = ax5.util.filter(_list, function () { return this.prdtCd ; }); } else { list = _list; }
return list; }, addRow: function () { this.target.addRow({__created__: true, origin: "KR"}, "last"); }, delRow: function delRow(_type) { this.target.deleteRow(_type); //여기서 무조건 deleteList에 추가해주고 있는것 같다.
//그렇다보니 기존 조회된 데이터가 아닌 신규로 추가한 후 삭제해도 추가되기 때문에 //저장시 안넘어가도 되는 데이터(화면상에서만 행추가후 삭제시)까지 날라간다.
//중복기능추가시: 조회된것이 아닌경우 deleteList에서 빼준다. for(i=0;i<this.target.deletedList.length ;i++) { if(this.target.deletedList[i].__searched__==undefined) { this.target.deletedList[i]=null; } }
} }); |
2) Controller(ProductController) 에서 로직 추가
package com.dasdes.shopmng.controllers; import com.chequer.axboot.core.api.response.Responses; import com.chequer.axboot.core.controllers.BaseController; import com.chequer.axboot.core.parameter.RequestParams; import org.springframework.stereotype.Controller; import com.chequer.axboot.core.api.ApiException; import com.chequer.axboot.core.api.response.ApiResponse; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import com.dasdes.shopmng.domain.prdt.Product; import com.dasdes.shopmng.domain.prdt.ProductService; import com.wordnik.swagger.annotations.ApiImplicitParam; import com.wordnik.swagger.annotations.ApiImplicitParams; import javax.inject.Inject; import java.util.List; @Controller @RequestMapping(value = "/api/v1/product") public class ProductController extends BaseController { @Inject private ProductService productService; @RequestMapping(method = RequestMethod.GET, produces = APPLICATION_JSON) @ApiImplicitParams({ @ApiImplicitParam(name = "prdtCd", value = "제품코드", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "prdtNm", value = "제품명", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "filter", value = "검색어", dataType = "String", paramType = "query") }) public Responses.ListResponse list(RequestParams<Product> requestParams) { List<Product> list = productService.gets(requestParams); return Responses.ListResponse.of(list); } @RequestMapping(method = {RequestMethod.PUT}, produces = APPLICATION_JSON) public ApiResponse save(@RequestBody List<Product> request) {
//중복체크 후 중복발생 시 Exception핸들러로 받는다. try { productService.savePrdt(request); } catch(ApiException e) { return handleApiException(e); } return ok(); } } |
3) ProductService 에서 로직 추가
package com.dasdes.shopmng.domain.prdt; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; //추가 import org.springframework.web.bind.annotation.ExceptionHandler; import com.dasdes.shopmng.domain.BaseService; import com.querydsl.core.BooleanBuilder; //추가 import javax.inject.Inject; import com.chequer.axboot.core.parameter.RequestParams; import java.util.List; import com.chequer.axboot.core.api.ApiException; //import org.slf4j.Logger; //import org.slf4j.LoggerFactory; @Service public class ProductService extends BaseService<Product, String> { //private final Logger logger = LoggerFactory.getLogger(ProductService.class); private ProductRepository productRepository; @Inject public ProductService(ProductRepository productRepository) { super(productRepository); this.productRepository = productRepository; } public List<Product> gets(RequestParams<Product> requestParams) { String prdtCd=requestParams.getString("prdtCd", ""); String prdtNm=requestParams.getString("prdtNm", ""); String filter = requestParams.getString("filter");
BooleanBuilder builder = new BooleanBuilder(); if (isNotEmpty(prdtCd)) { builder.and(qProduct.prdtCd.eq(prdtCd)); } if (isNotEmpty(prdtNm)) { builder.and(qProduct.prdtNm.eq(prdtNm)); } List<Product> prdtList = select().from(qProduct).where(builder).orderBy(qProduct.prdtCd.asc(), qProduct.prdtNm.asc()).fetch(); if (isNotEmpty(filter)) { prdtList = filter(prdtList, filter); }
return prdtList; }
@Transactional public void savePrdt(List<Product> product) { Product prdt=null;
for(int i=0;i<product.size();i++) { prdt=(Product)product.get(i);
//신규추가된 데이터에 대해 기존에 있는데이터인지 체크 if(prdt.isCreated() && exists(prdt.getId())) { throw new ApiException("신규로 추가하신 ["+prdt.getId()+"]코드는 이미 등록된 제품코드입니다."); } } save(product); } } |
4) 최종결과확인
: 위와같이 소스를 수정하고 서버를 재기동 후 중복제품코드를 추가해서 입력해본다.
어때요? 도움이 많이 되셨나요? ~~~~~~~
'오픈소스 > AXBoot프로그래밍' 카테고리의 다른 글
Axboot 멀티 테이블 수정/저장 예제 (2/2) (11) | 2019.06.06 |
---|---|
Axboot 멀티 테이블 수정/저장 예제 (1/2) (0) | 2019.06.05 |
Axboot 신규화면 만들기 7 - 중복등록체크로직 추가 -1 현상/방안 (0) | 2018.11.28 |
Axboot 신규화면 만들기 6 - 행추가시 초기값(default) 셋팅하기 (0) | 2018.11.28 |