function newSprt02050ControlRD(pageName, doctx="[data-doctx='sprt02050']", mainPageName="sprt02010") {
    let ctrlRdct = new DatasetControl({
          doctx: doctx
        , prefix: "rdct"
        , prefixName: "감경"
        , dataGetter: obj => obj["rdctInfo"]
        , infoSize: "md"
        , urls: {
              getInfo: "/info.do"
            , remove: "/remove.do"
        }
    });

    /**************************************************************************
     * DatasetControl Events
     **************************************************************************/
    // 현재 선택 자료 변경 이벤트
    ctrlRdct.onCurrentChange = (item) => {
        if (!item) return;

        // 화면에 단속 Dataset 셋팅
        let formFields = new FimsFormFields(ctrlRdct.selector("[name='frmEditRdct']"));
        formFields.set(ctrlRdct, item);
    };

    // 상세 정보 dialog
    ctrlRdct.getInfo = (params) => {
        if (!params) return;

        ajax.get({
              url: wctx.url("/levy/levy02/020/info.do")
            , data: params || {}
            , success: (resp) => {
                if ((typeof resp) != "string") {
                    if (resp.rtnMsg)
                        return dialog.alert(resp.rtnMsg);
                } else {
                    let dialogName = ctrlRdct.prefixed("Dialog");
                    let dialogId = dialogName + "-" + uuid();

                    dialog.open({
                          id: dialogId
                        , title: params.btnTitle
                        , size: ctrlRdct.infoSize
                        , content: resp
                        , init: () => {
                            $("#" + dialogId).attr("name", dialogName);
                            $("#" + dialogId).attr("data-ref-doctx", pageName);

                            AppSupport.setDialogZindex();
                        }
                        , onClose: () => { pageObject[pageName].fnRefresh(); }  // 정보 새로고침
                    });
                }
            }
        });
    }

    // 삭제 callback
    ctrlRdct.onRemove = (params, resp) => {
		if (resp.saved)
			return pageObject[mainPageName].fnRefresh();

        let showMessage = resp.rtnMsg.replace(/[S]|[F]/g, params.btnTitle);

        // 메시지 출력
        dialog.alert({
              content: showMessage
            , init: () => { AppSupport.setDialogZindex(); }
            , onOK: resp.saved ? undefined : () => { }
            , onClose: () => {
                if (resp.saved) { pageObject[pageName].fnRefresh(); }           // 정보 새로고침
            }
        });
    }

    // 삭제
    ctrlRdct.remove = (params) => {
        if (!params) return;

        ajax.post({
              url: wctx.url("/levy/levy02/010/remove.do")
            , data: params || {}
            , success: (resp) => { ctrlRdct.onRemove(params, resp); }
        });
    }

    return ctrlRdct;
}

function newSprt02050ControlLE(pageName, doctx="[data-doctx='sprt02050']", mainPageName="sprt02010") {
    let ctrlLevyExcl = new DatasetControl({
          doctx: doctx
        , prefix: "levyExcl"
        , prefixName: "부과제외"
        , dataGetter: obj => obj["levyExclInfo"]
        , infoSize: "md"
        , urls: {
              getInfo: "/info.do"
            , remove: "/remove.do"
        }
    });

    /**************************************************************************
     * DatasetControl Events
     **************************************************************************/
    // 현재 선택 자료 변경 이벤트
    ctrlLevyExcl.onCurrentChange = (item) => {
        if (!item) return;

        // 화면에 단속 Dataset 셋팅
        let formFields = new FimsFormFields(ctrlLevyExcl.selector("[name='frmEditLevyExcl']"));
        formFields.set(ctrlLevyExcl, item);
    };

    // 상세 정보 dialog
    ctrlLevyExcl.getInfo = (params) => {
        if (!params) return;

        ajax.get({
              url: wctx.url("/excl/excl01/020/info.do")
            , data: params || {}
            , success: (resp) => {
                if ((typeof resp) != "string") {
                    if (resp.rtnMsg)
                        return dialog.alert(resp.rtnMsg);
                } else {
                    let dialogName = ctrlLevyExcl.prefixed("Dialog");
                    let dialogId = dialogName + "-" + uuid();

                    dialog.open({
                          id: dialogId
                        , title: params.btnTitle
                        , size: ctrlLevyExcl.infoSize
                        , content: resp
                        , init: () => {
                            $("#" + dialogId).attr("name", dialogName);
                            $("#" + dialogId).attr("data-ref-doctx", pageName);

                            AppSupport.setDialogZindex();
                        }
                        , onClose: () => { pageObject[pageName].fnRefresh(); }  // 정보 새로고침
                    });
                }
            }
        });
    }

    // 삭제 callback
    ctrlLevyExcl.onRemove = (params, resp) => {
		if (resp.saved)
			return pageObject[mainPageName].fnRefresh();

        let showMessage = resp.rtnMsg.replace(/[S]|[F]/g, params.btnTitle);

        // 메시지 출력
        dialog.alert({
              content: showMessage
            , init: () => { AppSupport.setDialogZindex(); }
            , onOK: resp.saved ? undefined : () => { }
            , onClose: () => {
                if (resp.saved) { pageObject[pageName].fnRefresh(); }           // 정보 새로고침
            }
        });
    }

    // 삭제
    ctrlLevyExcl.remove = (params) => {
        if (!params) return;

        ajax.post({
              url: wctx.url("/excl/excl01/010/remove.do")
            , data: params || {}
            , success: (resp) => { ctrlLevyExcl.onRemove(params, resp); }
        });
    }

    return ctrlLevyExcl;
}

