Wave K: 잔여 패리티 갭 완결 (패리티 80%→~87%)
패리티 분석의 남은 갭(온보딩·KYC·3자대사·ISO전문·계정체계·비기능)을 마무리. ■ 가맹점 생애주기 (75→90) - mm_application(230): 온보딩/언더라이팅 심사(RECEIVED/UNDERWRITING/APPROVED/REJECTED). - mm_kyc(1,150): KYC/AML 5종(IDENTITY/SANCTION/PEP/AML/CREDIT). - 서비스 MM_ONBOARD(상태기계+MID발급, 부적법전이 거부)·MM_KYC_CHECK. ■ 원장·회계·대사 (80→90) - lg_account(10): 계정과목 — suspense(미결)/clearing(정산대기) 분리. - rc_3way(16,185): 3자대사 카드망↔내부원장↔은행입금. 서비스 RC_3WAY. ■ 클리어링·수수료 (75→85, 88→90) - cl_presentment 프레젠트먼트 윈도우·late_flag, interchange downgrade(56,912). - ISO8583 취소전문 0420, MONTHLY_DISCOUNT 펀딩모델 활성화(94,376). ■ 비기능 (50→58) - docs/OPS_RUNBOOK.md: HA/DR·PCI·데이터보존·규제 설계 명시(코드불가 영역 정직 구분). ■ 화면·검증 - 시스템현황에 온보딩·KYC·3자대사 패널. - 통합빌드 error 0, 5,915 서비스, 3본 실호출 검증(상태기계 부적법전이 거부), 6단체인 COMMIT OK, 미결2PC 0. - 패리티 재채점 ≈87/100. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d292772b1f
commit
bba433308a
14 changed files with 695 additions and 173 deletions
|
|
@ -152,6 +152,10 @@
|
|||
#include "MM_CHK_ORPHAN.h"
|
||||
#include "MM_CHK_GRADE.h"
|
||||
|
||||
/* ----- 가맹점 생애주기 (Wave K): 심사 상태기계 / KYC·AML 점검 */
|
||||
#include "MM_ONBOARD.h"
|
||||
#include "MM_KYC_CHECK.h"
|
||||
|
||||
/* ----- advertise table: {service name, function} (fn is extern from its file) */
|
||||
static struct { const char *name; void (*fn)(TPSVCINFO *); } SVCS[] = {
|
||||
{"MM_MERCH_REG", MM_MERCH_REG},
|
||||
|
|
@ -287,6 +291,8 @@ static struct { const char *name; void (*fn)(TPSVCINFO *); } SVCS[] = {
|
|||
{"MM_CHK_MCC", MM_CHK_MCC},
|
||||
{"MM_CHK_ORPHAN", MM_CHK_ORPHAN},
|
||||
{"MM_CHK_GRADE", MM_CHK_GRADE},
|
||||
{"MM_ONBOARD", MM_ONBOARD},
|
||||
{"MM_KYC_CHECK", MM_KYC_CHECK},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
|
|||
15
app/src/mm/svc/MM_KYC_CHECK.h
Normal file
15
app/src/mm/svc/MM_KYC_CHECK.h
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* MM_KYC_CHECK.h - mm 서비스 MM_KYC_CHECK 카피북 (copybook / record header).
|
||||
* KYC/AML 점검 수행·판정 후 mm_kyc 적재.
|
||||
* 사용 UBF 필드:
|
||||
* 입력 T_ID1(app_id), T_STR1(check_type: IDENTITY/SANCTION/PEP/AML/CREDIT)
|
||||
* 출력 T_STATUS(result: PASS/FAIL/REVIEW), T_ARG1(score), T_ID1(kyc_id), T_RC
|
||||
*/
|
||||
#ifndef MM_KYC_CHECK_H
|
||||
#define MM_KYC_CHECK_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_KYC_CHECK(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_KYC_CHECK_H */
|
||||
130
app/src/mm/svc/MM_KYC_CHECK.pgc
Normal file
130
app/src/mm/svc/MM_KYC_CHECK.pgc
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* MM_KYC_CHECK.pgc - mm 모듈 서비스 MM_KYC_CHECK (KYC/AML 점검 수행·판정).
|
||||
* 업무: mm_application.risk_score 를 근거로 check_type 별 판정을 수행하고
|
||||
* mm_kyc 에 점검 결과 1건을 적재한다.
|
||||
* 판정규칙:
|
||||
* - risk_score >= 950 -> FAIL (임계 초과)
|
||||
* - risk_score > 850 & check IN (SANCTION,AML) -> REVIEW (고위험 제재/자금세탁)
|
||||
* - status=REJECTED & check=CREDIT -> FAIL (신용 부적격)
|
||||
* - 그 외 -> PASS
|
||||
* 입력: T_ID1(app_id), T_STR1(check_type: IDENTITY/SANCTION/PEP/AML/CREDIT).
|
||||
* 출력: T_STATUS=result, T_ARG1=score, T_ID1=kyc_id, T_RC.
|
||||
* 호출자 XA 브랜치에서 수행(EXEC SQL CONNECT 없음). mm_svr 가 tpsvrinit 에서 광고.
|
||||
*/
|
||||
#include "MM_KYC_CHECK.h"
|
||||
|
||||
#define KYC_FAIL_THRESHOLD 950 /* 임계 초과 -> 무조건 FAIL */
|
||||
#define KYC_REVIEW_THRESHOLD 850 /* 제재/AML 고위험 -> REVIEW */
|
||||
|
||||
/* MM_KYC_CHECK - KYC/AML 점검 판정 및 mm_kyc 적재. */
|
||||
void MM_KYC_CHECK(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char check[24];
|
||||
int valid_type = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_app_id, h_risk, h_score, h_kyc_id, h_logid;
|
||||
char h_check[24], h_mid[64], h_astatus[16], h_result[16];
|
||||
char h_detail[160], h_svc[24], h_msg[200];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
/* 지역/호스트 변수 초기화 (DECLARE SECTION 밖) */
|
||||
h_app_id = h_risk = h_score = h_kyc_id = h_logid = 0;
|
||||
check[0] = 0;
|
||||
h_check[0] = h_mid[0] = h_astatus[0] = 0;
|
||||
strcpy(h_result, "PASS");
|
||||
strcpy(h_svc, "MM_KYC_CHECK");
|
||||
userlog("[MM_KYC_CHECK] KYC 점검 진입");
|
||||
|
||||
/* [1] 입력 검증부 -------------------------------------------------- */
|
||||
h_app_id = getl(b, T_ID1);
|
||||
if (h_app_id <= 0) {
|
||||
setl(b, T_RC, 7101);
|
||||
Bchg(b, T_MSG, 0, "신청 ID(app_id) 필수", 0L);
|
||||
userlog("[MM_KYC_CHECK] app_id 검증 실패 id=%ld", h_app_id);
|
||||
FAIL(b);
|
||||
}
|
||||
gets_(b, T_STR1, check, sizeof(check));
|
||||
if (strcmp(check, "IDENTITY") == 0 || strcmp(check, "SANCTION") == 0 ||
|
||||
strcmp(check, "PEP") == 0 || strcmp(check, "AML") == 0 ||
|
||||
strcmp(check, "CREDIT") == 0)
|
||||
valid_type = 1;
|
||||
if (!valid_type) {
|
||||
setl(b, T_RC, 7102);
|
||||
Bchg(b, T_MSG, 0, "check_type 은 IDENTITY/SANCTION/PEP/AML/CREDIT 중 하나", 0L);
|
||||
userlog("[MM_KYC_CHECK] 부적합 check_type=[%s]", check);
|
||||
FAIL(b);
|
||||
}
|
||||
strncpy(h_check, check, sizeof(h_check)-1); h_check[sizeof(h_check)-1] = 0;
|
||||
|
||||
/* [2] 신청/리스크 조회부 ----------------------------------------- */
|
||||
EXEC SQL SELECT risk_score, coalesce(merchant_id,''), status
|
||||
INTO :h_risk, :h_mid, :h_astatus
|
||||
FROM mm_application WHERE app_id = :h_app_id;
|
||||
if (sqlca.sqlcode == 100) {
|
||||
setl(b, T_RC, 7103);
|
||||
Bchg(b, T_MSG, 0, "신청 원장 미존재", 0L);
|
||||
userlog("[MM_KYC_CHECK] 신청 미존재 app_id=%ld", h_app_id);
|
||||
FAIL(b);
|
||||
} else if (sqlca.sqlcode < 0) {
|
||||
userlog("[MM_KYC_CHECK] 신청 조회 오류 [%d]", sqlca.sqlcode);
|
||||
FAIL(b);
|
||||
}
|
||||
h_score = h_risk;
|
||||
userlog("[MM_KYC_CHECK] app_id=%ld risk=%ld status=%s check=%s",
|
||||
h_app_id, h_risk, h_astatus, h_check);
|
||||
|
||||
/* [3] 판정부 (임계/제재/신용) ------------------------------------- */
|
||||
if (h_risk >= KYC_FAIL_THRESHOLD) {
|
||||
strcpy(h_result, "FAIL");
|
||||
userlog("[MM_KYC_CHECK] 리스크 임계 초과 risk=%ld -> FAIL", h_risk);
|
||||
} else if (h_risk > KYC_REVIEW_THRESHOLD &&
|
||||
(strcmp(h_check, "SANCTION") == 0 || strcmp(h_check, "AML") == 0)) {
|
||||
strcpy(h_result, "REVIEW");
|
||||
userlog("[MM_KYC_CHECK] 고위험 제재/AML -> REVIEW");
|
||||
} else if (strcmp(h_astatus, "REJECTED") == 0 && strcmp(h_check, "CREDIT") == 0) {
|
||||
strcpy(h_result, "FAIL");
|
||||
userlog("[MM_KYC_CHECK] 반려 신청 신용점검 -> FAIL");
|
||||
} else {
|
||||
strcpy(h_result, "PASS");
|
||||
}
|
||||
|
||||
/* [4] 본처리부: mm_kyc 적재 (kyc_id = nextval mm_kyc_seq) ---------- */
|
||||
EXEC SQL SELECT nextval('mm_kyc_seq') INTO :h_kyc_id;
|
||||
if (sqlca.sqlcode < 0) { userlog("[MM_KYC_CHECK] kyc 시퀀스 실패"); FAIL(b); }
|
||||
snprintf(h_detail, sizeof(h_detail), "%s 자동점검 risk=%ld result=%s",
|
||||
h_check, h_risk, h_result);
|
||||
EXEC SQL INSERT INTO mm_kyc
|
||||
(kyc_id, app_id, merchant_id, check_type, result, score, detail)
|
||||
VALUES (:h_kyc_id, :h_app_id, :h_mid, :h_check, :h_result, :h_score, :h_detail);
|
||||
if (sqlca.sqlcode < 0) {
|
||||
userlog("[MM_KYC_CHECK] mm_kyc 적재 실패 [%d]", sqlca.sqlcode);
|
||||
setl(b, T_RC, 7104);
|
||||
Bchg(b, T_MSG, 0, "KYC 점검 결과 적재 실패", 0L);
|
||||
FAIL(b);
|
||||
}
|
||||
|
||||
/* [5] 이력/감사 적재부 (cm_log) ----------------------------------- */
|
||||
EXEC SQL SELECT nextval('cm_log_seq') INTO :h_logid;
|
||||
if (sqlca.sqlcode < 0) { userlog("[MM_KYC_CHECK] 로그 시퀀스 실패"); FAIL(b); }
|
||||
snprintf(h_msg, sizeof(h_msg), "MM_KYC_CHECK app=%ld type=%s result=%s score=%ld kyc=%ld",
|
||||
h_app_id, h_check, h_result, h_score, h_kyc_id);
|
||||
EXEC SQL INSERT INTO cm_log (log_id, svc_name, log_level, msg, biz_date)
|
||||
VALUES (:h_logid, :h_svc,
|
||||
CASE WHEN :h_result = 'PASS' THEN 'I' ELSE 'W' END,
|
||||
:h_msg, current_date);
|
||||
if (sqlca.sqlcode < 0) { userlog("[MM_KYC_CHECK] 감사 로그 적재 실패 [%d]", sqlca.sqlcode); FAIL(b); }
|
||||
|
||||
/* [6] 응답부 (출력 필드 설정) ------------------------------------- */
|
||||
Bchg(b, T_STATUS, 0, h_result, 0L);
|
||||
setl(b, T_ARG1, h_score);
|
||||
setl(b, T_ID1, h_kyc_id);
|
||||
setl(b, T_RC, 0);
|
||||
|
||||
/* [7] 완료 로깅 --------------------------------------------------- */
|
||||
userlog("[MM_KYC_CHECK] 점검 완료 app_id=%ld type=%s result=%s kyc_id=%ld",
|
||||
h_app_id, h_check, h_result, h_kyc_id);
|
||||
OK(b);
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 et smartindent: */
|
||||
16
app/src/mm/svc/MM_ONBOARD.h
Normal file
16
app/src/mm/svc/MM_ONBOARD.h
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* MM_ONBOARD.h - mm 서비스 MM_ONBOARD 카피북 (copybook / record header).
|
||||
* 가맹점 심사 진행(상태기계). RECEIVED->UNDERWRITING->APPROVED/REJECTED.
|
||||
* 사용 UBF 필드:
|
||||
* 입력 T_ID1(app_id), T_STR1(action: UNDERWRITE/APPROVE/REJECT),
|
||||
* T_STR3(reviewer, 선택), T_REASON(reject 사유, 선택)
|
||||
* 출력 T_STATUS(새 status), T_STR2(발급 merchant_id), T_RC
|
||||
*/
|
||||
#ifndef MM_ONBOARD_H
|
||||
#define MM_ONBOARD_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_ONBOARD(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_ONBOARD_H */
|
||||
140
app/src/mm/svc/MM_ONBOARD.pgc
Normal file
140
app/src/mm/svc/MM_ONBOARD.pgc
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* MM_ONBOARD.pgc - mm 모듈 서비스 MM_ONBOARD (가맹점 심사 진행 / 상태기계).
|
||||
* 업무: mm_application 의 심사 상태를 전이한다. 상태기계는 아래 전이만 허용하고
|
||||
* 그 외 전이는 부적법(不適法)으로 거부한다.
|
||||
* RECEIVED --UNDERWRITE--> UNDERWRITING
|
||||
* UNDERWRITING --APPROVE----> APPROVED (merchant_id 발급/decision_at/reviewer)
|
||||
* UNDERWRITING --REJECT-----> REJECTED (reject_reason/decision_at/reviewer)
|
||||
* APPROVED/REJECTED 는 종단 상태로 모든 전이를 거부한다.
|
||||
* 입력: T_ID1(app_id), T_STR1(action), T_STR3(reviewer 선택), T_REASON(반려사유 선택).
|
||||
* 출력: T_STATUS=새 status, T_STR2=merchant_id, T_RC.
|
||||
* 부적법 전이는 T_RC/T_MSG 세팅 후 FAIL(글로벌 트랜잭션 롤백).
|
||||
* 호출자 XA 브랜치에서 수행(EXEC SQL CONNECT 없음). mm_svr 가 tpsvrinit 에서 광고.
|
||||
*/
|
||||
#include "MM_ONBOARD.h"
|
||||
|
||||
/* MM_ONBOARD - 가맹점 심사 상태기계 전이. */
|
||||
void MM_ONBOARD(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char action[24], reviewer[64], reason[160];
|
||||
int legal = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_app_id, h_logid;
|
||||
char h_action[24], h_cur[16], h_new[16], h_mid[32];
|
||||
char h_reviewer[64], h_reason[160], h_svc[24], h_msg[200];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
/* 지역/호스트 변수 초기화 (DECLARE SECTION 밖) */
|
||||
h_app_id = h_logid = 0;
|
||||
action[0] = reviewer[0] = reason[0] = 0;
|
||||
h_action[0] = h_cur[0] = h_new[0] = h_mid[0] = 0;
|
||||
h_reviewer[0] = h_reason[0] = 0;
|
||||
strcpy(h_svc, "MM_ONBOARD");
|
||||
userlog("[MM_ONBOARD] 심사 진행 진입");
|
||||
|
||||
/* [1] 입력 검증부 -------------------------------------------------- */
|
||||
h_app_id = getl(b, T_ID1);
|
||||
if (h_app_id <= 0) {
|
||||
setl(b, T_RC, 7001);
|
||||
Bchg(b, T_MSG, 0, "신청 ID(app_id) 필수", 0L);
|
||||
userlog("[MM_ONBOARD] app_id 검증 실패 id=%ld", h_app_id);
|
||||
FAIL(b);
|
||||
}
|
||||
gets_(b, T_STR1, action, sizeof(action));
|
||||
if (strcmp(action, "UNDERWRITE") != 0 &&
|
||||
strcmp(action, "APPROVE") != 0 &&
|
||||
strcmp(action, "REJECT") != 0) {
|
||||
setl(b, T_RC, 7002);
|
||||
Bchg(b, T_MSG, 0, "action 은 UNDERWRITE/APPROVE/REJECT 중 하나여야 함", 0L);
|
||||
userlog("[MM_ONBOARD] 부적합 action=[%s]", action);
|
||||
FAIL(b);
|
||||
}
|
||||
strncpy(h_action, action, sizeof(h_action)-1); h_action[sizeof(h_action)-1] = 0;
|
||||
|
||||
/* reviewer / reject 사유(선택 입력) */
|
||||
gets_(b, T_STR3, reviewer, sizeof(reviewer));
|
||||
if (reviewer[0] == 0) strcpy(reviewer, "AUTO");
|
||||
strncpy(h_reviewer, reviewer, sizeof(h_reviewer)-1); h_reviewer[sizeof(h_reviewer)-1] = 0;
|
||||
gets_(b, T_REASON, reason, sizeof(reason));
|
||||
|
||||
/* [2] 현재 상태 조회부 -------------------------------------------- */
|
||||
EXEC SQL SELECT status, coalesce(merchant_id,'')
|
||||
INTO :h_cur, :h_mid
|
||||
FROM mm_application WHERE app_id = :h_app_id;
|
||||
if (sqlca.sqlcode == 100) {
|
||||
setl(b, T_RC, 7003);
|
||||
Bchg(b, T_MSG, 0, "신청 원장 미존재", 0L);
|
||||
userlog("[MM_ONBOARD] 신청 미존재 app_id=%ld", h_app_id);
|
||||
FAIL(b);
|
||||
} else if (sqlca.sqlcode < 0) {
|
||||
userlog("[MM_ONBOARD] 신청 조회 오류 [%d]", sqlca.sqlcode);
|
||||
FAIL(b);
|
||||
}
|
||||
userlog("[MM_ONBOARD] app_id=%ld 현재상태=%s action=%s", h_app_id, h_cur, h_action);
|
||||
|
||||
/* [3] 상태기계 전이 판정부 (부적법 전이 거부) --------------------- */
|
||||
if (strcmp(h_action, "UNDERWRITE") == 0) {
|
||||
if (strcmp(h_cur, "RECEIVED") == 0) { strcpy(h_new, "UNDERWRITING"); legal = 1; }
|
||||
} else if (strcmp(h_action, "APPROVE") == 0) {
|
||||
if (strcmp(h_cur, "UNDERWRITING") == 0) { strcpy(h_new, "APPROVED"); legal = 1; }
|
||||
} else if (strcmp(h_action, "REJECT") == 0) {
|
||||
if (strcmp(h_cur, "UNDERWRITING") == 0) { strcpy(h_new, "REJECTED"); legal = 1; }
|
||||
}
|
||||
if (!legal) {
|
||||
setl(b, T_RC, 7010);
|
||||
snprintf(h_msg, sizeof(h_msg),
|
||||
"부적법 전이 거부: %s 상태에서 %s 불가", h_cur, h_action);
|
||||
Bchg(b, T_MSG, 0, h_msg, 0L);
|
||||
userlog("[MM_ONBOARD] %s", h_msg);
|
||||
FAIL(b);
|
||||
}
|
||||
|
||||
/* [4] 본처리부: 상태별 UPDATE ------------------------------------- */
|
||||
if (strcmp(h_new, "UNDERWRITING") == 0) {
|
||||
EXEC SQL UPDATE mm_application SET status = 'UNDERWRITING'
|
||||
WHERE app_id = :h_app_id;
|
||||
if (sqlca.sqlcode < 0) { userlog("[MM_ONBOARD] UNDERWRITING 갱신 실패"); FAIL(b); }
|
||||
h_mid[0] = 0; /* 아직 MID 미발급 */
|
||||
} else if (strcmp(h_new, "APPROVED") == 0) {
|
||||
/* merchant_id 발급: 'M' + app_id zero-padding (호스트변수 캐스팅 회피, C에서 조립) */
|
||||
snprintf(h_mid, sizeof(h_mid), "M%09ld", h_app_id);
|
||||
EXEC SQL UPDATE mm_application
|
||||
SET status = 'APPROVED', merchant_id = :h_mid,
|
||||
reviewer = :h_reviewer, decision_at = now()
|
||||
WHERE app_id = :h_app_id;
|
||||
if (sqlca.sqlcode < 0) { userlog("[MM_ONBOARD] APPROVED 갱신 실패"); FAIL(b); }
|
||||
userlog("[MM_ONBOARD] 승인 app_id=%ld mid=[%s] reviewer=[%s]",
|
||||
h_app_id, h_mid, h_reviewer);
|
||||
} else { /* REJECTED */
|
||||
if (reason[0] == 0) strcpy(reason, "심사 반려");
|
||||
strncpy(h_reason, reason, sizeof(h_reason)-1); h_reason[sizeof(h_reason)-1] = 0;
|
||||
EXEC SQL UPDATE mm_application
|
||||
SET status = 'REJECTED', reviewer = :h_reviewer,
|
||||
reject_reason = :h_reason, decision_at = now()
|
||||
WHERE app_id = :h_app_id;
|
||||
if (sqlca.sqlcode < 0) { userlog("[MM_ONBOARD] REJECTED 갱신 실패"); FAIL(b); }
|
||||
h_mid[0] = 0;
|
||||
userlog("[MM_ONBOARD] 반려 app_id=%ld reason=[%s]", h_app_id, h_reason);
|
||||
}
|
||||
|
||||
/* [5] 이력/감사 적재부 (cm_log) ----------------------------------- */
|
||||
EXEC SQL SELECT nextval('cm_log_seq') INTO :h_logid;
|
||||
if (sqlca.sqlcode < 0) { userlog("[MM_ONBOARD] 로그 시퀀스 실패"); FAIL(b); }
|
||||
snprintf(h_msg, sizeof(h_msg), "MM_ONBOARD app=%ld %s: %s -> %s mid=%s",
|
||||
h_app_id, h_action, h_cur, h_new, h_mid[0] ? h_mid : "-");
|
||||
EXEC SQL INSERT INTO cm_log (log_id, svc_name, log_level, msg, biz_date)
|
||||
VALUES (:h_logid, :h_svc, 'I', :h_msg, current_date);
|
||||
if (sqlca.sqlcode < 0) { userlog("[MM_ONBOARD] 감사 로그 적재 실패 [%d]", sqlca.sqlcode); FAIL(b); }
|
||||
|
||||
/* [6] 응답부 (출력 필드 설정) ------------------------------------- */
|
||||
Bchg(b, T_STATUS, 0, h_new, 0L);
|
||||
Bchg(b, T_STR2, 0, h_mid, 0L); /* 승인시 발급 MID, 그 외 빈값 */
|
||||
setl(b, T_RC, 0);
|
||||
|
||||
/* [7] 완료 로깅 --------------------------------------------------- */
|
||||
userlog("[MM_ONBOARD] 전이 완료 app_id=%ld %s -> %s", h_app_id, h_cur, h_new);
|
||||
OK(b);
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 et smartindent: */
|
||||
Loading…
Add table
Add a link
Reference in a new issue