acquire-core-x/app/build.sh
hyeongwoo-choi 1fd60a1e49 실운영 데이터 + 운영 대시보드/조회 화면 (실사용 시스템화)
- db/schema.d/90-seed.sql: 가맹점 40(실제풍 상호·업종별 MDR 18~30bp·한도),
  2026-04-20~07-19 3개월 매입 8,190건(주중/주말 거래량·금액구간 분포·채널/발급사 비중),
  승인 1:1, 정산 7,560, 원장 15,120(RECON+SETTLE 이중기표), 가맹점 일집계, 시퀀스 정렬
- 게이트웨이 /api/query: libpq 읽기전용 조회(SELECT만, 단일문, 500행 캡) — MIS/리포팅 경로
- UI 조회/현황 그룹 7화면: 운영 대시보드(카드 7종+최근거래+가맹점TOP7+7영업일 실적),
  매입/정산 목록, 가맹점 현황, 일자별 실적, 원장, 채널·발급사 분석 — 기본화면=대시보드
- 검증: 시드 로딩 psql 확인, /api/query 동작, 헤드리스 스크린샷으로 대시보드 실데이터 렌더 확인

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 03:24:57 +00:00

216 lines
7.6 KiB
Bash

#!/bin/bash
##
## build.sh - REUSABLE build + Enduro/X config generator for acquire-core-x.
##
## Discovers every module under app/src/<mod>/, ecpg-precompiles its .pgc, builds
## - libacqcommon.a (from app/src/common/*.c) [once]
## - lib<mod>dbio.a (from app/src/<mod>/dbio/*.pgc) [per module]
## - <mod>_svr (from app/src/<mod>/<mod>_svr.pgc) [per module]
## - <mod> batches (from app/src/<mod>/batch/*.pgc) [per module]
## - standalone clients (from app/src/clients/*.c)
## then GENERATES app/conf/ndrxconfig.xml with one <server> entry per <mod>_svr.
##
## Adding a new module later = drop app/src/<mod>/{<mod>_svr.pgc,dbio,batch} and
## re-run build.sh. No hand-editing of config or this script is required: modules,
## servers, dbio libs, batches, and srvids are all DISCOVERED.
##
set -euo pipefail
SRC=/app/src
BIN=/app/bin
LIB=/app/lib
OBJ=/app/obj
UBF=/app/ubftab
CONF=/app/conf
EXINC=/usr/local/include
PGINC="$(pg_config --includedir)"
PGLIB="$(pg_config --libdir)"
mkdir -p "$BIN" "$LIB" "$OBJ"
# Includes for every compile (CFLAGS is honored by buildserver/buildclient and
# by our direct gcc calls). Add every module's dbio AND svc dir so headers resolve
# (svc/*.pgc copybooks include the module's dbio + common headers).
CFLAGS="-I$UBF -I$EXINC -I$PGINC -I$SRC/common"
for d in "$SRC"/*/dbio; do [ -d "$d" ] && CFLAGS="$CFLAGS -I$d"; done
for d in "$SRC"/*/svc; do [ -d "$d" ] && CFLAGS="$CFLAGS -I$d"; done
export CFLAGS
PGLINK="-L$PGLIB -lecpg -lpq"
# ecpg needs the same header search path as gcc (its preprocessor opens the
# #include'd copybooks to find EXEC SQL host-var decls). Mirror CFLAGS' -I set.
ECPG_INC="-I$UBF -I$SRC/common"
for d in "$SRC"/*/dbio; do [ -d "$d" ] && ECPG_INC="$ECPG_INC -I$d"; done
for d in "$SRC"/*/svc; do [ -d "$d" ] && ECPG_INC="$ECPG_INC -I$d"; done
log() { echo "[build] $*"; }
# ---------------------------------------------------------------------------
# discover modules = dirs app/src/<mod>/ that contain <mod>_svr.pgc
# ---------------------------------------------------------------------------
MODS=()
for d in "$SRC"/*/; do
m="$(basename "$d")"
[ -f "$d/${m}_svr.pgc" ] && MODS+=("$m")
done
IFS=$'\n' MODS=($(printf '%s\n' "${MODS[@]}" | sort)); unset IFS
log "modules discovered: ${MODS[*]}"
# ---------------------------------------------------------------------------
# 0. UBF field header
# ---------------------------------------------------------------------------
log "mkfldhdr acq.fd"
( cd "$UBF" && FIELDTBLS=acq.fd FLDTBLDIR="$UBF" mkfldhdr acq.fd >/dev/null )
# ecpg precompile helper: $1 = .pgc path -> echoes generated .c path
ecpg_gen() {
local pgc="$1" base out
base="$(basename "${pgc%.pgc}")"
out="$OBJ/${base}.c"
ecpg $ECPG_INC -I"$(dirname "$pgc")" -o "$out" "$pgc"
echo "$out"
}
# ---------------------------------------------------------------------------
# 1. common lib -> libacqcommon.a
# ---------------------------------------------------------------------------
log "libacqcommon.a"
COMMON_OBJS=()
for c in "$SRC"/common/*.c; do
o="$OBJ/$(basename "${c%.c}").o"
gcc -c $CFLAGS "$c" -o "$o"
COMMON_OBJS+=("$o")
done
ar rcs "$LIB/libacqcommon.a" "${COMMON_OBJS[@]}"
NSVR=0; NDBIO=0; NBATCH=0
# ---------------------------------------------------------------------------
# 2..4 per module: dbio lib, server, batches
# ---------------------------------------------------------------------------
NSVC=0
for m in "${MODS[@]}"; do
MDIR="$SRC/$m"
DBIO_LIB=""
SVC_LIB=""
# -- dbio static lib (optional) --
if compgen -G "$MDIR/dbio/*.pgc" >/dev/null; then
log "lib${m}dbio.a"
DB_OBJS=()
for pgc in "$MDIR"/dbio/*.pgc; do
c="$(ecpg_gen "$pgc")"
o="${c%.c}.o"
gcc -c $CFLAGS "$c" -o "$o"
DB_OBJS+=("$o")
done
ar rcs "$LIB/lib${m}dbio.a" "${DB_OBJS[@]}"
DBIO_LIB="$LIB/lib${m}dbio.a"
NDBIO=$((NDBIO+1))
fi
# -- per-service static lib (NEW legacy layout, optional) --
# A module may keep its services INLINE in <mod>_svr.pgc (old style) OR split
# them into svc/*.pgc, one service per file (new style). Both are supported;
# when svc/*.pgc exist they are archived into lib<mod>svc.a and linked in.
if compgen -G "$MDIR/svc/*.pgc" >/dev/null; then
log "lib${m}svc.a"
SVC_OBJS=()
for pgc in "$MDIR"/svc/*.pgc; do
c="$(ecpg_gen "$pgc")"
o="${c%.c}.o"
gcc -c $CFLAGS "$c" -o "$o"
SVC_OBJS+=("$o")
done
ar rcs "$LIB/lib${m}svc.a" "${SVC_OBJS[@]}"
SVC_LIB="$LIB/lib${m}svc.a"
NSVC=$((NSVC+1))
fi
# -- module server <mod>_svr (links svc lib + dbio lib + common) --
log "${m}_svr"
SVR_C="$(ecpg_gen "$MDIR/${m}_svr.pgc")"
buildserver -o "$BIN/${m}_svr" -f "$SVR_C" \
-a "$SVC_LIB $DBIO_LIB $LIB/libacqcommon.a $PGLINK"
NSVR=$((NSVR+1))
# -- batches (optional): each *.pgc -> its own client executable --
if compgen -G "$MDIR/batch/*.pgc" >/dev/null; then
for pgc in "$MDIR"/batch/*.pgc; do
name="$(basename "${pgc%.pgc}")"
log "batch $name"
BC="$(ecpg_gen "$pgc")"
buildclient -o "$BIN/$name" -f "$BC" \
-a "$DBIO_LIB $LIB/libacqcommon.a $PGLINK"
NBATCH=$((NBATCH+1))
done
fi
done
# ---------------------------------------------------------------------------
# 5. standalone clients (plain C, no EXEC SQL)
# ---------------------------------------------------------------------------
NCLI=0
for c in "$SRC"/clients/*.c; do
name="$(basename "${c%.c}")"
log "client $name"
buildclient -o "$BIN/$name" -f "$c" -a "-L$PGLIB -lpq"
NCLI=$((NCLI+1))
done
# ---------------------------------------------------------------------------
# 6. GENERATE ndrxconfig.xml (tmsrv fixed at srvid 40; module servers 100 step 10)
# ---------------------------------------------------------------------------
log "generating ndrxconfig.xml for servers: ${MODS[*]/%/_svr}"
gen_servers() {
local srvid=100
for m in "${MODS[@]}"; do
cat <<EOF
<server name="${m}_svr">
<srvid>${srvid}</srvid>
<min>1</min>
<max>1</max>
<sysopt>-e \${NDRX_APPHOME}/log/${m}_svr.log -r</sysopt>
</server>
EOF
srvid=$((srvid+10))
done
}
cat > "$CONF/ndrxconfig.xml" <<EOF
<?xml version="1.0" ?>
<!-- GENERATED by app/build.sh - do not hand-edit. One <server> per discovered
<mod>_svr module server; each advertises its module's services at tpsvrinit. -->
<endurox>
<appconfig>
<sanity>1</sanity>
<brrefresh>5</brrefresh>
<restart_min>1</restart_min>
<restart_step>1</restart_step>
<restart_max>5</restart_max>
<restart_to_check>20</restart_to_check>
<gather_pq_stats>Y</gather_pq_stats>
</appconfig>
<defaults>
<min>1</min>
<max>1</max>
<autokill>1</autokill>
<start_max>20</start_max>
<pingtime>100</pingtime>
<ping_max>800</ping_max>
<end_max>30</end_max>
<killtime>1</killtime>
</defaults>
<servers>
<!-- XA transaction manager for RM1 (ECPG/PostgreSQL). -->
<server name="tmsrv">
<srvid>40</srvid>
<min>1</min>
<max>1</max>
<sysopt>-e \${NDRX_APPHOME}/log/tmsrv-rm1.log -r -- -t1 -l\${NDRX_APPHOME}/tmlogs/rm1 -m10</sysopt>
</server>
$(gen_servers)
</servers>
</endurox>
EOF
log "DONE: modules=${#MODS[@]} servers=$NSVR svc_libs=$NSVC dbio_libs=$NDBIO batches=$NBATCH clients=$NCLI"
echo "[build] server binaries: ${MODS[*]/%/_svr}"