Quick Start

다보리-컴포저블을 처음 사용하는 사용자에게 필요한 정보 안내 

1장. 설치하기

1장. 설치하기

Ownerkey 발급하기

Ownerkey란?

다보리앱은 main app과 guest app이 존재합니다. ownerKey를 공유하면 host app과 guest app간의 api 공유가 가능합니다.

OwnerKey 사용 예시

main app : 본점 A

guest app : 지점 B

지점 B는 본점 A의 api를 사용할 수 있습니다. 

1. 지점 B에서 회원리스트 조회시 본점 A의 회원리스트를 조회합니다.

2. 지점 B에서 신규회원 회원가입시 본점 A의 회원리스트로 추가됩니다. (회원리스트를 본점 A의 DB로만 사용할 경우)

3. 본점 A에서 새로운 상품추가시 본점 B의 삼품리스트에 추가됩니다. (상품리스트를 본점 A의 DB로만 사용할 경우)

OwnerKey 발급방법

Ownerkey를 사용하기 위해서는 guest app을 등록하여 OwnerKey를 발급받아야 합니다.

1. main app을 등록한 dabory 계정으로 로그인합니다.

2. guest app 등록을 위해서 My App 메뉴를 클릭합니다.

image.png

3. 좌측 메뉴에서 App Manager를 클릭합니다.

image.png

4. 등록한 app중 Owner key를 공유할 app을 클릭합니다.

image.png

5. GuestApp 탭을 클릭합니다.

image.png

6. a부터 c까지 입력 및 선택합니다.

image.png

ⓐ Guest App Name : Owner Key의 이름

ⓑ OwnerCode : Owner Key의 제한방식

ⓒ AppType : guest app의 type

7. Download .owner-key 버튼을 클릭하여 Owner key를 download 합니다.

8. MainApp 탭을 누른뒤 save 버튼을눌러 저장합니다. 

9. 생성된 .owner-key를 확인하고 frontend 소스코드를 open합니다.

10. .env 파일에 MAIN_API_OWNER_KEY 변수를 추가하고 생성된 owner key의 값을 넣어줍니다.

1장. 설치하기

env.dabory의 이해

env.dabory

env.dabory는 Laravel의 설정파일인 env 파일을 확장하여 API 서버와 db 연동을 위해 추가적으로 사용되는 연동용 설

정파일입니다.

 2. 서버와 db 연동과정

Frontend에서 백엔드 서버에 API를 요청할 때 env.dabory 파일을 참조합니다. 여기에서 api url은 요청을 보낼 API 서버를 결정하며, 특정 API를 호출하기 위해서는 해당 API 서버에서 발급한 GateToken이 필요합니다.

GateToken을 발급받기 위해서는 ClientId, ClientSecret, BeforeBase64의 값이 다보리 SSO에 등록된 DB 접속 정보와 일치해야 합니다. 즉, DB와의 연동이 인증되지 않으면 GateToken을 발급받을 수 없습니다. 이러한 변수들을 활용하여 지정된 API 서버에 요청하면, 해당 서버로부터 GateToken을 반환받아 이후 API 호출에 사용할 수 있습니다.

이처럼 GateToken을 중심으로 한 인증 절차를 통해 다보리 앱에서 main app과  guest app 간의 보안성을 유지하면서도 원활한 데이터 연동과 API 호출이 가능합니다.

 3. env.dabory의 주요 변수 설명
MAIN_API_URL :  연동할 API 서버의 URL과 포트 번호.
MAIN_API_CLIENT_ID : app별 고유한 API 클라이언트 ID.
MAIN_API_CLIENT_SECRET : app별 고유한 API 클라이언트 seceret키.
MAIN_API_BEFORE_BASE64 : app별 고유한 API 키 쌍을 Base64로 인코딩한 값.
1장. 설치하기

다보리 DB API 와 DB 연결 방법

해당사항은 먼저 2장 Restfull api의 구성 1번 메뉴얼을 숙지하시고 확인해주시기 바랍니다.

2장 1번 메뉴얼에서 언급한바와 같이 clientId와 beforebase64가 담긴 json type의 데이터를 통해 API 서버를 호출하게되면 api 서버에서 response로 gate token을 생성하여 반환합니다.

이 gate token은 .env.dabory 파일 생성시 입력된 db 접속정보가 암호화되어 있기 때문에 .env.dabory 파일에 설정이 되어 있고 App Manger에 등록되어 있다면 반환받은 gate-token을 통해 연동된 db api에 연결이 가능합니다.

1장. 설치하기

프론트엔드 설치하기 (Docker)

아래 단계에 따라 DC 프론트엔드 설치를 진행하세요:

1. DC 프론트엔드 설치본(Docker)을 다운로드하려면 제공된 다운로드 링크를 클릭하여 dc-demo-frontend-docker.tar.gz 파일을 다운로드합니다.

image.png

2. 다운로드가 완료되면 dc-demo-frontend-docker.tar.gz 파일을 DC를 설치할 디렉토리로 이동합니다. 예를 들어, 설치할 디렉토리를 /path/to/install로 정했다면, 다음 명령어를 사용해 파일을 이동할 수 있습니다.

mv ~/Downloads/dc-demo-frontend-docker.tar.gz /path/to/install

3.  설치 디렉토리로 이동한 후, tar 명령어를 사용해 압축을 해제합니다:

cd /path/to/install
tar -xzvf dc-demo-frontend-docker.tar.gz

압축 해제가 완료되면 demo 디렉토리가 생성됩니다.

image.png

4. 생성된 demo 디렉토리로 이동합니다:

cd demo

5. demo 디렉토리에는 다음과 같은 파일과 디렉토리가 포함되어 있습니다:

dbrerp : DC의 표준 ERP 소스 디렉토리입니다. ERP와 관련된 코드 및 리소스가 포함되어 있습니다.

docker-compose.yml : DC의 Docker 컨테이너 설정 파일입니다. 이 파일에는 컨테이너 구성, 포트 매핑, 볼륨 설정 등이 정의되어 있습니다.

php-docker : PHP 버전별 설정 및 Dockerfile이 포함된 디렉토리입니다. 프로젝트에서 사용할 PHP 환경을 설정하는 데 사용됩니다.

image.png

5. 설치가 완료되면 docker-compose.yml 파일을 사용해 Docker 컨테이너를 실행하여 DC 프론트엔드를 배포합니다. 실행 명령어는 다음과 같습니다:

docker-compose up -d

6. Docker 컨테이너가 실행되면, docker-compose.yml에 설정된 포트로 웹 브라우저를 통해 접속할 수 있습니다. 기본적으로 아래 주소를 사용합니다:

이제 DC 프론트엔드가 정상적으로 실행되며, 사용자 페이지와 관리자 페이지를 사용할 수 있습니다.

1장. 설치하기

웹서버/웹호스팅에 설치하는 방법

설치전 준비사항

0. dabory git server에 사용자를 등록합니다. (다보리 git server 바로가기)

image.png

1. .env  파일

2. .env.dabory 파일

3. php와 mariadb의 설치 

참고자료


웹서버/웹호스팅을 통한 설치방법

1. ssh을 통해 웹서버에 접근합니다.

2. 설치할 디렉토리를 생성하고 해당 디렉토리로 이동합니다.

3. 예제에서는 eyemsg 라는 테마폴더를 설치할 것이기 때문에 설치 경로에 아래와 같이 디렉토리를 구성하겠습니다.

각 디렉토리에 대한 설명은 아래에서 진행하겠습니다

4. 다보리 git 서버에서 mybin 레포지토리로 접속합니다. (mybin 바로가기)

5. HTTP url을 복사합니다.

image.png

6. 설치경로에서 git clone을 통해 mybin을 받아옵니다.

git clone http://git.daboryhost.com:10880/dabory/mybin

이제 다음과 같이 디렉토리들이 구성되었습니다.

image.png

5. eyemsg.daboryhost.com 디렉토리로 이동합니다.

cd eyemsg.daboryhost.com


6. 다보리 깃서버에 dbrerp 레포지토리로 접속합니다.

7. HTTP url을 복사해줍니다.

image.png

8. git clone 명령어를 통해 dbrerp 소스를 가져옵니다.

git clone http://git.daboryhost.com:10880/dabory/dbrerp.git

9. 아래 명령어를 통해 dbrerp의 하위 경로에 있는 모든 파일들을 eyemsg.daboryhost.com의 하위 경로로 이동시킵니다