function newSprt02050ControlCSH(pageName, doctx="[data-doctx='sprt02050']", mainPageName="sprt02010") {
    let ctrlCrdnSttsHstry = new DatasetControl({
          doctx: doctx
        , prefix: "crdnSttsHstry"
        , prefixName: "단속상태 이력"
        , dataGetter: obj => obj["crdnSttsHstrys"]
        , keys: ["STTS_HSTRY_ID"]
        , appendData: true
        , infoSize: "md"
        , urls: {
              load: "/list.do"
            , getInfo: "/info.do"
        }
        , formats: {
              REG_DT: datetimeFormat
            , MDFCN_DT: datetimeFormat
        }
    });

    /**************************************************************************
     * DatasetControl Events
     **************************************************************************/
    // Dataset 변경 이벤트
    ctrlCrdnSttsHstry.onDatasetChange = (obj, option) => {
        // 데이터 셋
        let dataList = ctrlCrdnSttsHstry.dataset;
        let empty = dataList.empty;

        let replacer = (str, dataItem) => str
            .replace(/{onclick}/gi, "pageObject['" + pageName + "'].ctrlCrdnSttsHstry.setCurrent('{data-index}');")

        let trs = empty ?
                      [ctrlCrdnSttsHstry.find("[name='tmpltNotFoundCrdnSttsHstry']").innerHTML]
                    : dataList.inStrings(ctrlCrdnSttsHstry.find("[name='tmpltCrdnSttsHstryRows']").innerHTML, replacer);

        // dataTables(그리드)에 자료 표시 td
        $(ctrlCrdnSttsHstry.find("[name='tbodyCrdnSttsHstryList']")).html(trs.join());
    };

    // 현재 선택 자료 변경 이벤트
    ctrlCrdnSttsHstry.onCurrentChange = (item) => {
        Apply.fromDataset.currentRow(ctrlCrdnSttsHstry.dataset, item, ctrlCrdnSttsHstry.find("[name='tbodyCrdnSttsHstryList']"));
    };

    return ctrlCrdnSttsHstry;
}

function newSprt02050ControlPAH(pageName, doctx="[data-doctx='sprt02050']", mainPageName="sprt02010") {
    let ctrlPayerAddrHstrys = new DatasetControl({
          doctx: doctx
        , prefix: "payerAddrHstry"
        , prefixName: "납부자주소 이력"
        , dataGetter: obj => obj["payerAddrHstrys"]
        , keys: ["ADDR_HSTRY_ID"]
        , appendData: true
        , infoSize: "md"
        , urls: {
              load: "/list.do"
            , getInfo: "/info.do"
        }
        , formats: {
            REG_DT: datetimeFormat
        }
    });

    /**************************************************************************
     * DatasetControl Events
     **************************************************************************/
    // Dataset 변경 이벤트
    ctrlPayerAddrHstrys.onDatasetChange = (obj, option) => {
        // 데이터 셋
        let dataList = ctrlPayerAddrHstrys.dataset;
        let empty = dataList.empty;

        let replacer = (str, dataItem) => str
            .replace(/{onclick}/gi, "pageObject['" + pageName + "'].ctrlPayerAddrHstrys.setCurrent('{data-index}');")

        let trs = empty ?
                      [ctrlPayerAddrHstrys.find("[name='tmpltNotFoundPayerHstry']").innerHTML]
                    : dataList.inStrings(ctrlPayerAddrHstrys.find("[name='tmpltPayerHstryRows']").innerHTML, replacer);

        // dataTables(그리드)에 자료 표시 td
        $(ctrlPayerAddrHstrys.find("[name='tbodyPayerHstryList']")).html(trs.join());
    };

    // 현재 선택 자료 변경 이벤트
    ctrlPayerAddrHstrys.onCurrentChange = (item) => {
        Apply.fromDataset.currentRow(ctrlPayerAddrHstrys.dataset, item, ctrlPayerAddrHstrys.find("[name='tbodyPayerHstryList']"));
    };

    return ctrlPayerAddrHstrys;
}
