[제품 가격 History]

두개 이상의 테이블을 컨트롤하는 예제를 처리하기 위해 기존 예제에 적합한

제품 가격이 변경될 때마다 그 내역을 관리할 수 있는 화면을 만들어 보기로 한다.



1. 작성순서

   1) 먼저 제품 가격 History를 저장할 수 있는 테이블을 생성하고 조회할 수 있는 화면을 만든다.

      (이 부분은 화면생성부분을 참고하기 바랍니다. 여기서는 대략적으로 설명할 예정입니다.)

      -Axboot 신규화면 만들기 1~3 참고       

       Axboot 신규화면 만들기 1 - DB생성 및 서버단 소스생성

       Axboot 신규화면 만들기 2 - 화면 소스 만들기

       Axboot 신규화면 만들기 3 - 정상적인 CRUD를 위한 JAVA소스 수정

   

   2) 이전 단계에서 만든 제품정보의 판매가격 변경 시 제품 가격 History테이블에 저장하는 로직을 추가한다.


2. 구현

   1) 제품 History테이블 생성      

CREATE TABLE `prdt_price_hist` (
	`id` INT(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
	`prdt_cd` VARCHAR(20) NOT NULL COMMENT '제품코드',
	`ch_date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '변경일시',
	`sales_price` INT(10) NOT NULL DEFAULT '0' COMMENT '판매가격',
	`CREATED_AT` DATETIME(6) NULL DEFAULT NULL,
	`CREATED_BY` VARCHAR(255) NULL DEFAULT NULL,
	`UPDATED_AT` DATETIME(6) NULL DEFAULT NULL,
	`UPDATED_BY` VARCHAR(255) NULL DEFAULT NULL,
	PRIMARY KEY (`id`)
)
COMMENT='제품가격History'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=4

  2) JAVA 코드 생성

      : http://localhost:8080/modelExtractor/db 접속 후 위에서 만들어진 테이블 클릭 후 기본 JAVA코드를 생성하자.
        (위 Axboot 신규화면 만들기 1 참조 - 코드생성 시 Package Name : prdt , Class Name : PrdtPriceHist 로 입력)    

  3) 제품 가격 History 화면소스 만들기

      : 간단히 기존에 만들었던 제품 정보 화면 소스를 복사해서 PrdtPriceHist.jsp와 PrdtPriceHist.js 로 

        이름을 변경한 후 일부만 수정하면 된다.

        (추가적으로 위 링크의 화면소스만들기 2를 참고하여 webapp하위의 axboot.config.js 에 js에서 호출할 

         약식이름과 full명의 mapping설정한다. - "prdtPriceHist":"/api/v1/prdtPriceHist")

        

     - PrdtPriceHist.jsp 수정     

<%@ page contentType="text/html; charset=UTF-8" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%@ taglib prefix="ax" tagdir="/WEB-INF/tags" %>


<ax:set key="system-common-code-version" value="1.0.0"/>

<ax:set key="title" value="${pageName}"/>

<ax:set key="page_desc" value="${pageRemark}"/>

<ax:set key="page_auto_height" value="true"/>


<ax:layout name="base">

    <jsp:attribute name="script">

        <ax:script-lang key="ax.script" var="LANG" />

        <ax:script-lang key="ax.admin" var="COL" />

        <script type="text/javascript" src="<c:url value='/assets/js/view/shopmng/prdtPriceHist.js' />"></script>

    </jsp:attribute>

    <jsp:body>


        <ax:page-buttons></ax:page-buttons>


        <div role="page-header">

            <ax:form name="searchView0">

                <ax:tbl clazz="ax-search-tbl" minWidth="500px">

                    <ax:tr>

                        <ax:td label='ax.admin.search' width="300px">

                            <ax:input type="text" name="filter" id="filter" clazz="form-control" placeholder="ax.admin.input.search"/>

                        </ax:td>

                    </ax:tr>

                </ax:tbl>

            </ax:form>

            <div class="H10"></div> 

        </div>


        <ax:split-layout name="ax1" orientation="horizontal">

            <ax:split-panel width="*" style="">


                <!-- 목록 -->

                <div class="ax-button-group" data-fit-height-aside="grid-view-01">

                    <div class="left">

                        <h2>

                            <i class="cqc-list"></i>

                            <!--<ax:lang id="ax.admin.commoncode.title"/>-->

                             제품 가격 변경 내역

                        </h2>

                    </div>

                    <div class="right">

                        <button type="button" class="btn btn-default" data-grid-view-01-btn="add"><i class="cqc-circle-with-plus"></i> <ax:lang id="ax.admin.add"/></button>

                        <button type="button" class="btn btn-default" data-grid-view-01-btn="delete"><i class="cqc-circle-with-minus"></i> <ax:lang id="ax.admin.delete"/></button>

                    </div>

                </div>

                <div data-ax5grid="grid-view-01" data-fit-height-content="grid-view-01" style="height: 300px;"></div>


            </ax:split-panel>

        </ax:split-layout>



    </jsp:body>

</ax:layout>


PrdtPriceHist.js 수정

var fnObj = {};

var ACTIONS = axboot.actionExtend(fnObj, {

    PAGE_SEARCH: function (caller, act, data) {

        axboot.ajax({

            type: "GET",

            url: ["prdtPriceHist"],

            data: caller.searchView.getData(),

            callback: function (res) {

                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: ["prdtPriceHist"],

            data: JSON.stringify(saveList),

            callback: function (res) {

                ACTIONS.dispatch(ACTIONS.PAGE_SEARCH);

                axToast.push(LANG("onsave"));

            }

        });

    },

    ITEM_ADD: function (caller, act, data) {

        caller.gridView01.addRow();

    },

    ITEM_DEL: function (caller, act, data) {

        caller.gridView01.delRow("selected");

    }

});


//기존 제품정보 복사 시 이 부분을 초기 셋팅으로만 변경해준다.

fnObj.pageStart = function () {

    this.pageButtonView.initView();

    this.searchView.initView();

    this.gridView01.initView();


    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

 */

fnObj.gridView01 = axboot.viewExtend(axboot.gridView, {

    initView: function () {

        var _this = this;

         

        this.target = axboot.gridBuilder({

            showRowSelector: true,

            frozenColumnIndex: 0,

            sortable: true,

            multipleSelect: true,

            target: $('[data-ax5grid="grid-view-01"]'), 

            columns: [

            {key: "id", label: "id", display: false},

            {key: "prdtCd", label: "제품코드", width: 100, align: "center", editor: "text"},  

                //내부적으로 update 일자를 관리하고 있지만, 그냥 넣어봤음.

                {key: "chDate", label: "변경일시", width: 150, align: "right", editor: "date"},  

                {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 = [];

        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}, "last");

    }

}); 


그 다음은 서버를 실행하여 프로그램 및 매뉴관리 화면에서 제품가격History를 추가해준다.


   


나머지 조회 및 Update(제품정보의 판매가격 수정시 호출)을 위한 JAVA소스 수정은 다음에 게시하고,

오늘은 여기까지만 하도록 하겠습니다. 



    

      

1. 설치목적

  - 이 블로그에서 postgresql DB를 설치하는 목적은 시각화 분석시스템인 superset (https://dodo-it.tistory.com/71)에서

   postgresql을 연결해 보기 위함이다.


2. 설치순서

   1) CentOS7에서는 yum으로 쉽게 설치된다. 

 # sudo yum install postgresql-server postgresql-contrib


   2) 초기 DB구성 설치

 # sudo postgresql-setup initdb


   3) 암호인증 허용하기 위한 설정 편집      

      - vi 에디터로 설정파일을 OPEN한다.

 # vi /var/lib/pgsql/data/pg_hba.conf

      - 열려진 에디터 창에서 Ctrl + G 를 눌러 한번에 제일 아래로 이동한다.(제일 아래쪽에 수정내용이 있다)

        그러면 아래 부분이 보인다. (수정할 부분은 빨간색 칠한부분이다)B


# "local" is for Unix domain socket connections only

local   all             all                                     md5

# IPv4 local connections:

host    all             all             127.0.0.1/32            ident

# IPv6 local connections:

host    all             all             ::1/128                 ident

# Allow replication connections from localhost, by a user with the

# replication privilege.

#local   replication     postgres                                peer

#host    replication     postgres        127.0.0.1/32            ident

#host    replication     postgres        ::1/128                 ident



     - 해당 위치로 커서 이동 후 i 를 눌러 편집모드에서 ident를 지우고 그 위치에 md5를 입력한다.

       또한 본인의 경우 virtualbox를 사용하여 virtualbox 아이피도 추가해준다.

       최종결과는 아래와 같은 모습이다.


# "local" is for Unix domain socket connections only

local   all             all                                     md5

# IPv4 local connections:

host    all             all             127.0.0.1/32            md5

# IPv6 local connections:

host    all             all             ::1/128                 md5

host    all             all             10.0.2.15/24            md5

# Allow replication connections from localhost, by a user with the

# replication privilege.

#local   replication     postgres                                peer

#host    replication     postgres        127.0.0.1/32            ident

#host    replication     postgres        ::1/128                 ident



   - vi 편집을 종료,저장하고 나가기 위해 esc 한번 ":"(콜론) 입력 wq 입력 enter 하면 완료된다.

 :wq


   - DB를 구동해본다.

 # sudo systemctl start postgresql

   

   - 시작시 자동으로 시작되도록 설정 

 # sudo systemctl enable postgresql

   

   - 외부접속가능하도록 방화벽을 열어준다.     

# firewall-cmd --permanent --zone=public --add-port=5432/tcp 

# firewall-cmd --reload


3. 기타 사용법

   1) 초기접속은 postgres 계정으로접속한다. (sudo -i -u postgres  --> password입력 --> psql 입력)

      * 초기 postgres 비번변경필요시 # sudo passwd postgres 명령어 사용


# sudo -i -u postgres

-bash-4.2$ psql

Password:

psql (9.2.24)

Type "help" for help.


postgres=#



  2) postgres=# 프롬프트에서 빠져나가기  

 postgres=# \q

      이후 아래 프롬프트 나오면 exit 입력후 엔터      

 -bash-4.2exit


  3) DB 생성하기(superset db를 생성하기로 함) 

 postgres=# CREATE DATABASE superset OWNER postgres;


  4) 생성된 DB List 보기 (역슬레쉬 + 소문자 엘)

 postgres=# \l

      * 결과        List of databases


   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges

-----------+----------+----------+-------------+-------------+-----------------------

 postgres  | postgres | UTF8     | ko_KR.UTF-8 | ko_KR.UTF-8 |

 sharkdb   | sharkdb  | UTF8     | en_US.UTF-8 | en_US.UTF-8 | sharkdb=CTc/sharkdb  +

           |          |          |             |             | =CTc/sharkdb

 superset  | postgres | UTF8     | ko_KR.UTF-8 | ko_KR.UTF-8 | =Tc/postgres         +

           |          |          |             |             | postgres=CTc/postgres+

           |          |          |             |             | soo=CTc/postgres

 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +

           |          |          |             |             | postgres=CTc/postgres

 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +

           |          |          |             |             | postgres=CTc/postgres

(5 rows)




어때요? 도움이 많이 되셨나요? ~~~~~~~


1. 에러상황

   : 평소 잘 되던 yum update 시도시 갑자기 아래와 같은 "No more mirrors to try"에러가 발생하면서

     update가 되지 않음. 

    (아래는 나의 패키지며, 사람마다 다르게 나올수 있음. 에러메시지에만 신경써주기 바람.) downloading packages:

  Error downloading packages:

    3:docker-ce-18.09.1-3.el7.x86_64: [Errno 256] No more mirrors to try.

    python36u-devel-3.6.7-1.ius.centos7.x86_64: [Errno 256] No more mirrors to try.

    tzdata-2018i-1.el7.noarch: [Errno 256] No more mirrors to try.

    containerd.io-1.2.2-3.el7.x86_64: [Errno 256] No more mirrors to try.

    python36u-libs-3.6.7-1.ius.centos7.x86_64: [Errno 256] No more mirrors to try.

    python36u-3.6.7-1.ius.centos7.x86_64: [Errno 256] No more mirrors to try.

    1:docker-ce-cli-18.09.1-3.el7.x86_64: [Errno 256] No more mirrors to try.

    tzdata-java-2018i-1.el7.noarch: [Errno 256] No more mirrors to try.

    python34-setuptools-39.2.0-1.el7.noarch: [Errno 256] No more mirrors to try.


2. 해결방법

  # yum clean all


  위와같이 yum을 clean해주고 다시 yum update 또는 install 시 아래와 같은 시원한 메시지를 볼 수 있다.


   Complete!



1. Apache superset이란?

   - 오픈소스 웹기반의 데이터 시각화 BI툴로 Airbnb에서 오픈소스(Apache2.0 라이센스)로 공개한 프로그램이다.

   - URL : https://superset.incubator.apache.org/

   - 상용 프로그램인 tableau의 대안으로 선택할 수 있다. 


2. 설치방법

   : superset 홈피에 보면 여러가지 설치방법이 나오는데 docker를 이용한 설치는 docker-build.sh 파일이 없어 

    에러가 발생한다. ==> 포기

    그래서 아래쪽에 pip로 설치해보니 정상적으로 작동되어 pip설치방법을 설명하도록 하겠음.

   1) 먼저 python3.6과 pip3 버전을 설치해야한다.

      : 설치방법은 기존글 참조 ==> CentOS 7 에 yum으로 python3.6 , pip3 설치하기 클릭


   2) superset 설치에 필요한 패키지를 설치한다.

      $ sudo yum upgrade python-setuptools 

      $ sudo yum install gcc gcc-c++ libffi-devel python-devel python-pip python-wheel openssl-devel libsasl2-devel openldap-devel   ==> sudo 부터 openldap-devel 까지 복사


   3) pip 로 superset 설치

      $ pip install superset 

  

   4) supserset admin 사용자 생성 (원하는대로 입력하면 됨.)

     : fabmanager create-admin --app superset      


     [root@localhost local]# fabmanager create-admin --app superset

     Username [admin]: dasdes                          ==> admin 사용자명

     User first name [admin]: dasdes                   ==> 사용자 이름

     User last name [user]: dasdes                      ==> 사용자 성

     Email [admin@fab.org]: dasdes@dasdes.com  ==> 사용자 이메일

     Password:                                               ==> 사용자비밀번호 (원하는대로)

     Repeat for confirmation:                            ==> 사용자비밀번호확인

     Recognized Database Authentications.          ==> 이하 생성성공메시지

     Admin User dasdes created.

 

※ 혹시 Was unable to import superset Error: cannot import name '_maybe_box_datetimelike' 에러가 나면

   원인은 pandas 버전 때문이라 기존버전을 지우고 0.23.X 버전으로 다운그레이드 하면 된다.

   -  pip uninstall pandas

   -  pip install pandas==0.23.4

   - 그런 다음 다시 fabmanager create-admin --app superset 하면 됨.



   5) superset db 초기화

     $ superset db upgrade 

 ※ 이 상황에서 에러가 나면 다음과 같은 에러가 나올거다.

sqlalchemy.exc.InvalidRequestError: Can't determine which FROM clause to join from, there are multiple FROMS which can join to this entity. Try adding an explicit ON clause to help resolve the ambiguity.

  그러면 pip 추가모듈을 설치해주고 다시 도전하면 된다.

  : pip install sqlalchemy==1.2.18


   6) 샘플데이터를 붙는다.

     $ superset load_examples 


   7) 초기 권한 자동셋팅

     $ superset init 

 

   8) centos7 에서 방화벽 port 8088을 열어준다.

     $ firewall-cmd --permanent --zone=public --add-port=8088/tcp 

     $ firewall-cmd --reload        ==> 방화벽 적용 


   9) 서버실행

    $ superset runserver -d


  10) 접속URL 

       http://localhost:8088

   그런다음 위에서 admin 계정만들때 사용했던 ID와 비밀번호를 입력하고 들어가면 됨.







 



어때요? 도움이 많이 되셨나요? ~~~~~~~


'오픈소스 > 기타 오픈소스' 카테고리의 다른 글

windows 10 docker 설치 및 필요 명령어  (0) 2019.12.09

 

◈ 설치순서

   1) ius repository 설치

      yum install -y https://centos7.iuscommunity.org/ius-release.rpm  링크깨짐
      $ yum install https://repo.ius.io/ius-release-el7.rpm https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm

 

     * 참고

        - 위 명령을 실행했을 때 아래와 같은 오류가 발생했을 경우에는 다운로드 후 yum install을 실행하면 된다.

       [root@localhost local]#  yum install -y https://centos7.iuscommunity.org/ius-release.rpm
       Loaded plugins: fastestmirror
       Cannot open: https://centos7.iuscommunity.org/ius-release.rpm. Skipping.
       Error: Nothing to do

        - $ cd /usr/local ==> /usr/local 로 이동(다운로드 받으려고)

        - $ wget https://centos7.iuscommunity.org/ius-release.rpm --no-check-certificate ==> ius-release.rpm 다운로드

        - $ yum install -y ius-release.rpm  ==> repository 설치

  ---------------------------------------------------------------------------------------------------------------------------------

        위에 wget으로 받은 후 yum install -y ius-release.rpm 했는데 ius-release.rpm 파일을 오픈할 수 없다는 둥...

        이런 메시지가 나오면 과감히 아래 링크에서 rpm을 따로 받아서 받은 rpm을 설치하세요.

         - 파일다운로드 : wget https://dl.iuscommunity.org/pub/ius/stable/CentOS/7/x86_64/ius-release-1.0-15.ius.centos7.noarch.rpm --no-check-certificate

         - Install 하기 :   yum install -y ius-release-1.0-15.ius.centos7.noarch.rpm

  ---------------------------------------------------------------------------------------------------------------------------------


2) 추가 패키지 설치

     $ yum install -y python36u python36u-devel python36u-libs python36u-pip

 

   3) pip명령어로 바로 pip3.6용 pip가 인식되도록 하기 위한 파일 다운로드 및 다운로드 파일 실행

     $ wget https://bootstrap.pypa.io/get-pip.py --no-check-certificate
     $ python3.6 get-pip.py      

     위 명령어를 실행하고 pip -V 을 실행시 아래와 같이 python 3.6 용 pip가 설치된것을 알 수 있다.

     pip 18.1 from /usr/lib/python3.6/site-packages/pip (python 3.6) 
     pip 21.1.2 from /usr/local/lib/python3.6/site-packages/pip (python 3.6)


   * 참고

     - python 만 쳐도 python3.6을 인식하게 하기 위해서는 Python3.7 설치하기(https://dodo-it.tistory.com/69)의

       제일 아래쪽 글을 참고하면 됨.

 

 

어때요? 도움이 많이 되셨나요? ~~~~~~~

 

+ Recent posts