mv dbrerp/* .


10. 사전에 준비해두었던 .env 파일과 .env.dabory 파일을 생성한뒤 내용을 붙여넣어줍니다.

이 부분이 숙지가 안되었다면 위 참고자료를 통해 env와 env.dabory 파일을 세팅해주세요.

vi .env
vi .env.dabory

11. dabory 디렉토리로 이동합니다.

cd dabory

12. 아래 링크를 클릭하여 theme 폴더를 설치한뒤 13번부터 진행해주시기 바랍니다.

테마폴더 설치하기

13. 다보리 git 서버의 vendor 레포지토리로 접속합니다.

14. git clone을 통해 vendor 소스를 가져옵니다.

git cloen http://git.daboryhost.com:10880/dabory/vendor.git

15. storage 관련 Update 예정

storage 누릭시 에러.png

16. eyemsg.daboryhost.com으로 접근하면 다음과 같이 설치가 완료되었습니다.

image.png


 참고자료
1장. 설치하기

더미테마(Dummy-Theme)설치 방법

.env 항목에서 DBR_THEME 변수에 erponly를 넣어줍니다. erponly는 테마는 /pro로 들어오는 경로로 들어오는 모든 트래픽을 user page로 redirection시켜주는 테마입니다.

/dabory/themes 디렉토리로 이동한뒤 git clone erponly url 명령어를 통해 theme 소스코드를 가져옵니다. 반드시 변수의 이름과 테마 폴더 이름을 변수 값으로 동기화해야 합니다. 디렉토리 관련해서는composer 디렉토리에 autoload_psr4 파일에 각 디렉토리들을 namespace로 구성하여 관리되고 있으니 참고하시기 바랍니다.

1장. 설치하기

운영테마(Production-Theme)설치방법

.env파일에서 ERP_THEME, PRO_THEME 변수를 찾아 확인합니다. 변수의 이름과 테마 폴더 이름을 변수 값으로 동기화해야 합니다. /themes/pro 폴더 임폴트 (수정 예정)

1장. 설치하기

Dabory Linux 서버 SSH를 통한 로그인 방법

사전준비

1. .ussh 파일 (ssh를 통해 편리하게 접근하기 위한 셸 스크립트 파일입니다.) 

2. dbr_list.txt 파일 (개발자가 직접 생성합니다.)

2-1. 아래 내용을 입력합니다. 

#서버코드                           #IP                            #설치지역
dbr02=13.124.2.254           #erics-and-kloxo

* dbr02서버는 예시입니다. 서버가 다를 수 있기 때문에 미리 확인하시고 진행하시기 바랍니다.

2-2. ussh 파일이 있는 디렉토리에서 dbr_list.txt 라는 이름으로 텍스트 파일을 생성하고 2-1의 내용을 붙여넣어줍니다.


ussh를 통한 서버 접근방법

1. ussh 파일이 준비되었다면 해당위치로 이동합니다.

2. 아래 명령어를 통해 서버에 접근합니다.

./ussh dbr02 eyemsg
# ./ussh 서버이름 계정명
1장. 설치하기

xampp를 통한 설치방법

설치전 준비사항

1. xampp 링크를 통해 xampp를 다운로드합니다.

2. More Downloads 클릭

image.png

3. 자신의 OS에 맞는 버전을 선택합니다. 예제는 window 버전으로 설치하겠습니다.

image.png

4. 7.3 ~8.0 까지의 php 버전을 호환하는 버전을 설치합니다. 예제는 7.3.33버전을 설치하겠습니다.

image.png

5. 포터블 버전이 아닌 일반 버전의 installer.exe를 클릭하여 설치합니다.

image.png

6. 다운로드된 설치파일을 클릭하여 설치를 진행합니다.

image.png

7. env/env.dabory 파일 세팅


xampp를 통한 설치방법

window 기준으로 설치를 진행한 예제입니다.

1. XAMPP Control Pannel을 관리자권한으로 실행합니다.

2. xampp는 기본 80포트 / 443 포트로 실행됩니다. 포트 충돌이 일어난다면 httpd.conf / httpd-ssl.conf / Config에서 포트를 변경해줍니다.

image.png

image.png

image.png

3. Apache 서버를 실행합니다. 만약 실행이 안된다면 아래와 같이 화살표버튼을 클릭하여 Apache를 재설치합니다.

image.png

4. 서버가 실행되었다면 터미널을 열어줍니다.

image.png5. 

5. 아래 명령어를 통해  다보리 컴포터블의 dbrerp를 받아옵니다.

cd htdocs
git clone http://git.daboryhost.com:10880/dabory/dbrerp.git

6. 아래 명령어를 통해 필요한 파일들을 받아옵니다.

# vendor
cd dbrerp
git clone http://git.daboryhost.com:10880/dabory/vendor.git

# erponly
cd dabory
mkdir themes
git clone http://git.daboryhost.com:10880/dbrerp-themes/erponly.git

7. 이제 localhost:port번호로 접근합니다.

8. 만약 특정 에러가 발생한다면 

- env 혹은 env.dabory 파일 확인

- vendor 혹은 storage 파일 확인

- xampp apache 서버의 설정파일 확인 (public 경로설정)

- 테마폴더의 존재 및 위치 확인

위 사항들을 체크해보시기 바랍니다.

2장. Restfull API 구성

2장. Restfull API 구성

Gate Token 개념

인증 & OAuth 2.0

인증이란 특정 사용자가 본인임을 확인하는 절차를 의미합니다. 일반적으로 아이디와 비밀번호가 일치하면 해당 사용자가 본인이라고 판단할 수 있습니다. 예를 들어, 다보리에 로그인할 때 다보리 계정의 아이디와 비밀번호를 입력하여 본인 여부를 확인하는 방식입니다.

하지만,  다보리 오픈API를 활용하여 개발한 애플리케이션에서 사용자가 다보리 계정의 아이디와 비밀번호를 직접 입력하도록 하면 보안상의 위험이 발생할 수 있습니다. 이를 방지하기 위해, 사용자가 제 삼자가 만든 애플리케이션이 아닌 **공식 인증 서비스(예: 네이버 로그인 페이지)**에서 직접 인증을 진행하고, 그 결과를 애플리케이션에 전달하는 방식이 필요합니다.

이러한 인증 방식을 체계적으로 정리한 표준이 OAuth이며, 다보리 오픈API는 OAuth 2.0 프로토콜을 적용하여 안전한 인증 서비스를 제공하고 있습니다.

Gate Token

dabory sso(OAuth2 기반)을 통해 사용자가 인증되면 이후 GateToken을 사용하여 API 서버와 DB에 연동할 수 있습니다. GateToken 자체는 사용자 인증을 담당하지 않고, 로그인 이후 인증된 사용자의 권한을 기반으로 API 및 DB 접근을 관리하는 역할을 합니다.

다보리 Frontend에서는 로그인 체크 이전에 session에 저장된 gatetoken을 check합니다. 만약 gatetoken이 존재하지 않는다면 main_api server로 부터 gatetoken을 발급받습니다. 즉 gatetoken은 app등록시 입력된 db 접근정보와 api server와의 정상적인 연동 권한을 갖췄는지 체크하기 위해 사용되는 암호화된 토큰입니다.

api 서버로부터 반환받은 GateToken은 프론트엔드 session에 저장됩니다. 이 session은 권한이 필요한 모든 프론트엔드 요청의 header에 포함됩니다.

2장. Restfull API 구성

다보리 API 설계의 기본 지식

HTTP Method 및 보안성:

DaborySSO 및 환경 변수:

GateToken:

이러한 설계 원칙을 준수하여 안전하고 효율적인 API 시스템을 구축할 수 있습니다.

3장. Frontend 기반 구조

3장. Frontend 기반 구조

.env 의 구조

.env 파일 세팅 예제

 참고자료

Lavavel .env 기본 메뉴얼(https://laravel.kr/docs/5.7/configuration)

Lavavel .env Example(https://zetawiki.com/wiki/라라벨_.env,_.env.example)

# [Dabory]
ERP_THEMES=테마명입력 (해당 테마 설치후 입력)
LOCALE_SEQUENCE=다국어 사용 목록
APP_MOBILE_NO=아직 사용X
TAG_LINE=아직 사용X
CDN_TYPE=미디어 CDN (aws-s3 or local)
MEDIA_URL=미디어 base url 지정(미디어가 local or a3)
FAVICON_PATH=파비콘 파일 path
IS_SKIP_DBUPDATE=DBUPDATE 스킵 or 사용
IS_ON_MEMBER_SIGNUP=아직 사용X

## [MetaMask]
CHAIN_ID=0xE67B
CHAIN_NAME='Dang Smart Chain'
RPC_URLS=http://3.38.62.211:8545
NATIVE_CURRENCY_NAME=DGT
NATIVE_CURRENCY_SYMBOL=DGT
NATIVE_CURRENCY_DECIMALS=18
BLOCK_EXPLORER_URLS=https://explorer-staging.dangnn.co.kr

# [Strong Api]
STRGO_API_URL= strong api 연동시 입력합니다.

### [asset & cache]
BROWSER_CACHE=브라우저 캐시사용  (개발단계에서 false)
CSSJS_URL=local or asset url 입력          (개발단계에서 local)

### [Printer]
REPORT_SERVER_URL=프린터 서버 base url

### [Laravel]
APP_NAME=앱 이름
APP_ENV=.env 기본 메뉴얼 참고
APP_KEY=base64:.env 기본 메뉴얼 참고
APP_DEBUG=.env 기본 메뉴얼 참고
APP_URL=앱 url
LOG_CHANNEL=stack
LOG_LEVEL=debug
DB_CONNECTION=사용x
DB_HOST=사용x
DB_PORT=사용x
DB_DATABASE=사용x
DB_USERNAME=사용x
DB_PASSWORD=사용x

BROADCAST_DRIVER=사용x
CACHE_DRIVER=사용x
FILESYSTEM_DRIVER=사용x
QUEUE_CONNECTION=사용x
SESSION_DRIVER=사용x
SESSION_LIFETIME=사용x
MEMCACHED_HOST=사용x
REDIS_HOST=사용x
REDIS_PASSWORD=사용x
REDIS_PORT=사용x

MAIL_MAILER=.env 기본 메뉴얼 참고
MAIL_HOST=.env 기본 메뉴얼 참고
MAIL_PORT=.env 기본 메뉴얼 참고
MAIL_USERNAME=.env 기본 메뉴얼 참고
MAIL_PASSWORD=.env 기본 메뉴얼 참고
MAIL_ENCRYPTION=.env 기본 메뉴얼 참고
MAIL_FROM_ADDRESS=.env 기본 메뉴얼 참고
MAIL_FROM_NAME=.env 기본 메뉴얼 참고

AWS_ACCESS_KEY_ID=.env 기본 메뉴얼 참고
AWS_SECRET_ACCESS_KEY=.env 기본 메뉴얼 참고
AWS_DEFAULT_REGION=.env 기본 메뉴얼 참고
AWS_BUCKET=.env 기본 메뉴얼 참고
AWS_USE_PATH_STYLE_ENDPOINT=.env 기본 메뉴얼 참고

PUSHER_APP_ID=사용x
PUSHER_APP_KEY=사용x
PUSHER_APP_SECRET=사용x
PUSHER_APP_CLUSTER=사용x

MIX_PUSHER_APP_KEY=사용x
MIX_PUSHER_APP_CLUSTER=사용x

ANALYTICS_UA_ID=
ANALYTICS_VIEW_ID=

ANALYTICS_G_ID=
ANALYTICS_PROPERTY_ID=

3장. Frontend 기반 구조

.env.dabory 와 Gate Token

제 2장 Rest Api의 구성(https://manual.dabory.com/books/frontend-tutorial/chapter/restfull-api)에서 Gate Token에 대한 내용을 다뤘으니 참조하시고 해당 장을 숙지하시면 이해하는데 도움이 됩니다.

 참고사항

- [ KeyPair/PublicKey 등을 를 생성하는 일반적인 PHP Code]
https://www.php.net/manual/en/function.sodium-crypto-box-seal.php
- [Sodium 사용 Ajax 제공 (260~262 Lines)]
http://git.daboryhost.com:10880/dabory/dbrerp/src/master/routes/web.php
- [ DB 정보 암호화 how to use it in PHP (254~263 Lines)](http://git.daboryhost.com:10880/dabory/dbrerp/src/master/resources/views/front/dabory/pro/my-app/popup/popup-form1/form-a/client-app-form.blade.php).
dabory Gate Token(DGT)

[DGT 생성과정 시작]

[Main Request]

[DCS 생성과정 시작]

[요청 끝]

3장. Frontend 기반 구조

다보리 Frontend 폴더 구조

Frontend 구조(표준)

image.png

 주요 디렉토리 설명

dabory 디렉토리는 다보리의 중요한 구성 요소로, 관리자 및 ERP 사용자 메뉴를 커스터마이징 할 수 있도록 설정하는 디렉토리입니다.

para : 이 디렉토리에는 관리자가 설정할 수 있는 다양한 ERP 사용자 메뉴시스템 설정 파일들이 JSON 형식으로 저장됩니다. 이러한 파일들을 통해 ERP 시스템의 메뉴 구성, 권한 관리, 기타 관리 설정 등을 유동적으로 수정이 가능합니다.

image.png


themes :  다보리의 프론트엔드 테마를 커스터마이징 할 수 있는 디렉토리입니다. 각 사이트별로 제공되는 테마를 개별적으로 수정하거나 새로 구축할 수 있습니다. 각 테마의 템플릿, 스타일, JavaScript, 리소스 등을 이곳에서 관리하며, 이를 통해 각 업체나 고객에 맞춤화된 프론트엔드 페이지를 구현할 수 있습니다.

image.png

public  : public 폴더는 웹 애플리케이션의 진입점이자 외부에서 접근 가능한 모든 파일들이 위치하는 폴더입니다. 다보리 프론트엔드에서 테마 요소에 실제로 접근할 수 있는 디렉토리입니다.  para- -/dabory 폴더와 themes 폴더는 위 dabory 폴더와 동일한 구조로 이루어져 있습니다. dabory 폴더에서는 이미지나 리소스에 접근이 불가능하기 때문에 public 폴더에서 심볼릭 링크(symbolic link)를 생성하여 사용합니다.

image.png

*심볼릭 링크 (Symbolic Link)
dabory 폴더 안에서는 이미지나 리소스에 직접 접근할 수 없기 때문에, public 폴더에 심볼릭 링크(symbolic link)를 생성하여 dabory 내부의 이미지 및 리소스를 외부에서 접근 가능하도록 연결합니다. 이를 통해 public 폴더를 경유하여 dabory 폴더 내의 리소스를 웹 애플리케이션에서 사용할 수 있습니다.

 추가설명

다보리의 프론트엔드 구조는 매우 유연하고 확장 가능하도록 설계되어 있으며, dabory 폴더를 통해 관리자는 ERP 시스템과 테마를 자유롭게 커스터마이징할 수 있습니다. 또한 public 폴더는 웹 애플리케이션의 외부 리소스를 제공하는 중심 역할을 하며, 필요한 경우 심볼릭 링크를 통해 리소스를 접근할 수 있습니다.

3장. Frontend 기반 구조

다보리 Theme 폴더의 구조

Theme 폴더의 구조

 pro (Service Page)

 pro 디렉토리는 기업이나 조직 외부에 있는 게스트 및 고객을 대상으로 하는 프론트 오피스 페이지입니다. 표준 ERP와는 별도로 pro디렉토리에서만 사용되는 독립적인 클래스와 로직이 app, resources, routes 등의 디렉토리에 구분되어 존재하며, 표준 erp와는 독립적으로 작동합니다.

- pro 디렉토리 예시

image.png

app

이 디렉토리에는 각 기능별로 정의된 Controller가 있으며, 기능에 따라 명명 규칙을 따릅니다. Controller는 외부 API 호출과 반환된 값들을 view 페이지에 전송하는 역할을 합니다.

para

pro 디렉토리에서 사용되는 view 페이지의 구성요소, api에 대한 명시 등등 pro 페이지를 구성하는 전반적인 요소들이 파라메터로 구성되어 있습니다.

resources

pro 디렉토리에서 작동하는 정적인 요소들이 포함된 디렉토리입니다. 보통 Controller와 동일한 네이밍 규칙을 따르며, Controller에서 받아온 데이터를 활용해 view 페이지가 구성됩니다. 스크립트 코드와 css, image 등이 포함되어 있습니다.

 erp (Back Office)

ERP 디렉토리는 기업이나 조직 내 직원 및 관리자를 위한 백오피스 페이지입니다. 보통 erp의 표준 erp로 작동하지만 pro  페이지 없이 erp만 사용할 수 있는 erponly 테마의 경우 pro에 설정된 route  경로로 들어오는 모든 route를 erp 경로로 redirect하여 표준 erp에서만 작동하는 구조로 간결하게 구성되어 있습니다.

- erp 디렉토리 예시

image.png

 

4장. Parameter 기반 개발

4장. Parameter 기반 개발

다보리 파라메터의 개념

다보리 파라메터

다보리 컴포저블에서는 모든 구성요소들을 파라메터를 통해 관리, 구성하고 있습니다. 다보리 파라메터를 통해 다음과 같이 구현이 가능합니다. 몇가지 예시를 소개합니다.

고객입력창 구현을 위한 파라메터

{
    "General": {
        "Title": "고객입력",
        "PickApi": "slip-form-book",
        "ActApi": "company-act"
    },


    "QueryVars": {
        "QueryName": "pos/customer"
    },
  
    "SelectButtonOptions": [
        {
            "Value": "new",
            "Caption": "새 레코드"
        },
        {
            "Value": "del",
            "Caption": "레코드 삭제"
        },
        {
            "Value": "copy",
            "Caption": "레코드 복사"
        },
        {
            "Value": "rpt-print-pdf",
            "Caption": "연말정산(pdf)"
        },
        {
            "Value": "rpt-print-paper",
            "Caption": "연말정산(종이)"
        }
    ],


    "//FormVars": "ListVars[0]-Caption",
    "FormVars": [
        {
            "SaveButton": "저장",
            "CompanyName": "고객번호(자동채번)*",
            "MainContact": "고객명* / 성별",
            "MobileNo": "휴대전화*",
            "TelNo": "유선전화",
            "BirthDate": "생년월일*",
            "Email": "이메일*",
            "CgroupId": "고객분류*",
            "ZipCode": "우편번호*",
            "Addr1": "주소*",
            "Addr2": "주소상세",
            "IsOkText": "문자발송",
            "IsOkEmail": "이메일발송",
            "IsOkDm": "디엠발송",
            "Remarks": "관리자메모",
            "UserCredit": "적립금",
            "CurrUserCredit": "현재 적립금",
            "AvailUserCredit": "가용 적립금(적용-버튼)"
        },
        {
            "SaveButton": "",
            "CompanyName": "left",
            "MainContact": "left",
            "MobileNo": "left",
            "TelNo": "left",
            "BirthDate": "left",
            "Email": "left",
            "CgroupId": "left",
            "ZipCode": "left",
            "Addr1": "left",
            "Addr2": "left",
            "IsOkText": "left",
            "IsOkEmail": "left",
            "IsOkDm": "left",
            "Remarks": "left",
            "UserCredit": "left",
            "CurrUserCredit": "left",
            "AvailUserCredit": "left"
        },
        {
            "SaveButton": "0",
            "CompanyName": "20",
            "MainContact": "20",
            "MobileNo": "20",
            "TelNo": "20",
            "BirthDate": "20",
            "Email": "20",
            "CgroupId": "20",
            "ZipCode": "20",
            "Addr1": "20",
            "Addr2": "100",
            "IsOkText": "20",
            "IsOkEmail": "20",
            "IsOkDm": "20",
            "Remarks": "",
            "UserCredit": "20",
            "CurrUserCredit": "20",
            "AvailUserCredit": "20"
        },
        {
            "SaveButton": "",
            "CompanyName": "required",
            "MainContact": "required",
            "MobileNo": "required",
            "TelNo": "",
            "BirthDate": "required",
            "Email": "required",
            "CgroupId": "required",
            "ZipCode": "required",
            "Addr1": "required",
            "Addr2": "",
            "IsOkText": "",
            "IsOkEmail": "",
            "IsOkDm": "",
            "Remarks": "",
            "UserCredit": "",
            "CurrUserCredit": "",
            "AvailUserCredit": ""
        }
    ]
}
['General']['Title'] : view page에서 페이지의 title로 사용
['General']['PickApi'] : view page 혹은 비지니스 로직에서 api 서버로 특정 pick-api를 호출 가능
['QueryVars']['QueryName'] : api 서버에 특정 api 호출시 백엔드서버에 요청할 query를 지정
let response = await call_slip_form_book(formA['General']['PickApi'], formA['QueryVars']['QueryName'],
                customer_name, {!! json_encode($menuCode) !!});
['SelectButtonOptions']['Value'] : view page에서 버튼으로 구현할 경우 버튼의  javascript에서 value를 통해 특정 이벤트를 발생시키거나 함수로 구현
$('.customer-eyetest-act').on('click', function () {
                // console.log($(this).data('value'))
                switch( $(this).data('value') ) {
                    case 'save': customer_eyetest_btn_act_save(); break;
                    case 'new': atype_custom_btn_act_new(); break;
                    case 'copy': customer_eyetest_btn_act_copy(); break;
                    case 'del': customer_eyetest_btn_act_del(); break;
                    case 'rpt-print-pdf': Stype.rpt_print('#customer-eyetest .frm'); break;
                    case 'rpt-print-paper': print_test(); break;
                }
            });
['SelectButtonOptions']['Caption'] : button의 이름 등 text형태로  다양하게 활용가능 
<ul class="dropdown-menu dropdown-menu-right" role="menu">
  @foreach ($formA['SelectButtonOptions'] as $key => $btn)
    <li class="dropdown-item">`{{ $btn['Caption'] }}`</li>    
   @endforeach
</ul>
['FormVars'][0] : label,  input등의 title
['FormVars'][1] : label,  input css 정렬
['FormVars'][2] : label,  input등의 maxlength 설정

['FormVars'][2] : label,  input등의 필수요소 설정

<div class="form-group w-100 d-flex flex-column" style="width: 143px">
  <label class="m-0 overflow-hidden text-nowrap">{{ $formA['FormVars']['Title']['CompanyName'] }}</label>
  <div class="col-12 d-flex p-0">
  <input type="text" class="auto-slip-no-txt rounded w-100 radius-l0" autocomplete="off" disabled
         maxlength="{{ $formA['FormVars']['MaxLength']['CompanyName'] }}"
         {{ $formA['FormVars']['Required']['CompanyName'] }}>
  </div>
</div>

품목찾기 모달창 구현을 위한 파라메터

{
    "General": {
        "Title": "품목 찾기",
        "PageApi": "item-search-page"
    },


    "QueryVars": {
        "QueryName": "master/item",
        "FilterName": "is_material",
        "FilterValue": "0"
    },


    "//FormVars": "ListVars[0]-Caption, ListVars[0]-format",
    "FormVars": [
        {
            "SelectButton": "",
            "ItemCode": "품목코드",
            "ItemName": "품명",
            "SubName": "서브명",
            "CountUnit": "수량단위",
            "CurrStockQty": "현재고",
            "PurchPrc": "표준매입가",
            "SalesPrc": "표준매출가",
            "ItemDesc": "품목설명",
            "FilterOption": "검색조건",
            "SimpleOption": "상태별 검색"
        },
        {
            "SelectButton": "left",
            "ItemCode": "left",
            "ItemName": "left",
            "SubName": "left",
            "CountUnit": "left",
            "CurrStockQty": "decimal('stock_qty')",
            "PurchPrc": "decimal('purch_prc')",
            "SalesPrc": "decimal('sales_prc')",
            "ItemDesc": "left",
            "FilterOption": "left",
            "SimpleOption": "left"
        }
    ],



    "// OrderByOptions": "OrderBy Options//첫번째 Value가 Default, 필수(Required)",
    "OrderByOptions": [
        {
            "Value": "item_code asc",
            "Caption": "품목코드 정렬"
        },
        {
            "Value": "item_name asc",
            "Caption": "품명 정렬"
        },
        {
            "Value": "sub_name asc",
            "Caption": "서브명 정렬"
        }
    ],


    "FilterSelectOptions": [
        {
            "Value": "",
            "Caption": "=검색 조건="
        },
        {
            "Value": "mx.item_code",
            "Caption": "품목코드"
        },
        {
            "Value": "mx.item_name",
            "Caption": "품명"
        },
        {
            "Value": "mx.sub_name",
            "Caption": "서브명"
        }
    ],


    "SimpleSelectOptions": [
        {
            "Value": "mx.expose_type='0'",
            "Caption": "온라인 게시"
        },
        {
            "Value": "mx.expose_type='1'",
            "Caption": "온라인 누락"
        },
        {
            "Value": "mx.expose_type='2'",
            "Caption": "쿠폰신청 상품"
        },
        {
            "Value": "",
            "Caption": "전체"
        }
    ],


    "// ListVars": "ListVars[0]-caption, ListVars[1]-size(%), ListVars[2]-align",
    "// Price": "Prices show with comma and truncate numbers under decimal !!",
    "ListVars": [
        {
            "$Radio": "$Radio",
            "$Check": "",
            "No": "번호",
            "ItemCode": "품목 코드",
            "ItemName": "품명",
            "SubName": "서브명",
            "IgroupName": "품목구분",
            "SalesPrc": "매출가",
            "PurchPrc": "매입가",
            "MoreInfo": "추가정보"
        },
        {
            "$Radio": "3",
            "$Check": "3",
            "No": "10",
            "ItemCode": "15",
            "ItemName": "12",
            "SubName": "12",
            "IgroupName": "13",
            "SalesPrc": "10",
            "PurchPrc": "10",
            "MoreInfo": "10"
        },
        {
            "$Radio": "center",
            "$Check": "center",
            "No": "center",
            "ItemCode": "left",
            "ItemName": "left",
            "SubName": "left",
            "IgroupName": "left",
            "SalesPrc": "decimal('sales_qty')",
            "PurchPrc": "decimal('purch_prc')",
            "MoreInfo": "left"
        }
    ]
}

4장. Parameter 기반 개발

ListType1 파라메터의 이해와 사용법

ListType1

ListType1은 다보리 파라메터 중 가장 많이 사용되는 파라메터입니다. 주로 필터링을 통해 데이터를 List 형식으로 출력합니다.

 ListType1 예시

1. view page

image.png

상단 필터링을 통해 데이터가 걸러지고 하단 박스에 결과 데이터들을 출력합니다.

2. para

{
    "//list-type-1": "simple and plain list by query of table join",

    "General": {
        "Title": "상품 리스트",
        "PageApi": "list-type1-page",
        "ActApi": "list-type1-upload"
    },

    "QueryVars": {
        "QueryName": "master/item-fngoods-input",
        "FilterName": "",
        "FilterValue": "",
        "FilterDate": ""
    },

    "PrintVars": {
        "QueryName": "federated/crystal/master/item-fngoods-input",
        "ReportPath": "standard/master/item-fngoods-input.rpt",
        "ExportFmt": "PDF",
        "ServerPrinter": "",
        "CustomCode": "item-fngoods-input"
    },

    "HeadSelectOptions": [
        {
            "Value": "clear-all-filter",
            "Caption": "초기화"
        },
        {
            "Value": "barcode-print",
            "Caption": "바코드 인쇄"
        },
        {
            "Value": "rpt-print",
            "Caption": "빠른 표준 보고서"
        },
        {
            "Value": "rpt-custom",
            "Caption": "커스텀 보고서"
        }
    ],

    "//FormVars": "FormVars[0]-caption, FormVars[1]-searchPopup",
    "FormVars": [
        {
            "ListButton": "조회",
            "DateRange": "",
            "DateNavi": "일자방향(오늘)",
            "Date": "",
            "From": "부터",
            "To": "까지",
            "FirstRange": "",
            "SecondRange": "",
            "ThirdRange": "",
            "FourthRange": "",
            "AddTotalLine": "",
            "SelectPopup": "",
            "MultiPopup": "",
            "ChartPopup": "",
            "DownloadList": "",
            "ShowOnlyClosed": "",
            "Balance": "",
            "OrderBy": "표시 순서",
            "FilterOption": "검색조건",
            "SimpleOption": "상태별 검색"
        }
    ],

    "FilterSelectOptions": [
        {
            "Value": "",
            "Caption": "=검색 조건="
        },
        {
            "Value": "mx.item_code",
            "Caption": "품목코드"
        },
        {
            "Value": "mx.item_name",
            "Caption": "품명"
        },
        {
            "Value": "mx.sub_name",
            "Caption": "서브명"
        }
    ],

    "SimpleSelectOptions": [
        {
            "Value": "mx.expose_type='0'",
            "Caption": "온라인 게시"
        },
        {
            "Value": "mx.expose_type='1'",
            "Caption": "온라인 누락"
        },
        {
            "Value": "",
            "Caption": "전체"
        }
    ],

    "//ListType1RangeVars": "[0]-filter, [1]-component, [2]-parameter",
    "ListType1RangeVars": [
        {
            "FirstRange": "",
            "SecondRange": "",
            "ThirdRange": "",
            "FourthRange": ""
        },
        {
            "FirstRange": "",
            "SecondRange": "",
            "ThirdRange": "",
            "FourthRange": ""
        },
        {
            "FirstRange": "",
            "SecondRange": "",
            "ThirdRange": "",
            "FourthRange": ""
        }
    ],

    "// DateRangeOptions": "월:현재월의 1~30, 분기: 현재분기의 첫째월 1일 ~ 마지막월의 말일, 반기/년 동일한 컨셉,전체:1990~3000",
    "DateRangeOptions": [
    ],

    "DateNaviOptions": [
        {
            "Value": "day",
            "Caption": "일"
        },
        {
            "Value": "week",
            "Caption": "주"
        },
        {
            "Value": "month",
            "Caption": "월"
        },
        {
            "Value": "quarterly",
            "Caption": "분기"
        },
        {
            "Value": "year",
            "Caption": "년"
        },
        {
            "Value": "all",
            "Caption": "전체"
        }
    ],

    "SelectPopupOptions": [
        {
            "Caption": "상품 입력/수정/삭제",
            "Component": "popup-form1.form-a.item-form",
            "Parameter": "/popup/popup-form1/form-a/item"
        }
    ],
    "SelectLinkedPopupOptions":[
        {
            "Caption": "상품 입력/수정/삭제",
            "Linked":"/dabory/erp/master-data/item-tabbed?bpa=eyJtZW51X25hbWUiOiJ0ZXN0LWl0ZW0tdGFiYmVkIiwibWVudV9jb2RlIjoiOTMwMDAwIiwiZGlzYWJsZV9sX21lbnUiOiIwIiwiZW5hYmxlX3JfbWVudSI6IjAiLCJwZXJtaXNzaW9uIjp7ImlzX215bWVudSI6IjAiLCJpc19saXN0IjoiMSIsImlzX3JlYWQiOiIxIiwiaXNfY3JlYXRlIjoiMSIsImlzX3VwZGF0ZSI6IjEiLCJpc19kZWxldGUiOiIxIiwiaXNfbmV3dGFiIjoiMCJ9LCJwYWdlX3VyaSI6IlwvZGFib3J5XC9lcnBcL21hc3Rlci1kYXRhXC9pdGVtLXRhYmJlZCIsInBhcmFfbmFtZSI6IlwvZm9ybVwvZm9ybS1hXC9pdGVtLXRhYmJlZCIsInRoZW1lX2RpciI6IiIsIm1haW5fYXBwX2lkIjowLCJndWVzdF9hcHBfaWQiOjAsImN1c3RvbV92YXIiOiIifQ=="
        }
    ],

    "// OrderByOptions": "OrderBy Options//첫번째 Value가 Default",
    "OrderByOptions": [
        {
            "Value": "mx.item_code asc",
            "Caption": "상품 코드 순서"
        },
        {
            "Value": "mx.item_code desc",
            "Caption": "상품 코드 역순"
        }
    ],

    "//BalanceOptions": "Show OnlyBalaceRemained or All",
    "BalanceOptions": [
        {
            "Value": "",
            "Caption": "전체 보기"
        },
        {
            "Value": "c10 > 0",
            "Caption": "잔량있는 것만"
        }
    ],

    "DisplayVars": {
        "IsListFirst" : true,
        "IsExcelColumn" : false,
        "InitLines" : 15,
        "HeadHeight": "130",
        "IsC1Popup": "1",
        "BodyHeight": "680"
    },

    "// ListVars": "ListVars[0]-caption, ListVars[1]-size(px), ListVars[2]-align->right(number) left(left)",
    "ListVars": [
        {
            "$Radio": "$Radio",
            "$Check": "$Check",
            "No": "번호",
            "C1": "품목코드",
            "C2": "품명",
            "C3": "서브명",
            "C4": "품목구분",
            "C5": "매출가",
            "C6": "매입가",
            "C7": "단위",
            "C8": "공급사(입점사)",
            "C9": "온라인누락"
        },
        {
            "$Radio": "3",
            "$Check": "3",
            "No": "5",
            "C1": "12",
            "C2": "25",
            "C3": "12",
            "C4": "8",
            "C5": "6",
            "C6": "6",
            "C7": "4",
            "C8": "8",
            "C9": "8"
        },
        {
            "$Radio": "center",
            "$Check": "center",
            "No": "center",
            "C1": "left",
            "C2": "left",
            "C3": "left",
            "C4": "left",
            "C5": "decimal('sales_prc')",
            "C6": "decimal('purch_prc')",
            "C7": "center",
            "C8": "center",
            "C9": "check"
        }
    ]
}

ListType1 추가방법

새로운 ListType1을 추가하는 방법입니다.

1. 웹상에서 /dabory/erp 경로로 이동합니다.

image.png 

2. 좌측 Left menu에서 슈퍼유저 메뉴 - 시스템 관리(주의)메뉴를 찾습니다.

image.png

3. 위 메뉴들은 모두 ListType1을 통해 구현된 메뉴들을 불러오는 리스트메뉴입니다. 사용자 메뉴 불러오기를 예시로 새로운 ListType1을 추가하겠습니다.

4. 사용자 메뉴 불러오기 메뉴 진입시 아래와 같이 리스트가 출력됩니다. C5:파라메터명을 확인합니다.

image.png

5. 예제에서는 회원 앱 권한 메뉴를 복사하여 새로운 ListType1을 생성하겠습니다. 회원 앱 권한의 파라메터명은 /form/form-b/member-menu-perm입니다.

6. dbrerp 소스상에서 para 파일들이 들어있는 dabory/para 디렉토리에서 /list/list-type1/downupload/ 경로에서 

image.png

7. member-menu-perm 파일을 복사하여 새로운 name으로 수정합니다. member-menu-perm_new.json로 하겠습니다.

image.png

image.png

8. 이제 weberp-queries을 편집기에서 열고 

해당 페이지 메뉴에서 보여주고 싶은 데이터, 엑셀 다운로드 데이터를 C1~C20까지 순서대로 넣습니다.

image.png

쿼리 작성이 끝났다면 방금 만들어줬던 쿼리와 동일하게 새로 만들어준 json 파일의 파라메터도 수정해줍니다.

image.png

마지막으로 쿼리를 실행하기 위래 QueryName을 입력해줍니다.

image.png

이제 다시 웹으로 가서 바둑판 메뉴 불러오기를 하면 새로 추가한 list를 확인할 수 있습니다.

4장. Parameter 기반 개발

ListType1 파라메터의 이해와 사용법2

ListType1

ListType1은 다보리 파라메터 중 가장 많이 사용되는 파라메터입니다. 주로 필터링을 통해 데이터를 List 형식으로 출력합니다.

 ListType1 예시

1. view page

image.png

상단 필터링을 통해 데이터가 걸러지고 하단 박스에 결과 데이터들을 출력합니다.

2. para

{
    "//list-type-1": "simple and plain list by query of table join",

    "General": {
      "Title": "업체조회",
      "PageApi": "list-type1-page",
      "ActApi": "list-type1-upload"
    },

    "QueryVars": {
      "QueryName": "company-input",
      "FilterName": "",
      "FilterValue": "",
      "SimpleFilter": ""
    },
    "HeadSelectOptions": [
      {
        "Value": "new",
        "Caption": "추가"
      },
      {
        "Value": "multi-delete",
        "Caption": "일괄 삭제"
      }
    ],

    "//FormVars": "FormVars[0]-caption, FormVars[1]-searchPopup",
    "FormVars": [
      {
        "ListButton": "조회",
        "DateRange": "",
        "DateNavi": "일자방향(오늘)",
        "Date": "",
        "From": "부터",
        "To": "까지",
        "FirstRange": "",
        "SecondRange": "",
        "ThirdRange": "",
        "FourthRange": "",
        "AddTotalLine": "",
        "SelectPopup": "",
        "MultiPopup": "",
        "ChartPopup": "",
        "DownloadList": "",
        "ShowOnlyClosed": "",
        "Balance": "",
        "OrderBy": "표시 순서",
        "FilterOption": "조건조회",
        "SimpleOption": "거래유형 지정"
      }
    ],

    "FilterSelectOptions": [
      {
        "Value": "",
        "Caption": "=검색 조건="
      },
      {
        "Value": "",
        "Caption": "메뉴코드"
      }
    ],


    "SimpleSelectOptions": [
        {
            "Value": "sort ='buyer'",
            "Caption": "매출업체"
        },
        {
            "Value": "sort ='supplier'",
            "Caption": "공급업체"
        },
        {
            "Value": "sort ='seller'",
            "Caption": "입점업체"
        },
        {
            "Value": "sort ='agent'",
            "Caption": "영업대리인"
        },
        {
            "Value": " =''",
            "Caption": "해외(무역)업체"
        },
        {
            "Value": "sort =''",
            "Caption": "금융기관"
        },
        {
            "Value": "sort =''",
            "Caption": "급여대상자"
        },
        {
            "Value": "sort =''",
            "Caption": "거래중지"
        },
        {
            "Value": "",
            "Caption": "전체"
        }
    ],

    "//ListType1RangeVars": "[0]-filter, [1]-component, [2]-parameter",
    "ListType1RangeVars": [
      {
        "FirstRange": "",
        "SecondRange": "",
        "ThirdRange": "",
        "FourthRange": ""
      },
      {
        "FirstRange": "",
        "SecondRange": "",
        "ThirdRange": "",
        "FourthRange": ""
      },
      {
        "FirstRange": "",
        "SecondRange": "",
        "ThirdRange": "",
        "FourthRange": ""
      }
    ],

    "DateNaviOptions": [
        {
            "Value": "day",
            "Caption": "일"
          },
          {
            "Value": "week",
            "Caption": "주"
          },
          {
            "Value": "month",
            "Caption": "월"
          },
          {
            "Value": "quarterly",
            "Caption": "분기"
          },
          {
            "Value": "semiannual",
            "Caption": "반기"
          },
          {
            "Value": "year",
            "Caption": "년"
          },
          {
            "Value": "all",
            "Caption": "전체"
          }
    ],

    "SelectPopupOptions": [
        {
            "Caption": "업체 출력(새탭)",
            "Component": "",
            "Parameter": "",
            "TabbedMenuHash": "d2e8109543c426b4a3cb71c4a129a52d"
        }
    ],
    "SelectLinkedPopupOptions":[
        {
            "Caption": "업체 출력(새탭)",
            "Linked":"/dabory/erp/master-data/company-tabbed?bpa=eyJtZW51X25hbWUiOiJcdWM1YzVcdWNjYjRcdWI0ZjFcdWI4NWQtXHVkMGVkIiwibWVudV9jb2RlIjoiNzgwNjA0IiwiZGlzYWJsZV9sX21lbnUiOiIwIiwiZW5hYmxlX3JfbWVudSI6IjAiLCJwZXJtaXNzaW9uIjp7ImlzX215bWVudSI6IjAiLCJpc19saXN0IjoiMSIsImlzX3JlYWQiOiIxIiwiaXNfY3JlYXRlIjoiMSIsImlzX3VwZGF0ZSI6IjEiLCJpc19kZWxldGUiOiIxIiwiaXNfbmV3dGFiIjoiMCJ9LCJwYWdlX3VyaSI6IlwvZGFib3J5XC9lcnBcL21hc3Rlci1kYXRhXC9jb21wYW55LXRhYmJlZCIsInBhcmFfbmFtZSI6IlwvZm9ybVwvZm9ybS1hXC9jb21wYW55LXRhYmJlZCIsInRoZW1lX2RpciI6IiIsIm1haW5fYXBwX2lkIjowLCJndWVzdF9hcHBfaWQiOjAsImN1c3RvbV92YXIiOiIiLCJ0YWJiZWRfbWVudV9oYXNoIjoiZDJlODEwOTU0M2M0MjZiNGEzY2I3MWM0YTEyOWE1MmQifQ=="
        }
    ],


    "// OrderByOptions": "OrderBy Options//첫번째 Value가 Default",
    "OrderByOptions": [
      {
        "Value": "",
        "Caption": "상품 코드 순서"
      },
      {
        "Value": "",
        "Caption": "상품 코드 역순"
      }
    ],

    "//BalanceOptions": "Show OnlyBalaceRemained or All",
    "BalanceOptions": [
      {
        "Value": "",
        "Caption": "전체 보기"
      },
      {
        "Value": "c10 > 0",
        "Caption": "잔량있는 것만"
      }
    ],

    "DisplayVars": {
      "IsSimpleSelectPage": false,
      "IsListFirst": true,
      "IsExcelColumn": true,
      "InitLines": 15,
      "InitDateRange" : "week",
      "HeadHeight": "130",
      "IsC1Popup": "3",
      "BodyHeight": "570"
    },

    "//Theme": "ListVars[0]-caption, ListVars[1]-size(px), ListVars[2]-align->right(number) left(left)",
    "ListVars": [
          {
              "$Radio": "$Radio",
              "$Check": "$Check",
              "No": "번호",
              "C1": "업체명",
              "C2": "담당자",
              "C3": "업체구분",
              "C4": "모바일번호",
              "C5": "전화번호",
              "C6": "이메일",
              "C7": "상호",
              "C8": "업체번호"
          },
          {
              "$Radio": "3",
              "$Check": "3",
              "No": "3",
              "C1": "5",
              "C2": "5",
              "C3": "10",
              "C4": "5",
              "C5": "6",
              "C6": "6",
              "C7": "6",
              "C8": "6"
          },
          {
              "$Radio": "center",
              "$Check": "center",
              "No": "center",
              "C1": "left",
              "C2": "left",
              "C3": "left",
              "C4": "left",
              "C5": "left",
              "C6": "left",
              "C7": "left",
              "C8": "left"
          }
      ]
  }

ListType1 Filter 제어하기

image.png

1. DateNavi 제어하기

(1). FormVars에 DateNavi를 지정합니다.

(2). DateRange는 ""으로 입력합니다. (현재는 Deprecate 되었습니다.)

"FormVars": [
      {
        "ListButton": "조회",
        "DateRange": "",
        "DateNavi": "일자방향(오늘)",
        "Date": "",
        "From": "부터",
        "To": "까지",
        "FirstRange": "",
        "SecondRange": "",
        "ThirdRange": "",
        "FourthRange": "",
        "AddTotalLine": "",
        "SelectPopup": "",
        "MultiPopup": "",
        "ChartPopup": "",
        "DownloadList": "",
        "ShowOnlyClosed": "",
        "Balance": "",
        "OrderBy": "표시 순서",
        "FilterOption": "조건조회",
        "SimpleOption": "거래유형 지정"
      }
    ],

image.png

위와 같이 사용됩니다.

(3). DateNaviOptions를 다음과 같이 작성합니다. 필요없는 값들은 제외해도 무방합니다.

"DateNaviOptions": [
        {
            "Value": "day",
            "Caption": "일"
          },
          {
            "Value": "week",
            "Caption": "주"
          },
          {
            "Value": "month",
            "Caption": "월"
          },
          {
            "Value": "quarterly",
            "Caption": "분기"
          },
          {
            "Value": "semiannual",
            "Caption": "반기"
          },
          {
            "Value": "year",
            "Caption": "년"
          },
          {
            "Value": "all",
            "Caption": "전체"
          }
    ],

(4). InitDateRange에 초기 default값을 지정합니다. 

"DisplayVars": {
      "IsSimpleSelectPage": false,
      "IsListFirst": true,
      "IsExcelColumn": true,
      "InitLines": 15,
      "InitDateRange" : "week",
      "HeadHeight": "130",
      "IsC1Popup": "3",
      "BodyHeight": "570"
    },

아래와 같이 설정된 default 값으로 DateNavi를 출력할 수 있습니다.

image.png

4장. Parameter 기반 개발

파라메터를 이용한 head/body 복사

head 복사 구현하기

파라메터를 이용하여 sorder의 head와 body를 복사하는 방법을 명시합니다.

예제에서는 sorder(수주)로 테스트를 진행하겠습니다.


 필요한 사항

1. 파라메터에 대한 전반적인 이해도

2. JavaScript에 대한 기초적인 이해도

3. API에 대한 이해도


1. 수주리스트의 파라메터인 sorder.json을 살펴보겠습니다.

{
    "General": {
        "Title": "수주등록",
        "PickApi": "slip-form-book",
        "ActApi": "sorder-act"
    },


    "QueryVars": {
        "QueryName": "sales/sorder"
    },


    "HeadSelectOptions": [
        {
            "Value": "new",
            "Caption": "추가",
            "Parameter": ""
        },
        {
            "Value": "save-and-new",
            "Caption": "저장 후 추가",
            "Parameter": ""
        },
        {
            "Value": "copy-to-another",
            "Caption": "수주에서 수주로 복사(-)",
            "Parameter": "sales/sorder-sorder"
        },
        {
            "Value": "copy-to-another",
            "Caption": "매입 가격표에서 수주로 복사(-)",
            "Parameter": "purch/pquote-sorder"
        },
        {
            "Value": "copy-to-another",
            "Caption": "견적에서 수주로 복사",
            "Parameter": "sales/squote-sorder"
        },
        {
            "Value": "delete",
            "Caption": "삭제",
            "Parameter": ""
        }
    ],


    "StatusOptions": [
        {
            "Value": "확정",
            "Caption": "확정"
        },
        {
            "Value": "취소",
            "Caption": "취소"
        }
    ],


    "BodySelectOptions": [
        {
            "Value": "body-copy",
            "Caption": "수주에서 수주로 품목 복사(-)",
            "Parameter": "sales/sorder-sorder"
        },
        {
            "Value": "body-copy",
            "Caption": "견적에서 수주로 품목 복사(-)",
            "Parameter": "sales/squote-sorder"
        },
        {
            "Value": "multi-delete",
            "Caption": "품목 일괄 삭제",
            "Parameter": ""
        },
        {
            "Value": "multi-update",
            "Caption": "품목 일괄 수정",
            "Parameter": ""
        }
    ],


    "//FormVars": "ListVars[0]-Caption",
    "FormVars": [
        {
            "SaveButton": "저장",
            "AddNewBdButton": "품목 추가",
            "AutoSlipNo": "수주번호(자동채번)*",
            "Date": "수주일자*",
            "Buyer": "매출업체*",
            "BuyerContact": "업체담당자",
            "DealType": "거래구분*",
            "VatType": "부가세*",
            "VatTypeRate": "부가세율",
            "Status": "상황",
            "Delivery": "납품기한",
            "PayTerms": "지불조건",
            "Destination": "납품장소",
            "IsClosed": "종결",
            "SgroupName": "영업부서*",
            "UserName": "입력사용자*",
            "Remarks": "비고"
        },
        {
            "SaveButton": "left",
            "AddNewBdButton": "left",
            "AutoSlipNo": "left",
            "Date": "left",
            "Buyer": "left",
            "BuyerContact": "left",
            "DealType": "left",
            "VatType": "left",
            "VatTypeRate": "left",
            "Status": "left",
            "Delivery": "left",
            "PayTerms": "left",
            "Destination": "left",
            "IsClosed": "left",
            "SgroupName": "left",
            "UserName": "left",
            "Remarks": "left"
        },
        {
            "SaveButton": "0",
            "AddNewBdButton": "20",
            "AutoSlipNo": "20",
            "Date": "20",
            "Buyer": "20",
            "BuyerContact": "20",
            "DealType": "20",
            "VatType": "20",
            "VatTypeRate": "20",
            "Status": "20",
            "Delivery": "20",
            "PayTerms": "20",
            "Destination": "20",
            "IsClosed": "0",
            "SgroupName": "20",
            "UserName": "20",
            "Remarks": "0"
        },
        {
            "SaveButton": "",
            "AddNewBdButton": "",
            "AutoSlipNo": "required",
            "Date": "required",
            "Buyer": "required",
            "BuyerContact": "",
            "DealType": "required",
            "VatType": "required",
            "VatTypeRate": "",
            "Status": "",
            "Delivery": "",
            "PayTerms": "",
            "Destination": "",
            "IsClosed": "",
            "SgroupName": "required",
            "UserName": "required",
            "Remarks": ""
        }
    ],
    "// ListVars": "ListVars[0]-Caption, ListVars[1]-Size(%), ListVars[2]-align",
    "ListVars": [
        {
            "$Radio": "",
            "$Check": "$Check",
            "ItemCode": "품목코드*",
            "ItemName": "품명*",
            "SubName": "서브명#",
            "CountUnit": "단위#",
            "SorderQty": "수주수량*",
            "SorderPrc": "수주단가*",
            "SupplyAmt": "공급가액*",
            "VatAmt": "세액*",
            "SumAmt": "합계금액*",
            "CurrSalesPrc": "매출가#",
            "ConfirmDate": "요청납기일",
            "DeliDate": "확정납기일*",
            "Ref1": "참고1",
            "Ref2": "참고2",
            "SorderMemo": "품목설명(M)"
        },
        {
            "$Radio": "",
            "$Check": "3",
            "ItemCode": "10",
            "ItemName": "30",
            "SubName": "10",
            "CountUnit": "5",
            "SorderQty": "10",
            "SorderPrc": "10",
            "SupplyAmt": "10",
            "VatAmt": "10",
            "SumAmt": "10",
            "CurrSalesPrc": "10",
            "DeliDate": "12",
            "ConfirmDate": "12",
            "Ref1": "15",
            "Ref2": "15",
            "SorderMemo": "10"
        },
        {
            "$Radio": "",
            "$Check": "center",
            "ItemCode": "left",
            "ItemName": "left",
            "SubName": "left",
            "CountUnit": "center",
            "SorderQty": "decimal('sales_qty')",
            "SorderPrc": "decimal('sales_prc')",
            "SupplyAmt": "decimal('sales_amt')",
            "VatAmt": "decimal('sales_amt')",
            "SumAmt": "decimal('sales_amt')",
            "CurrSalesPrc": "decimal('sales_prc')",
            "DeliDate": "right",
            "ConfirmDate": "right",
            "Ref1": "right",
            "Ref2": "right",
            "SorderMemo": "right"
        }
    ],
    "FooterVars": [
        {
            "StorageName": "창고",
            "BranchName": "점포명",
            "QtyTotal": "수량 합계",
            "SupplyTotal": "공급가액 소계",
            "VatTotal": "부가세액 소계",
            "SumTotal": "합계액 소계"
        }
    ]
}


5장. 실행 메뉴와 권한 관리

5장. 실행 메뉴와 권한 관리

실행 메뉴의 확장

다보리 컴포저블에서 사용자 메뉴를 확장하고 수정할 수 있습니다.

사용자 메뉴리스트

image.png

erp 페이지 좌측에 사용자 메뉴리스트입니다. 로그인한 사용자의 권한에 따라, 설정에 따라 사용가능한 모든 메뉴가 노출됩니다.

모든 메뉴는 고유식별 코드인 메뉴코드가 존재하며 부모메뉴 - 자식메뉴와 같이 계층형으로 구성되어 있습니다.

좌측메뉴를 제어하기 위해서 '메뉴 확장과 API 관리' - '사용자 메뉴'로 가면

image.png

해당 앱에서 생성된 모든 메뉴 레코드가 출력됩니다.

여기서 메뉴정보들은 bpa 변수 안에 암호화되어 반환되고 테마폴더의 경로 + bpa를 통해 해당 메뉴에 접근할 수 있습니다.

우측 상단에 보이는 조회 버튼 옆에 화살표 버튼 클릭시 메뉴 레코드의 데이터를 제어할 수 있습니다.

Component : /views/components/nav-side-bar-component

Parameter : /dabory/para/erp/ko_KR/list/list-typ1/user-menu-input

Query_name : user-menu-input

사용자 메뉴의 수정 / 추가 / 삭제

image.png

"C1": "메뉴코드"        -> 메뉴의 고유한 식별코드입니다. 계층형 구조로 되어있습니다.
"C2": "메뉴명"            -> 메뉴의 이름입니다.
"C3": "페이지URL"     -> 해당 메뉴 클릭시 연결되는 url주소입니다. /dabory/erp/ 이후경로부터 작성합니다.
"C4": "파라메터명"    -> 해당 메뉴의 파라미터 경로에 있는 json 파일명을 의미합니다.
"C5": "테마폴더"        -> 해당 업체에 적용된 테마폴더의 위치를 의미합니다.
"C6": "메뉴스킵"        -> 메뉴표시 누락과 매칭되며 
"C7": "아이콘"            -> 아이콘 파일의 파일명을 의미합니다.
 "C8": "좌측메뉴"       -> 체크시 좌측메뉴에 노출이 비활성화됩니다.
"C9": "우측메뉴"        -> 체크시 우측메뉴에 노출이 활성화됩니다.
"C10": "매뉴얼URL"   -> 
"C11": "MainApp"      -> 
"C12": "GuestApp"     -> 

user-menu-input 파라미터를 통해 사용자메뉴를 추가하고 삭제하고 수정할 수 있습니다

* 사용자메뉴를 추가할 경우

1. 메뉴코드 확인

사용자 메뉴리스트에서 메뉴코드를 확인하고 추가할 메뉴의 메뉴코드가 들어갈 위치를 확인합니다.

사용자 메뉴는 parent(최상위 메뉴) - child(하위메뉴) - second chlid(두번째 하위메뉴) - third child(세번째 하위메뉴) ...

위와 같은 계층형 구조로 이루어져 있습니다. parent 의 메뉴코드가 010000이라면 child의 메뉴코드는 01로 시작합니다.

또 child의 메뉴코드가 011000이라면 second chlid의 메뉴코드는 011로 시작합니다.

이런식으로 반복하며 사용자 메뉴가 출력되기 때문에 메뉴코드를 확인하고 생성해야 합니다.

2. 테마폴더 / sort_type 지정

현재 사용하고 있는 테마의 디렉토리와 sort_type을 확인하여 input에 입력해야 합니다.

sort_type은 해당 업체의 db마다 다르기 때문에 dbr_sort_menu에서 확인이 가능합니다.

3. saveBtn을 통해 db에 저장됐다면 erp header에 캐시삭제를 통해 캐시를 삭제해주어야 웹상에 반영이 됩니다.

만약 좌측메뉴에 노출이 안된다면 아래와 같은 원인이 있을 수 있습니다.

  1. 캐시가 남아있을 경우
  2. 테마경로를 잘못 입력
  3. is_use, is_skipp 등의 컬럼값이 잘못 체크

Component : views/front/dabory/erp/list-type/type1

Parameter : /dabory/para/erp/ko_KR_list/popup/popup-form1/form-a/user-menu-input

Query_name : menu-perm/user

사용자 메뉴의 검색

image.png

"FormVars": [
        {
            "FilterOption": "검색 조건",          -> 특정 컬럼으로 검색합니다.
            "SimpleOption": "상태별 검색"    -> 특정 상태컬럼으로 검색합니다.
        }

"FilterSelectOptions": [
        {
            "Value": "",
            "Caption": "=검색 조건="
        },
        {
            "Value": "mx.menu_code",
            "Caption": "메뉴코드"
        },
        {
            "Value": "mx.menu_lang0",
            "Caption": "메뉴명"
        },
        {
            "Value": "mx.page_uri",
            "Caption": "페이지 URL"
        },
        {
            "Value": "mx.para_name",
            "Caption": "파라메터명"
        }
    ],

"SimpleSelectOptions": [
        {
            "Value": "",
            "Caption": "전체"
        },
        {
            "Value": "mx.is_skipped='1'",
            "Caption": "메뉴스킵"
        }
    ],
사용자가 FormVars['FilterOption'] 혹은  FormVars['SimpleOption']을 통해
FilterSelectOptions['Caption']이나 SimpleSelectOptions['Caption']을 선택하면 
FilterSelectOptions['value'], SimpleSelectOptions['value'] 값을 통해 쿼리가 추가되어 검색결과가 출력됩니다.
위 파라메터의 value값을 통해 다양한 검색조건, 상태별 검색이 가능합니다.

Component : views/front/dabory/erp/list-type/type1

Parameter : /dabory/para/erp/ko_KR_list/popup/popup-form1/form-a/user-menu-input

Query_name : menu-perm/user


5장. 실행 메뉴와 권한 관리

실행메뉴의 권한관리

사용자 메뉴별 유저의 권한을 설정할 수 있습니다.

image.png

녹색 바탕의 흰색 폴더 버튼을 클릭하게 되면 사용자 메뉴조회 popup이 나타납니다.

image.png

사용자의 권한별 권한 정보를 확인할 수 있으며 특정 권한번호를 클릭하게 되면 해당 사용권한에서 사용할 수 있는 사용자메뉴가 출력됩니다.

Component : /views/front/dabory/erp/perm/user-perm

Parameter : /dabory/para/erp/ko_KR/form/form-b/user-menu-perm

Query_name : user-menu-perm

이 Component에서 사용자별 메뉴의 상태값들을 수정할 수 있고 사용자메뉴에서 추가한 새로운 메뉴를 적용할 수 있습니다.

image.png

"BodySelectOptions": [
        {
            "Value": "multi-update",
            "Caption": "체크/언체크 적용",    -> 체크한 상태값의 변경사항을 반영합니다.
            "Parameter": ""
        },
        {
            "Value": "multi-delete",
            "Caption": "일부 항목 제거",        -> 체크한 특정 항목을 삭제합니다.
            "Parameter": ""
        },
        {
            "Value": "all-checked",
            "Caption": "권한 전체 체크",        -> all check
            "Parameter": ""
        },
        {
            "Value": "all-unchecked",
            "Caption": "권한 전체 언체크",    -> all uncheck
            "Parameter": ""
        },
        {
            "Value": "all-create",
            "Caption": "항목 전체 생성",        -> 추가한 사용자 메뉴를 user_menu_perm에서 불러옵니다.
            "Parameter": ""
        },
        {
            "Value": "all-delete",
            "Caption": "항목 전체 삭제",        -> 
            "Parameter": ""
        }
    ],

6장. 테마 커스터마이징

6장. 테마 커스터마이징

테마 설치하기

테마 설치하기

1. 설치할 테마를 확인한뒤 다보리 깃서버에서 해당 테마 레포지토리로 이동하여 HTTP url을 복사합니다.

image.png

2. dbrerp 소스에서 dabory 디렉토리로 이동합니다.

cd dabory

3. themes 디렉토리를 생성합니다.

mkdir themes

4. 생성한 themes 디렉토리로 이동합니다.

cd themes

5. 복사했던 깃레포지토리의 HTTP url를 git clone 합니다.

git clone http://git.daboryhost.com:10880/dbrerp-themes/eyemsg.git

6. dbrerp 소스의 루트 디렉토리에 위치한 public 경로로 이동합니다.

cd ../../public

7.  /themes/eyemsg/pro 디렉토리를 생성합니다.

mkdir -p /themes/point2u/pro

8. 생성해준 /themes/point2u/pro 경로로 이동합니다.

cd themes/eyemsg/pro

9. public/themes/eyemsg/pro 경로 안에 dabory/themes/eyemsg/pro 경로의 resources의 심볼릭 링크를 걸어줘야 합니다.

ln -s [타겟경로] [심볼릭 링크 경로] 명령어를 통해 심볼릭 링크를 걸 수 있습니다.

아래 명령어를 입력하여 심볼릭 링크를 걸어줍니다.

ln -s ../../../../dabory/themes/eyemsg/pro/resources resources

만약 이 심볼릭 링크가 정상적으로 걸리지 않았다면 css 등 정적인 요소들이 깨져서 나타날 수 있습니다.

6장. 테마 커스터마이징

git 서버와 Standard/theme 폴더 동기화

깃서버 : 테마폴더 동기화

로컬 PC에서의 스크립트 (cd php):

  1. cd $HOME/docker-works/php/: 홈 디렉토리 아래에 있는 docker-works/php/ 경로로 이동합니다. 

  2. all-gitpp {website-alias}: all-gitpp는 사전 정의된 쉘 함수로, 웹사이트 별로 Git 저장소에서 변경 사항을 가져오고 특정 폴더로 이동하여 업데이트를 수행합니다. {website-alias}는 웹사이트의 별칭을 나타내며, 해당 웹사이트의 폴더로 이동하고 Git 동기화를 실행합니다.

서버에서의 스크립트 (cdz):

  1. cd /home: 서버의 /home 디렉토리로 이동합니다. 

  2. all-gitpp-host {website-alias}: all-gitpp-host는 로컬 PC의 all-gitpp와 비슷한 역할을 합니다. 이 명령은 특정 웹사이트에 대한 Git 저장소 동기화 및 업데이트를 실행합니다. 이전과 마찬가지로 {website-alias}는 웹사이트의 별칭을 나타내며, 해당 웹사이트의 폴더로 이동하고 Git 동기화를 실행합니다.

이러한 스크립트들은 특정 작업을 자동화하여 개발자가 코드 변경 사항을 효율적으로 동기화하고 관리할 수 있도록 도와줍니다. 로컬 PC에서는 개발 환경을 관리하고, 서버에서는 실제 배포된 웹사이트를 관리하는 데 사용될 수 있습니다.

6장. 테마 커스터마이징

theme 폴더 및 .env 변수 동기화

Theme 폴더 : .env 변수 동기화

 

프로젝트 루트 경로에서 .env파일로 이동합니다.

.env파일의 DBR_THEME, PRO_THEME 변수에  적용할 테마 폴더의 이름과 동일한 값을 넣어줍니다.


(변수 이름과 테마 폴더 이름을 변수 값으로 동기화해야 합니다.)

현재는 DBR_THEME로 통합되어 DBR_THEME 변수로만 운영되고 있습니다.

6장. 테마 커스터마이징

프로 테마 커스터마이징하기

테마 개발시 pro 커스터마이징하기

다보리 컴포저블의 기본 쇼핑몰 테마인 dcdemo의 pro 페이지를 커스터마이징하는 예제입니다.

dcdemo가 설치되어 있지 않다면 프론트엔드 설치하기 예제를 통해 설치를 완료해주세요.



 pro의 구조

pro 디렉토리는 다음과 같이 구성되어있습니다. 커스터마이징시 app, para, resources, routes에서 모든 커스터마이징이 이뤄집니다.

image.png

예제1

image.png

위 이미지처럼 item-details 페이지에서 상품구분, 상품명, 상품 가격, 옵션 등의 데이터들을 출력하고 있습니다. 

예제1에서는 item-details 페이지에서 출력하고 있는 데이터를 변경하여 원하는 데이터로 바꿔서 출력하겠습니다.




6장. 테마 커스터마이징

서버에 테마를 반영하는 방법

수정사항 서버에 배포하기

1. 수정사항을 git repo에 piush합니다.

2. 서버 로그인

3. 아래와 같이 명령어를 입력합니다.

cd /home
all-gitpp-dbrerp 서버계정명


6장. 테마 커스터마이징

Api23KeyPair를 활용한 통신 가이드


 

 API23JS란?

API23JSGUEST 사이트의 JavaScript에서 HOST 사이트의 API를 사용하기 위한 권한 키입니다. 여기서 HOST는 데이터를 요청받아 처리하고 반환하는 부모 사이트이며,
GUEST는 데이터를 요청하는 자식 사이트라고 하겠습니다.
예를 들어 예시에서는 아래와 같이 정해놓고 진행하겠습니다.

 HOST 설정방법

1. HOST가 될 사이트의 통합설정으로 이동합니다.

image.png

* 사이트별로 메뉴명이 상이할 수 있습니다.

2. Api23 KeyPair Encrypted 메뉴를 클릭합니다.

image.png

3. ①, ②를 순서대로 클릭하여 Api23eKeyPair를 생성합니다.

image.png

4. 편집기를 실행하여 HOST(예시에서는 opticalpos)의 .env파일로 이동합니다.

image.png

4-1. 혹은 command에서 vi 편집기를 통해 .env 파일을 열어줍니다.

5. env파일에 API23E_KEY_PAIR 변수안에 Api23 KeyPair Encrypted 메뉴에서 생성한 Api23eKeyPair 값을 추가해줍니다.

image.png

6. 링크를 클릭하여 myapp API23-Apps로 이동합니다.

7. 아래와 같이 차례대로 버튼을 클릭합니다.

image.png

8. 아래와 같이 SSO App의 Api23 Keys를 생성할 수 있는 모달창이 열립니다.

image.png

App Type : App의 타입을 지정합니다. js를 통해 함수를 사용하여 통신할 것 이기 때문에 js로 하겠습니다.

Sort : 앱의 종료에 대해서 선택합니다. CRM을 기준하로 하기 때문에 표준 CRM인 KingkongCrm을 선택하겠습니다.

OriginUrl : geust로 사용할 url을 입력합니다.

9. Generate New Api23 Keys 버튼을 클릭하여 Api23Key생성값을 복사하여 메모장에 붙여넣습니다. (추후 HOST Api를 사용하기 위해서 필요합니다.)

10. Save 버튼을 통하여 입력한 값들을 반드시 저장합니다.

 GUEST 설정방법


1.  HOST 생성방법 3번에서 생성해준 API23eKeyPair 값을 HOST와 동일하게 GUEST의 프로젝트 .env 파일에도 동일하게 넣어주겠습니다. 

* 'api23key'키가 아니라  'API23eKeyPair'키를 넣어야합니다.

image.png

2. 편집기를 열고 GUEST 사이트의 FrontEnd(dbrerp)에서 HOST의 API를 사용하려는 view 페이지로 이동합니다.

예시에서는 eyemsg의 right.blade.php 파일에 아래와 같이 script를 추가하겠습니다.

<script src="/js/dabory.data-linker.js?serverUrl=https://opticalpos.daboryhost.com&api23Key=Nx4QebHKTssjDuP0AKude0IMZWnak0O0hb1SJ5C3PCUuPK0oRxAVAclS5/I6Zs4cO1Czr8DDrR2LNw/uJpwmzibLTYvsH54ThO5lVLs8ifHllF0fenDeHGL1R6Tuv+KJMQGQGt//HhRLrNKRyrXsx2wN1ZSUtPrpkvEQLC+DE/O0xPxYqBXqM80EaRJ+K1qrTQFkVKMwcTEv"></script>
위 script의 src 속성에서 dabory.data-linker.js에 ServerUrl에 HOST 사이트인 opticalpos url을 넣고 api23Key에  HOST 생성방법 9번에서 생성해준  Api23Key를 파라미터로 넣습니다.
* dabory.data-linker.js는 GUEST에서 HOST와 통신할 수 있도록 구현된 함수를 모아둔 파일입니다.

 dabory.data-linker.js 사용방법

<script src="/js/dabory.data-linker.js?serverUrl=https://opticalpos.daboryhost.com&api23Key=Nx4QebHKTssjDuP0AKude0IMZWnak0O0hb1SJ5C3PCUuPK0oRxAVAclS5/I6Zs4cO1Czr8DDrR2LNw/uJpwmzibLTYvsH54ThO5lVLs8ifHllF0fenDeHGL1R6Tuv+KJMQGQGt//HhRLrNKRyrXsx2wN1ZSUtPrpkvEQLC+DE/O0xPxYqBXqM80EaRJ+K1qrTQFkVKMwcTEv"></script>
    <script>
        $('#open-signup-popup').on('click', function () {
            if (! window.passwdPolicy) {
                $.fn.dataLinker.api23Js('setup-get', {
                    'SetupCode': 'passwd-policy',
                    'BrandCode': 'member'
                }, function (response) {
                    window.passwdPolicy = response
                    $('#policy-desc-em').text(window.passwdPolicy['PolicyDesc'])
                    // console.log(window.passwdPolicy)
                    $('#join').modal('show');
                })
            } else {
                $('#join').modal('show');
            }
        });
    </script>
1번 줄 :
- dabory.data-linker.js 스크립트를 로드합니다. 이 스크립트는 serverUrlapi23Key 파라미터를 통해 API 호출을 처리할 서버와 인증 키를 설정합니다.

5번줄 :

이렇게 API23JS는 HOST와 GUEST간의 안전한 데이터 통신을 가능하게 합니다.

6장. 테마 커스터마이징

Theme 개발시 네이밍 규칙

테마/계정/DB 복사 시 중복 단어로 인한 오류 방지를 위한 네이밍 규칙

 🔎문제사항

테마나 DB를 복사할 때, 폴더명내부 콘텐츠의 텍스트가 함께 일괄 변경되면서 예상치 못한 문제가 발생할 수 있습니다.

예를들어

 🛠 해결방안

1️⃣테마명, 계정명, DB명에 언더바(_) 사용하기
기존방식
✅변경방식
분류
composable ✅ compos_able theme
myaccount ✅ my_account theme
composable_db ✅ compos_able_db db
myaccount_db ✅ my_account_db db
2️⃣도메인(URL) 생성 시 하이픈(-) 사용하기
기존방식
✅ 변경방식
분류
composable.com ✅ compos_able.com domain
myaccount.com ✅ my_account.com domain

7장. 쿼리 커스터마이징

7장. 쿼리 커스터마이징

쿼리 커스터마이징 개념

다보리 컴포저블에서는 weberp_queries에 표준화된 쿼리 구조가 적용되어 있습니다. 표준 쿼리는 다양한 ERP 및 PRO 기능을 체계적으로 지원하며, 각 분류별로 구조화되어 있습니다. 테마별로 쿼리를 커스터마이징하여 사용할 수도 있지만, 기본적인 표준 쿼리의 구조와 위치를 유지하는 것이 중요합니다.

표준 쿼리 구조

weberp_queries 는 표준화된 쿼리들이 구축되어 있으며, 각 쿼리는 특정 기능과 연관된 디렉토리 구조를 따릅니다. 예를 들어, erp/list/list-type1/download/post 디렉토리에는 pro_post 테이블의 다운로드 기능을 구현하는 쿼리 파일이 포함되어 있습니다.

커스터마이징 지침

예시

weberp_queries의 디렉토리 구조 예시:

테마 디렉토리의 커스터마이징된 쿼리 구조 예시:

커스터마이징 쿼리를 구축할 때는 반드시 weberp_queries를 참조하여 필요한 쿼리의 구조와 위치를 확인하고, 동일한 디렉토리 구조로 구현해야 합니다. 이를 통해 표준 쿼리의 체계를 유지하면서도 필요한 부분을 커스터마이징할 수 있습니다.

7장. 쿼리 커스터마이징

커스터마이징 예제

pro 테마중 kbgolf에 적용된 쿼리 커스터마이징 예제를 살펴보겠습니다.

디렉토리 구조 설정

먼저 kbgolf 테마의 qry 디렉토리로 이동합니다. 예제에서 kbgolf/qry 디렉토리 구조는 다음과 같습니다.

image.png

표준 쿼리 디렉토리와 일치

백엔드 서버에서 SQL 파일을 인식하기 위해서는 main_api 서버의 디렉토리 구조와 동일하게 만들어야 합니다. 

weberp_queries 의 디렉토리를 참고하여 동일한 디렉토리를 구축합니다.

image.png

weberp_queries 디렉토리 구조 예시:

image.png

커스터마이징 쿼리의 디렉토리 구조 예시

 

QueryVars 작성

프론트엔드에서 쿼리를 호출하기 위한 파라미터를 작성합니다. QueryVars에 테마명을 포함하여 작성합니다:

"QueryVars": {
        "QueryName": "kbgolf::post/sise",
        "FilterName": "",
        "FilterValue": "",
        "FilterDate": "",
        "SimpleFilter": ""
    },

QueryName: kbgolf::post/sise와 같이 테마명을 포함시켜줍니다. 테마명이 포함되지 않으면 서버에서 표준 쿼리를 찾게 되어 에러가 발생할 수 있습니다.

서버 반영

파라메터 작성이 완료되었으면 해당 서버에 반영해야 합니다.
참고사항

테마 서버에 반영 방법


8장. 커스텀 테이블 사용방법

8장. 커스텀 테이블 사용방법

strong api를 활용한 STRONG 커스터마이징

Strong 커스터마이징이란?

다보리 컴포저블의 표준화된 테이블 구조는 통합 관리, 데이터의 일관성, 유지보수 효율성 등 여러 가지 면에서 큰 장점을 제공합니다. 만약 특정 애플리케이션에서 구조 변경이 발생했을 때 db-update 실행시 메인 API 서버에서 돌고 있는 모든 애플리케이션의 테이블 구조를 동기화할 수 있습니다.

하지만 모든 애플리케이션이 동일한 데이터 구조를 사용함에 따라 유연성의 제한이 생길 수 있습니다. 이러한 부분들은 Strong 커스터마이징을 통해 표준 테이블 구조에서 벗어나 다양하게 커스터마이징할 수 있습니다. 커스터마이징 테이블에는 테이블명에 특정 prefix를 붙여 기존 표준 테이블과 구분합니다.

 예를 들어, dbr_item이라는 표준으로 사용하고 있는 db table을 strong api를 사용하여 커스터마이징 하려면 zzz_dbr_item 같이 테이블명에 특정한 prefix를 붙여 변경하여 표준테이블과는 다르게 db 테이블을 사용할 수 있습니다. 이렇게 테이블을 커스터마이징하여 각 애플리케이션 별로 개성 있는 데이터 구조를 구축할 수 있습니다.

 또한 Strong 커스터마이징은 Java, Python, Golang 등 다양한 언어로 백엔드 API 서버 구축이 가능합니다. 이 API 서버를 통해 해당 어플리케이션의 개발 언어와 무관하게 다보리 컴포저블의 게이트웨이 서버를 이용할 수 있습니다. 이를 통해 각 애플리케이션은 고유한 요구사항을반영한 맞춤형 데이터 구조를 가질 수 있으면서도, 다보리 컴포저블의 통합 관리 및 일관성 유지의 장점을 활용할 수 있습니다.

Strong api를 활용한 프론트엔드 예제

참고사항

프론트엔드 세팅

1. env파일에 API_URL변수 추가

해당 API 서버의 URL을 입력해줍니다.

2. dabory/themes/dcdemo/ 경로 안에 strong 디렉토리 추가

image.png

3. strong 디렉토리에 frontend/erp 디렉토리 추가

image.png

4. app, resources 디렉토리를 각각 추가

image.png

기타

기타

바코드 프린트 사용방법

바코드 라이브러리 적용방법

1. 라라벨 패키지 정보

"DNS1D": "Milon\\Barcode\\Facades\\DNS1DFacade",
                        "DNS2D": "Milon\\Barcode\\Facades\\DNS2DFacade"

 

 

  1. 바코드 print 사용방법

controller :  db에서 데이터 불러옴 ->

view :  불러온 데이터를 가져와서 DNS1D 클래스를 통해 바코드와 연동

padding, margin 등을 적용하여 바코드의 출력위치를 지정

 

 

기타

크리스탈 레포트 사용방법

MacOS에서 크리스탈 레포트 사용 및 윈도우 서버 접근 방법

1. 크리스탈 레포트 개요

크리스탈 레포트(Crystal Reports)는 데이터를 자동으로 가져와 PDF, Excel, Word 등의 보고서를 생성 및 배포하는 역할을 합니다 일반적으로 기업용 ERP, 회계 시스템, CRM 등과 연동하여 사용되며, 이러한 이유로 윈도우 서버 환경에서 운영됩니다

2. MacOS에서 윈도우 서버 접근 방법

MacOS에서 윈도우 서버에서 실행 중인 크리스탈 레포트에 접근하려면 원격 데스크톱 연결을 사용해야 합니다

2.1 Microsoft 원격 데스크톱 앱 설치

MacOS에서는 RDP(Remote Desktop Protocol) 파일을 실행하여 원격 서버에 접속할 수 있으며, 이를 위해 Microsoft의 원격 데스크톱 앱이 필요합니다

 2.2 원격 데스크톱 연결 방법

  1. Microsoft Remote Desktop 앱을 실행합니다.

  2. 'Import from RDP File' 또는 **'새 연결 추가'**를 선택합니다.

  3. 제공받은 RDP 파일을 불러오거나 수동으로 서버 정보를 입력합니다.

  4. Username(사용자명)과 Password(비밀번호)를 입력하여 로그인합니다.

  5. 원격 데스크톱을 통해 윈도우 서버에 접속하면 크리스탈 레포트를 사용할 수 있습니다.

스크린샷 2025-02-14 오전 11.19.35.png


3. 크리스탈 레포트 실행

다음은 윈도우 서버 접속 후 .rpt 파일을 열어 크리스탈 리포트에서 보고서를 편집할 때, 자주 사용하는 기능들 입니다

스크린샷(19).png

🔹 1. 텍스트 상자 (Text Box)

📌 역할:

🔹 2. 라인(Line) 생성 도구

📌 역할:

🔹 3. DB 필드 (Database Fields) - 동적 데이터 바인딩

📌 역할:

4. 크리스탈 리포트에서 합계 자동 정렬 방법

📌 목표: ex) 연말정산에서 데이터 한줄 한줄 추가 될때 합계가 맨 아래에 위치하는 방법


📌 원리:

스크린샷(20).png

📌 설정 방법:
1️⃣ "Section Expert"에서 Report Footer 설정 조정

2️⃣ Suppress 조건 추가하여 Report Footer가 마지막에만 나오도록 설정

📌 예상 결과:

No 방문일 현금 카드 외상금액 합계
1 2024-11-10 10,000 50,000 0 60,000
2 2024-11-11 5,000 40,000 0 45,000
3 2024-11-12 8,000 35,000 0 43,000
  합계 23,000 125,000 0 148,000

데이터가 많아질수록 합계가 자동으로 맨 아래로 정렬됨

 

5. 크리스탈 리포트에서 Database Fields를 연동하여 데이터 치환하는 방법

📌 목표:
오른쪽 Database Fields에서 불러온 데이터를 원하는 위치에 배치하여 동적으로 치환하기


1. Database Fields에서 필요한 데이터 가져오기

📌 설정 방법:
1️⃣ 오른쪽 Field Explorer 창에서 "Database Fields" 선택
2️⃣ 필요한 데이터 필드를 찾음 (예: {c1}, {c2}, {c3} 등)
3️⃣ 각 필드를 드래그하여 보고서(Report) 디자인의 적절한 위치에 배치


2. 데이터 필드를 Header, Details, Footer에 적절히 배치하기

📌 배치 방법:
Header(헤더) 섹션:


3. 예제: Database Fields 배치하기

📝 Report 디자인에서 데이터 배치 예시

위치 Database Fields (예제) 설명
Header {c1} (사업자번호) 보고서 상단에 고정
Header {c2} (전화번호) 보고서 상단에 고정
Details {c3} (방문일) 데이터가 동적으로 반복됨
Details {c4} (현금) 데이터가 동적으로 반복됨
Details {c5} (카드) 데이터가 동적으로 반복됨
Details {c6} (합계) 데이터가 동적으로 반복됨
Footer {c7} (총합계) 마지막 행 아래에 위치

이제 데이터가 동적으로 추가될 때, 각 위치에 맞는 값이 자동으로 채워짐
합계도 마지막 행 아래에 자동으로 정렬됨


 


기타

프론트에서 크리스탈레포트 연동방법

Crystal Report + Front 연동방법

1. 아래와 같이 이미 작업된 양식의 rpt파일이 존재한다면 해당 rpt파일에서 필요한 필드들을 확인합니다.

image.png

1-1 위와 같이 작성된 rpt 파일이 존재하지 않는다면 C:\ReCrystallizeServer\Reports\standard 경로로 이동후 필요한 양식과 가장 흡사한 양식을 찾아 복사해줍니다.

2.  확인한 필드를 토대로 쿼리를 작성합니다.

-- opticalpos::federated/crystal/adjustment/subqry/insert1.sql

SELECT
    UNIX_TIMESTAMP() as created_on,
    2 as list_token,
    'head-foot' as position,
    -- 발행매장
    tax_no as c1,             -- 사업자등록번호
    tel_no as c2,             -- 전화번호
    branch_name as c3,        -- 상호명
    branch_manager as c4,     -- 대표자
    -- 고객정보
    company_no as c5,         -- 고객번호
    company_name as c6,       -- 고객명


    0 as d1,  -- dummy
    0 as d2,  -- dummy
    0 as d3,  -- dummy
    0 as d4,  -- dummy
    0 as d5,  -- dummy
    0 as d6,  -- dummy
    0 as d7,  -- dummy
    0 as d8,  -- dummy
    0 as d9,  -- dummy
    0 as d10  -- dummy


from dbr_company as mx
inner join dbr_sorder on mx.id = dbr_sorder.buyer_id
inner join dbr_branch on dbr_sorder.branch_id = dbr_branch.id


-- @where
group by mx.id
-- @order



-- opticalpos::federated/crystal/adjustment/subqry/insert2.sql

SELECT
    UNIX_TIMESTAMP() as created_on,
	2 as list_token,
	'body' as position,
	sorder_date as c1,                      -- 주문일자
    ccard_amt as c2,                        -- 카드 사용금액
    cash_amt as c3,                         -- 현금 사용금액
    coupon_amt as c4,                       -- 쿠폰 사용금액
    reward_use_amt as c5,                   -- 적립금 사용금액
    discount_amt as c6,                     -- 할인금 사용금액
    sum(sorder_sum) - ccard_amt - cash_amt - coupon_amt - reward_use_amt as c7, -- 외상 금액
    sum(ccard_amt) as c8,                   -- 해당일의 총 카드 사용금액
    sum(cash_amt) as c9,                    -- 해당일의 총 현금 사용금액
    sum(sorder_sum) as c10,                  -- 해당일의 총 사용금액
    sum(sum(sorder_sum)) OVER () as c11,     -- 해당고객의 토탈 사용금액
	0 as d1,  -- dummy
    0 as d2,  -- dummy
    0 as d3,  -- dummy
    0 as d4,  -- dummy
    0 as d5,  -- dummy
    0 as d6,  -- dummy
    0 as d7,  -- dummy
    0 as d8,  -- dummy
    0 as d9,  -- dummy
    0 as d10  -- dummy

from
	dbr_sorder
	inner join
		( select
	    buyer_id, dbr_company.id as id
    from
	    dbr_company
	    inner join dbr_sorder on dbr_company.id = dbr_sorder.buyer_id
    group by buyer_id
	 ) as mx
	on mx.buyer_id = dbr_sorder.buyer_id

inner join dbr_sorder_bd on dbr_sorder.id = dbr_sorder_bd.sorder_id

-- @where
group by sorder_no
-- HAVING SUM(sorder_sum) - ccard_amt - cash_amt - coupon_amt - reward_use_amt <> SUM(sorder_sum)
-- @order
list-token :
position : rpt 파일에서 사용할  데이터필드의 섹션을 명시합니다.
c1 ~ c6  : head-foot section에 치환될 데이터들을 차례대로 작성합니다.
d1~d10 : 필요하다면 d1~d10까지 사용하여 데이터 필드를 채워줍니다.


3. crystal report를 사용하는 메뉴의 파라메터에 PrintVars를 추가합니다.

"PrintVars": {
        "QueryName": "opticalpos::federated/crystal/adjustment",
        "ReportPath": "standard/adjustment/adjustment.rpt",
        "ExportFmt": "PDF",
        "ServerPrinter": "",
        "CustomCode": "adjustment"
    },

QueryName : 위에서 작성했던 query를 입력해줍니다.

ReportPath :  winodw server에서 rpt 파일을 저장했던 위치입니다.

ExportFmt : 레포트 출력시 파일의 형식입니다.

ServerPrinter : ""

CustomCode : 해당 커스텀을 구분할 수 있는 code입니다.

4. env(설정파일)에 REPORT_SERVER_URL 변수를 확인합니다.