diff --git a/brochure/v1/sam-brochure-1page.pptx b/brochure/v1/sam-brochure-1page.pptx index af863d1..5fe19a4 100644 Binary files a/brochure/v1/sam-brochure-1page.pptx and b/brochure/v1/sam-brochure-1page.pptx differ diff --git a/brochure/v1/sam-brochure-2page.pptx b/brochure/v1/sam-brochure-2page.pptx index 26a7357..016084a 100644 Binary files a/brochure/v1/sam-brochure-2page.pptx and b/brochure/v1/sam-brochure-2page.pptx differ diff --git a/brochure/v1/slides/brochure-1page.html b/brochure/v1/slides/brochure-1page.html index 6e54695..8eea8ab 100644 --- a/brochure/v1/slides/brochure-1page.html +++ b/brochure/v1/slides/brochure-1page.html @@ -197,10 +197,12 @@
-

SAM

-

www.sam.it.kr

+

(주)코드브릿지엑스

+

www.codebridge-x.com

+

무료 데모 및 상담

+

contact@codebridge-x.com

diff --git a/brochure/v1/slides/brochure-2page-back.html b/brochure/v1/slides/brochure-2page-back.html index fbd68ab..a285d16 100644 --- a/brochure/v1/slides/brochure-2page-back.html +++ b/brochure/v1/slides/brochure-2page-back.html @@ -209,17 +209,19 @@
+

무료 데모를 신청하세요

귀사에 최적화된 맞춤 데모를 제공합니다

-

www.sam.it.kr

+

contact@codebridge-x.com

+

www.codebridge-x.com

-

SAM — Smart Automation Management

+

(주)코드브릿지엑스 | SAM - Smart Automation Management

\ No newline at end of file diff --git a/brochure/v1/slides/brochure-2page-front.html b/brochure/v1/slides/brochure-2page-front.html index ae770d9..fe6da03 100644 --- a/brochure/v1/slides/brochure-2page-front.html +++ b/brochure/v1/slides/brochure-2page-front.html @@ -110,8 +110,8 @@
-

SAM

-

www.sam.it.kr

+

(주)코드브릿지엑스

+

www.codebridge-x.com

뒷면에서 상세 기능과 가격을 확인하세요

diff --git a/brochure/v2/sam-brochure-v2-dashboard-1page.pptx b/brochure/v2/sam-brochure-v2-dashboard-1page.pptx index 929effc..d5fb878 100644 Binary files a/brochure/v2/sam-brochure-v2-dashboard-1page.pptx and b/brochure/v2/sam-brochure-v2-dashboard-1page.pptx differ diff --git a/brochure/v2/sam-brochure-v2-dashboard-2page.pptx b/brochure/v2/sam-brochure-v2-dashboard-2page.pptx index dd6039a..315707d 100644 Binary files a/brochure/v2/sam-brochure-v2-dashboard-2page.pptx and b/brochure/v2/sam-brochure-v2-dashboard-2page.pptx differ diff --git a/brochure/v2/slides/brochure-dashboard-1page.html b/brochure/v2/slides/brochure-dashboard-1page.html index 8e1c3cb..eca646a 100644 --- a/brochure/v2/slides/brochure-dashboard-1page.html +++ b/brochure/v2/slides/brochure-dashboard-1page.html @@ -248,10 +248,12 @@
-

SAM

-

www.sam.it.kr

+

(주)코드브릿지엑스

+

www.codebridge-x.com

+

무료 데모 신청

+

contact@codebridge-x.com

diff --git a/brochure/v2/slides/brochure-dashboard-back.html b/brochure/v2/slides/brochure-dashboard-back.html index 2f446f0..147b8bf 100644 --- a/brochure/v2/slides/brochure-dashboard-back.html +++ b/brochure/v2/slides/brochure-dashboard-back.html @@ -224,17 +224,19 @@
+

무료 데모를 신청하세요

대표님 전용 대시보드를 직접 체험해 보세요

-

www.sam.it.kr

+

contact@codebridge-x.com

+

www.codebridge-x.com

-

SAM — Smart Automation Management

+

(주)코드브릿지엑스 | SAM - Smart Automation Management

\ No newline at end of file diff --git a/brochure/v2/slides/brochure-dashboard-front.html b/brochure/v2/slides/brochure-dashboard-front.html index ac67529..0df1434 100644 --- a/brochure/v2/slides/brochure-dashboard-front.html +++ b/brochure/v2/slides/brochure-dashboard-front.html @@ -160,8 +160,8 @@
-

SAM

-

www.sam.it.kr

+

(주)코드브릿지엑스

+

www.codebridge-x.com

뒷면에서 상세 기능을 확인하세요

diff --git a/brochure/v3/sam-brochure-v3-dashboard-1page.pptx b/brochure/v3/sam-brochure-v3-dashboard-1page.pptx index 307d933..cbb6084 100644 Binary files a/brochure/v3/sam-brochure-v3-dashboard-1page.pptx and b/brochure/v3/sam-brochure-v3-dashboard-1page.pptx differ diff --git a/brochure/v3/sam-brochure-v3-dashboard-2page.pptx b/brochure/v3/sam-brochure-v3-dashboard-2page.pptx index 0a97e40..cdc1014 100644 Binary files a/brochure/v3/sam-brochure-v3-dashboard-2page.pptx and b/brochure/v3/sam-brochure-v3-dashboard-2page.pptx differ diff --git a/brochure/v3/slides/brochure-dashboard-1page.html b/brochure/v3/slides/brochure-dashboard-1page.html index f6316e2..8547c7d 100644 --- a/brochure/v3/slides/brochure-dashboard-1page.html +++ b/brochure/v3/slides/brochure-dashboard-1page.html @@ -392,10 +392,12 @@
-

SAM

-

www.sam.it.kr

+

(주)코드브릿지엑스

+

www.codebridge-x.com

+

무료 데모 신청

+

contact@codebridge-x.com

diff --git a/brochure/v3/slides/brochure-dashboard-back.html b/brochure/v3/slides/brochure-dashboard-back.html index 95eb751..f199750 100644 --- a/brochure/v3/slides/brochure-dashboard-back.html +++ b/brochure/v3/slides/brochure-dashboard-back.html @@ -354,18 +354,20 @@
+

무료 데모를 신청하세요

대표님 전용 대시보드를 직접 체험

-

www.sam.it.kr

+

contact@codebridge-x.com

+

www.codebridge-x.com

-

SAM — Smart Automation Management

+

(주)코드브릿지엑스 | SAM - Smart Automation Management

\ No newline at end of file diff --git a/brochure/v3/slides/brochure-dashboard-front.html b/brochure/v3/slides/brochure-dashboard-front.html index 5223cb5..b1d8828 100644 --- a/brochure/v3/slides/brochure-dashboard-front.html +++ b/brochure/v3/slides/brochure-dashboard-front.html @@ -250,8 +250,8 @@
-

SAM

-

www.sam.it.kr

+

(주)코드브릿지엑스

+

www.codebridge-x.com

뒷면에서 상세 기능을 확인하세요 ▶

diff --git a/brochure/v4/sam-brochure-v4-dashboard-1page.pptx b/brochure/v4/sam-brochure-v4-dashboard-1page.pptx index 2ec5fe9..747d4f4 100644 Binary files a/brochure/v4/sam-brochure-v4-dashboard-1page.pptx and b/brochure/v4/sam-brochure-v4-dashboard-1page.pptx differ diff --git a/brochure/v4/sam-brochure-v4-dashboard-2page.pptx b/brochure/v4/sam-brochure-v4-dashboard-2page.pptx index 84ae7aa..c56e36e 100644 Binary files a/brochure/v4/sam-brochure-v4-dashboard-2page.pptx and b/brochure/v4/sam-brochure-v4-dashboard-2page.pptx differ diff --git a/brochure/v4/slides/brochure-dashboard-1page.html b/brochure/v4/slides/brochure-dashboard-1page.html index 7920035..8792a24 100644 --- a/brochure/v4/slides/brochure-dashboard-1page.html +++ b/brochure/v4/slides/brochure-dashboard-1page.html @@ -392,10 +392,12 @@
-

SAM

-

www.sam.it.kr

+

(주)코드브릿지엑스

+

www.codebridge-x.com

+

무료 데모 신청

+

contact@codebridge-x.com

diff --git a/brochure/v4/slides/brochure-dashboard-back.html b/brochure/v4/slides/brochure-dashboard-back.html index 3de9eb6..6b64b85 100644 --- a/brochure/v4/slides/brochure-dashboard-back.html +++ b/brochure/v4/slides/brochure-dashboard-back.html @@ -354,18 +354,20 @@
+

무료 데모를 신청하세요

대표님 전용 대시보드를 직접 체험

-

www.sam.it.kr

+

contact@codebridge-x.com

+

www.codebridge-x.com

-

SAM — Smart Automation Management

+

(주)코드브릿지엑스 | SAM - Smart Automation Management

\ No newline at end of file diff --git a/brochure/v4/slides/brochure-dashboard-front.html b/brochure/v4/slides/brochure-dashboard-front.html index 98d48c7..8f4165f 100644 --- a/brochure/v4/slides/brochure-dashboard-front.html +++ b/brochure/v4/slides/brochure-dashboard-front.html @@ -248,8 +248,8 @@
-

SAM

-

www.sam.it.kr

+

(주)코드브릿지엑스

+

www.codebridge-x.com

뒷면에서 상세 기능을 확인하세요 ▶

diff --git a/brochure/v5/sam-brochure-v5-dashboard-1page.pptx b/brochure/v5/sam-brochure-v5-dashboard-1page.pptx index f6b930e..60194bf 100644 Binary files a/brochure/v5/sam-brochure-v5-dashboard-1page.pptx and b/brochure/v5/sam-brochure-v5-dashboard-1page.pptx differ diff --git a/brochure/v5/sam-brochure-v5-dashboard-2page.pptx b/brochure/v5/sam-brochure-v5-dashboard-2page.pptx index e9f9c95..e53d81c 100644 Binary files a/brochure/v5/sam-brochure-v5-dashboard-2page.pptx and b/brochure/v5/sam-brochure-v5-dashboard-2page.pptx differ diff --git a/brochure/v5/slides/brochure-dashboard-1page.html b/brochure/v5/slides/brochure-dashboard-1page.html index 9c1105e..6e8d331 100644 --- a/brochure/v5/slides/brochure-dashboard-1page.html +++ b/brochure/v5/slides/brochure-dashboard-1page.html @@ -306,10 +306,12 @@
-

SAM

-

www.sam.it.kr

+

(주)코드브릿지엑스

+

www.codebridge-x.com

+

무료 데모 신청

+

contact@codebridge-x.com

diff --git a/brochure/v5/slides/brochure-dashboard-back.html b/brochure/v5/slides/brochure-dashboard-back.html index 46012b5..aa9f629 100644 --- a/brochure/v5/slides/brochure-dashboard-back.html +++ b/brochure/v5/slides/brochure-dashboard-back.html @@ -292,18 +292,20 @@
+

무료 데모를 신청하세요

대표님 전용 대시보드를 직접 체험

-

www.sam.it.kr

+

contact@codebridge-x.com

+

www.codebridge-x.com

-

SAM — Smart Automation Management

+

(주)코드브릿지엑스 | SAM - Smart Automation Management

\ No newline at end of file diff --git a/brochure/v5/slides/brochure-dashboard-front.html b/brochure/v5/slides/brochure-dashboard-front.html index 013a249..ba19d78 100644 --- a/brochure/v5/slides/brochure-dashboard-front.html +++ b/brochure/v5/slides/brochure-dashboard-front.html @@ -204,8 +204,8 @@
-

SAM

-

www.sam.it.kr

+

(주)코드브릿지엑스

+

www.codebridge-x.com

뒷면에서 상세 기능을 확인하세요 ▶

diff --git a/brochure/v6/sam-brochure-v6-dashboard-1page.pptx b/brochure/v6/sam-brochure-v6-dashboard-1page.pptx index 0fbb21d..a9fa7c0 100644 Binary files a/brochure/v6/sam-brochure-v6-dashboard-1page.pptx and b/brochure/v6/sam-brochure-v6-dashboard-1page.pptx differ diff --git a/brochure/v6/sam-brochure-v6-dashboard-2page.pptx b/brochure/v6/sam-brochure-v6-dashboard-2page.pptx index 406787c..8c54f02 100644 Binary files a/brochure/v6/sam-brochure-v6-dashboard-2page.pptx and b/brochure/v6/sam-brochure-v6-dashboard-2page.pptx differ diff --git a/brochure/v6/slides/brochure-dashboard-1page.html b/brochure/v6/slides/brochure-dashboard-1page.html index 4afb7db..20ee484 100644 --- a/brochure/v6/slides/brochure-dashboard-1page.html +++ b/brochure/v6/slides/brochure-dashboard-1page.html @@ -359,10 +359,12 @@
-

SAM

-

www.sam.it.kr

+

(주)코드브릿지엑스

+

www.codebridge-x.com

+

무료 데모 신청

+

contact@codebridge-x.com

diff --git a/brochure/v6/slides/brochure-dashboard-back.html b/brochure/v6/slides/brochure-dashboard-back.html index 6cd9c34..792d610 100644 --- a/brochure/v6/slides/brochure-dashboard-back.html +++ b/brochure/v6/slides/brochure-dashboard-back.html @@ -316,18 +316,20 @@
+

무료 데모를 신청하세요

대표님 전용 대시보드를 직접 체험

-

www.sam.it.kr

+

contact@codebridge-x.com

+

www.codebridge-x.com

-

SAM — Smart Automation Management

+

(주)코드브릿지엑스 | SAM - Smart Automation Management

diff --git a/brochure/v6/slides/brochure-dashboard-front.html b/brochure/v6/slides/brochure-dashboard-front.html index d21776b..d25994a 100644 --- a/brochure/v6/slides/brochure-dashboard-front.html +++ b/brochure/v6/slides/brochure-dashboard-front.html @@ -217,8 +217,8 @@
-

SAM

-

www.sam.it.kr

+

(주)코드브릿지엑스

+

www.codebridge-x.com

뒷면에서 상세 기능을 확인하세요 ▶

diff --git a/brochure/v7/sam-brochure-v7-dashboard-1page.pptx b/brochure/v7/sam-brochure-v7-dashboard-1page.pptx index 3fb887d..6f12fd7 100644 Binary files a/brochure/v7/sam-brochure-v7-dashboard-1page.pptx and b/brochure/v7/sam-brochure-v7-dashboard-1page.pptx differ diff --git a/brochure/v7/sam-brochure-v7-dashboard-2page.pptx b/brochure/v7/sam-brochure-v7-dashboard-2page.pptx index 9f37b2f..20a6bd1 100644 Binary files a/brochure/v7/sam-brochure-v7-dashboard-2page.pptx and b/brochure/v7/sam-brochure-v7-dashboard-2page.pptx differ diff --git a/brochure/v7/slides/brochure-dashboard-1page.html b/brochure/v7/slides/brochure-dashboard-1page.html index ccba1ba..4cde3f3 100644 --- a/brochure/v7/slides/brochure-dashboard-1page.html +++ b/brochure/v7/slides/brochure-dashboard-1page.html @@ -363,10 +363,12 @@
-

SAM

-

www.sam.it.kr

+

(주)코드브릿지엑스

+

www.codebridge-x.com

+

무료 데모 신청

+

contact@codebridge-x.com

diff --git a/brochure/v7/slides/brochure-dashboard-back.html b/brochure/v7/slides/brochure-dashboard-back.html index aab44bf..7298655 100644 --- a/brochure/v7/slides/brochure-dashboard-back.html +++ b/brochure/v7/slides/brochure-dashboard-back.html @@ -354,18 +354,20 @@
+

무료 데모를 신청하세요

대표님 전용 대시보드를 직접 체험

-

www.sam.it.kr

+

contact@codebridge-x.com

+

www.codebridge-x.com

-

SAM — Smart Automation Management

+

(주)코드브릿지엑스 | SAM - Smart Automation Management

\ No newline at end of file diff --git a/brochure/v7/slides/brochure-dashboard-front.html b/brochure/v7/slides/brochure-dashboard-front.html index 8d72199..1a4ccdd 100644 --- a/brochure/v7/slides/brochure-dashboard-front.html +++ b/brochure/v7/slides/brochure-dashboard-front.html @@ -266,8 +266,8 @@
-

SAM

-

www.sam.it.kr

+

(주)코드브릿지엑스

+

www.codebridge-x.com

뒷면에서 상세 기능을 확인하세요 ▶

diff --git a/brochure/v8/sam-brochure-v8-dashboard-1page.pptx b/brochure/v8/sam-brochure-v8-dashboard-1page.pptx index 4f20645..4a2c33d 100644 Binary files a/brochure/v8/sam-brochure-v8-dashboard-1page.pptx and b/brochure/v8/sam-brochure-v8-dashboard-1page.pptx differ diff --git a/brochure/v8/sam-brochure-v8-dashboard-2page.pptx b/brochure/v8/sam-brochure-v8-dashboard-2page.pptx index f149d83..ade5f05 100644 Binary files a/brochure/v8/sam-brochure-v8-dashboard-2page.pptx and b/brochure/v8/sam-brochure-v8-dashboard-2page.pptx differ diff --git a/brochure/v8/slides/brochure-dashboard-1page.html b/brochure/v8/slides/brochure-dashboard-1page.html index bbbec34..fbf62ea 100644 --- a/brochure/v8/slides/brochure-dashboard-1page.html +++ b/brochure/v8/slides/brochure-dashboard-1page.html @@ -218,18 +218,20 @@
+

무료 데모를 신청하세요

대표님 전용 대시보드를 직접 체험

-

www.sam.it.kr

+

contact@codebridge-x.com

+

www.codebridge-x.com

-

SAM — Smart Automation Management

+

(주)코드브릿지엑스 | SAM - Smart Automation Management

diff --git a/brochure/v8/slides/brochure-dashboard-back.html b/brochure/v8/slides/brochure-dashboard-back.html index aafa592..28747b2 100644 --- a/brochure/v8/slides/brochure-dashboard-back.html +++ b/brochure/v8/slides/brochure-dashboard-back.html @@ -301,18 +301,20 @@
+

무료 데모를 신청하세요

대표님 전용 대시보드를 직접 체험

-

www.sam.it.kr

+

contact@codebridge-x.com

+

www.codebridge-x.com

-

SAM — Smart Automation Management

+

(주)코드브릿지엑스 | SAM - Smart Automation Management

\ No newline at end of file diff --git a/brochure/v8/slides/brochure-dashboard-front.html b/brochure/v8/slides/brochure-dashboard-front.html index ff7f738..10ecdb0 100644 --- a/brochure/v8/slides/brochure-dashboard-front.html +++ b/brochure/v8/slides/brochure-dashboard-front.html @@ -268,8 +268,8 @@
-

SAM

-

www.sam.it.kr

+

(주)코드브릿지엑스

+

www.codebridge-x.com

뒷면에서 상세 기능을 확인하세요 ▶

diff --git a/brochure/v9/sam-brochure-v9-dashboard-1page.pptx b/brochure/v9/sam-brochure-v9-dashboard-1page.pptx index 1b7de30..9a39ae4 100644 Binary files a/brochure/v9/sam-brochure-v9-dashboard-1page.pptx and b/brochure/v9/sam-brochure-v9-dashboard-1page.pptx differ diff --git a/brochure/v9/sam-brochure-v9-dashboard-2page.pptx b/brochure/v9/sam-brochure-v9-dashboard-2page.pptx index 2a61715..3fd20cc 100644 Binary files a/brochure/v9/sam-brochure-v9-dashboard-2page.pptx and b/brochure/v9/sam-brochure-v9-dashboard-2page.pptx differ diff --git a/brochure/v9/slides/brochure-dashboard-1page.html b/brochure/v9/slides/brochure-dashboard-1page.html index 3b707b6..d228d07 100644 --- a/brochure/v9/slides/brochure-dashboard-1page.html +++ b/brochure/v9/slides/brochure-dashboard-1page.html @@ -250,15 +250,17 @@
+

무료 데모를 신청하세요

대표님 전용 대시보드를 직접 체험

-

www.sam.it.kr

+

contact@codebridge-x.com

+

www.codebridge-x.com

-

SAM

+

(주)코드브릿지엑스

\ No newline at end of file diff --git a/brochure/v9/slides/brochure-dashboard-back.html b/brochure/v9/slides/brochure-dashboard-back.html index 6bd4f11..46e438c 100644 --- a/brochure/v9/slides/brochure-dashboard-back.html +++ b/brochure/v9/slides/brochure-dashboard-back.html @@ -211,17 +211,19 @@
+

무료 데모를 신청하세요

대표님 전용 대시보드를 직접 체험

-

www.sam.it.kr

+

contact@codebridge-x.com

+

www.codebridge-x.com

-

SAM

+

(주)코드브릿지엑스

\ No newline at end of file diff --git a/brochure/v9/slides/brochure-dashboard-front.html b/brochure/v9/slides/brochure-dashboard-front.html index 87a7f93..dc52623 100644 --- a/brochure/v9/slides/brochure-dashboard-front.html +++ b/brochure/v9/slides/brochure-dashboard-front.html @@ -172,8 +172,8 @@
-

SAM

-

www.sam.it.kr

+

(주)코드브릿지엑스

+

www.codebridge-x.com

뒷면에서 상세 기능을 확인하세요

diff --git a/features/barobill-kakaotalk/README.md b/features/barobill-kakaotalk/README.md index 151f1fb..09f1909 100644 --- a/features/barobill-kakaotalk/README.md +++ b/features/barobill-kakaotalk/README.md @@ -1,9 +1,9 @@ # 바로빌 카카오톡 (알림톡/친구톡) 연동 -> **문서 버전**: 1.0 +> **문서 버전**: 1.1 > **작성일**: 2026-02-14 -> **최종 수정**: 2026-02-24 -> **상태**: 운영 중 (전자계약 알림톡 발송 완료) +> **최종 수정**: 2026-02-27 +> **상태**: 운영 중 (알림톡 + SMS + 환경별 분기 완료) > **대상 프로젝트**: MNG --- @@ -25,7 +25,11 @@ | 채널 연동 (바로빌↔카카오) | **완료** (2026-02-20) | 바로빌 관리 URL에서 채널 연동 처리 | | 바로빌 파트너 과금 설정 | **완료** (2026-02-23) | 바로빌 측에서 파트너사 과금 설정 완료 | | 알림톡 템플릿 v1 검수 | **완료** (2026-02-22) | `전자계약_서명요청`, `전자계약_리마인드` 2종 승인 | -| 알림톡 템플릿 v2 검수 | **심사 중** (2026-02-24 접수) | 버튼 URL에 `#{토큰}` 변수 포함 2종 재등록 | +| 알림톡 템플릿 v2 검수 | **완료** (2026-02-25) | 버튼 URL에 `#{토큰}` 변수 포함 3종 승인 | +| 알림톡 `전자계약_완료` | **완료** (2026-02-26) | 서명 완료 알림 발송용 템플릿 승인 | +| 역할 기반 알림 분기 | **완료** (2026-02-26) | 본사=이메일, 상대방=알림톡/SMS | +| 환경별 템플릿 분기 | **완료** (2026-02-27) | `_DEV` 접미사 개발 템플릿 등록 | +| DEV 템플릿 검수 | **심사 중** (2026-02-27 접수) | 개발서버용 3종 (`admin.codebridge-x.com`) | > 상세 등록 가이드: [카카오톡 알림톡 채널 및 템플릿 등록 가이드](../../guides/카카오톡-알림톡-채널-템플릿-등록.md) @@ -310,14 +314,24 @@ $params = [ | 전달 결과 확인 (2단계) | **구현 완료** | 2026-02-24 | | 로그인 페이지 서명 확인 | **성공** | 2026-02-24 | -### 5.3 대기 중인 항목 +### 5.3 완료된 추가 항목 (2026-02-26~27) | 항목 | 상태 | 비고 | |------|------|------| -| 템플릿 v2 승인 | **심사 중** | 버튼 URL에 `#{토큰}` 변수 포함 | -| v2 승인 후 코드 수정 | **대기** | 동적 서명 URL을 버튼에 전달 | -| `전자계약_완료` 템플릿 | **미등록** | 서명 완료 알림 발송용 | -| SMS 대체발송 | **미설정** | 발신번호 등록 필요 | +| 템플릿 v2 승인 | **완료** | 버튼 URL에 `#{토큰}` 변수 포함 3종 승인 | +| `전자계약_완료` 템플릿 | **완료** | 서명 완료 알림 발송 — PDF 다운로드 버튼 | +| 역할 기반 알림 분기 | **완료** | 본사(creator)=이메일, 상대방(counterpart)=알림톡 | +| OTP SMS 발송 | **완료** | 상대방에게 SMS로 인증코드 발송 | +| 환경별 템플릿 분기 | **완료** | `resolveTemplateName()` — `_DEV` 접미사 자동 적용 | +| 서명 PDF 재생성 | **완료** | `downloadDocument()`에서 완료 계약 PDF 자동 재생성 | + +> 상세 가이드: [전자계약 알림톡/SMS 환경별 설정 가이드](./esign-notification-guide.md) + +### 5.4 대기 중인 항목 + +| 항목 | 상태 | 비고 | +|------|------|------| +| DEV 템플릿 검수 | **심사 중** | `admin.codebridge-x.com` 도메인 3종 | | 친구톡 발송 | **대기** | 채널 친구 추가 후 가능 | | 대량 발송 | **대기** | 단건 안정화 후 | @@ -377,37 +391,7 @@ $buttons = [ --- -## 8. API 측 바로빌 연동 (세금계산서) - -MNG의 카카오톡 연동 외에, API(`api/`)에서도 바로빌 서비스를 사용한다: - -### 8.1 바로빌 설정 API - -| HTTP | URI | 설명 | -|------|-----|------| -| GET | `/v1/barobill-settings` | 바로빌 설정 조회 | -| PUT | `/v1/barobill-settings` | 바로빌 설정 저장 (사업자번호, 인증키, 자동발행 등) | -| POST | `/v1/barobill-settings/test-connection` | 연동 테스트 | - -### 8.2 세금계산서 발행 - -`BarobillService`는 세금계산서 발행/취소/국세청 전송 상태 조회도 담당한다: - -| API 메서드 | 설명 | -|-----------|------| -| `issueTaxInvoice()` | 세금계산서 발행 (RegistAndIssueTaxInvoice) | -| `cancelTaxInvoice()` | 세금계산서 취소 | -| `checkNtsSendStatus()` | 국세청 전송 상태 조회 | -| `checkBusinessNumber()` | 사업자번호 휴폐업 조회 | -| `testConnection()` | GetAccessToken으로 연동 테스트 | - -**인증키 보안:** `cert_key`는 Laravel `Crypt` 파사드로 자동 암/복호화 - -→ 상세: [세금계산서 관리](../finance/tax-invoices.md) - ---- - -## 9. 참고 자료 +## 8. 참고 자료 - [바로빌 API 문서](https://dev.barobill.co.kr) - [카카오비즈니스 채널 관리](https://business.kakao.com) @@ -420,6 +404,7 @@ MNG의 카카오톡 연동 외에, API(`api/`)에서도 바로빌 서비스를 | 날짜 | 버전 | 변경 내용 | |------|------|----------| +| 2026-02-27 | 1.1 | 역할 기반 알림, OTP SMS, 환경별 템플릿 분기, 완료 알림톡 추가 | | 2026-02-24 | 1.0 | 전자계약 알림톡 연동 완료, 트러블슈팅 문서화, v2 템플릿 가이드 추가 | | 2026-02-14 | 0.2 | 전자계약(E-Sign) 알림톡 연동 활용 계획 추가 | | 2026-02-14 | 0.1 | 초안 작성 - 코드 구현 완료, 실 서비스 연동 대기 | diff --git a/features/documents/README.md b/features/documents/README.md index 91f3dd9..ab1f4d5 100644 --- a/features/documents/README.md +++ b/features/documents/README.md @@ -111,10 +111,12 @@ DRAFT → PENDING → APPROVED ## 관련 문서 +- [MNG 문서관리 시스템 상세](mng-document-system.md) — MNG 화면 구성, 탭별 기능, 서식 빌더, EAV 저장 패턴 상세 +- [MNG 문서양식관리](mng-document-template.md) — 서식 생성/편집, Legacy/Block Builder, 프리셋, 연결품목 관리 - [DB 스키마 — 문서/전자서명](../../system/database/documents.md) - [게시판 시스템](../boards/README.md) — 유사한 EAV 패턴 적용 - Swagger: `/api-docs` → Documents 섹션 --- -**최종 업데이트**: 2026-02-27 +**최종 업데이트**: 2026-03-06 diff --git a/projects/index_projects.md b/projects/index_projects.md index b08bbb9..7ce5106 100644 --- a/projects/index_projects.md +++ b/projects/index_projects.md @@ -1,7 +1,7 @@ # 프로젝트 문서 인덱스 > SAM 시스템 개발 프로젝트별 문서 모음 -> **최종 업데이트**: 2026-02-12 +> **최종 업데이트**: 2026-03-08 --- @@ -18,6 +18,8 @@ | [auto-login](#auto-login---자동-로그인) | ⚪ 대기 | 자동 로그인 기능 | | [migration-5130-mng](#migration-5130-mng---5130--mng-마이그레이션) | 🟡 진행중 | 5130 → mng 통합 마이그레이션 | | [e-sign](#e-sign---전자계약-서명) | 🟢 v1.0 구현 완료 | 전자계약 서명 솔루션 (SAM E-Sign) | +| [org-chart](#org-chart---조직도-관리) | 🟢 v1.0 구현 완료 | 트리형 조직도 관리 (드래그앤드롭, 숨기기) | +| [planning-design](#planning-design---기획디자인-스토리보드-에디터) | 🟢 v1.2 운영 중 | 브라우저 블록 에디터 (Notion/Figma 스타일) | --- @@ -204,6 +206,53 @@ --- +### org-chart - 조직도 관리 + +**경로**: `docs/projects/org-chart/` +**상태**: 🟢 v1.0 구현 완료 (2026-03-06) +**목표**: 테넌트별 조직 구조를 시각적으로 관리하는 트리형 조직도 + +**핵심 문서**: +- [README.md](./org-chart/README.md) - 기술 문서 (아키텍처, API, DB, 프론트엔드 상세) + +**구현 범위**: + +| 영역 | 수량 | +|------|------| +| MNG 컨트롤러 메서드 | 7개 (RdController) | +| API 엔드포인트 | 6개 (조회, 배치, 해제, 순서변경, 숨기기) | +| DB 마이그레이션 | 1개 (departments.options JSON 추가) | +| 뷰 | 1개 (Alpine.js + SortableJS) | + +**기술 스택**: Alpine.js + SortableJS + 수동 DOM 렌더링 (x-for 미사용) + +--- + +### planning-design - 기획디자인 스토리보드 에디터 + +**경로**: `docs/projects/planning-design/` +**상태**: 🟢 v1.2 운영 중 (고도화 진행중) +**목표**: 브라우저 내 Notion/Figma 스타일 블록 에디터로 ERP 화면 기획서 작성 + +**핵심 문서**: +- [README.md](./planning-design/README.md) - 프로젝트 개요 및 구현 이력 + +**구현 범위**: + +| 영역 | 수량 | +|------|------| +| 블록 유형 | 15종 (텍스트/레이아웃/UI모형/미디어/체크리스트) | +| 편집 기능 | 올가미 선택, Undo/Redo, 복사/잘라내기, 서식 | +| 서식 시스템 | 글자색/배경색/크기/굵기/기울임/정렬/z-index | +| 작업 영역 | 사이드바/Description 접기/펼치기, 캔버스 폭 자동 확장 | +| 출력 | HTML 내보내기 + A4 인쇄 (좌표 기반 WYSIWYG) | + +**기술 스택**: Alpine.js + localStorage (서버 API 없음) + +**기술 스펙**: [features/rd/planning-design.md](../features/rd/planning-design.md) + +--- + ## 디렉토리 구조 ``` @@ -232,7 +281,9 @@ docs/projects/ ├── mng-mobile-responsive/ # 모바일 반응형 ├── auto-login/ # 자동 로그인 ├── migration-5130-mng/ # 5130→mng 마이그레이션 -└── e-sign/ # 전자계약 서명 (SAM E-Sign) +├── e-sign/ # 전자계약 서명 (SAM E-Sign) +├── org-chart/ # 조직도 관리 +└── planning-design/ # 기획디자인 스토리보드 에디터 ``` --- @@ -240,7 +291,7 @@ docs/projects/ ## 관련 문서 - [docs/INDEX.md](../INDEX.md) - 전체 문서 인덱스 -- [docs/dev_plans/index_plans.md](../plans/index_plans.md) - 기획 문서 인덱스 +- [docs/plans/index_plans.md](../plans/index_plans.md) - 기획 문서 인덱스 - [docs/guides/PROJECT_DEVELOPMENT_POLICY.md](../guides/PROJECT_DEVELOPMENT_POLICY.md) - 공통 개발 정책 - [CURRENT_WORKS.md](../../CURRENT_WORKS.md) - 현재 작업 diff --git a/rules/billing-policy.md b/rules/billing-policy.md index 5c2dce0..56a5966 100644 --- a/rules/billing-policy.md +++ b/rules/billing-policy.md @@ -54,8 +54,7 @@ SAM 프로젝트의 과금정책 중 **본사 지출 원가**, **마진 구조** |--------|--------|------| | 계좌조회 | 10,000원 | 고객 부담 | | 카드내역 | 10,000원 | 고객 부담 | -| 홈택스 매입 | 33,000원 (VAT 포함) | 코드브릿지엑스 지원 → 본사 부담 (무료) | -| 홈택스 매출 | 33,000원 (VAT 포함) | 코드브릿지엑스 지원 → 본사 부담 (무료) | +| 홈택스 매입/매출 | 33,000원 (VAT 포함) | 코드브릿지엑스 지원 → 본사 부담 (무료) | > **참고**: 계좌조회/카드내역 월정액은 고객에게 전가한다. 홈택스는 본사가 흡수한다. diff --git a/rules/customer-pricing.md b/rules/customer-pricing.md index e233fa6..60a9ff2 100644 --- a/rules/customer-pricing.md +++ b/rules/customer-pricing.md @@ -92,7 +92,7 @@ SAM 서비스 도입 시 고객에게 안내하는 요금 체계를 정리한다 |--------|---------|---------|---------|----------| | 계좌조회 | 월정액 10,000원 | 1계좌 | 추가 1계좌당 10,000원 | 고객 | | 카드내역 | 월정액 10,000원 | 5장 | 추가 1장당 5,000원 | 고객 | -| 홈택스 매입/매출 | 월 33,000원 × 2 | - | - | 본사 (무료) | +| 홈택스 매입/매출 | 월 33,000원 | - | - | 본사 (무료) | | 세금계산서 발행 | 건별 | 100건 | 추가 50건당 5,000원 | 고객 | > **과금 계산 예시**: diff --git a/rules/slides/billing-policy/slide-03.html b/rules/slides/billing-policy/slide-03.html index c32f344..b1e7126 100644 --- a/rules/slides/billing-policy/slide-03.html +++ b/rules/slides/billing-policy/slide-03.html @@ -50,18 +50,12 @@

10,000원

고객 부담 (전가)

- -
-

홈택스 매입

+ +
+

홈택스 매입/매출

33,000원

본사 흡수 (코드브릿지엑스 → 무료)

- -
-

홈택스 매출

-

33,000원

-

본사 흡수 (무료)

-
diff --git a/rules/slides/customer-pricing/slide-06.html b/rules/slides/customer-pricing/slide-06.html index d50a3e8..e3c9461 100644 --- a/rules/slides/customer-pricing/slide-06.html +++ b/rules/slides/customer-pricing/slide-06.html @@ -67,7 +67,7 @@

홈택스 매입/매출

-

월 33,000원 x 2

+

월 33,000원

-

-

diff --git a/sam/coocon/쿠콘_나이스평가정보_API_개발가이드.md b/sam/coocon/쿠콘_나이스평가정보_API_개발가이드.md deleted file mode 100644 index 1c354a6..0000000 --- a/sam/coocon/쿠콘_나이스평가정보_API_개발가이드.md +++ /dev/null @@ -1,685 +0,0 @@ -# 개발가이드 나이스평가정보연계 API - -> Ver 1.0.0 -> 최종수정일: 2024-06-28 - ---- - -## 개정 내역 - -| 개정버전 | 개정일자 | 개정내용 | -|--------|----------|--------| -| 1.0.0 | 2024.06.28 | 초안작성 | - ---- - -## 목차 - -1. [개요](#1-개요) -2. [용어정의](#2-용어정의) -3. [개발절차](#3-개발절차) -4. [API 인증키](#4-api-인증키) -5. [개발가이드](#5-개발가이드) -6. [개발 유의사항](#6-개발-유의사항) -7. [결과코드](#참조-1-결과코드) - ---- - -## 1. 개요 - -### 1.1 설명 - -나이스평가 정보 연동하여 업무를 처리합니다. - -### 1.2 기본정보 - -| 항목 | 값 | -|------|-----| -| Protocol | HTTPS | -| 데이터형식 | JSON | -| Network | 인터넷망 | -| 데이터 제공방식 | 실시간 | -| Content-Type | application/json | - -### 1.3 API 목록 - -| API 명 | 환경 | URL | 설명 | -|--------|------|-----|------| -| [기업]지표-주요경영지표 (OA07) | 개발 | https://dev2.coocon.co.kr:8443/sol/gateway/oapi_relay.jsp | 업무구분 API_ID(OA07) | -| | 운영 | https://sgw.coocon.co.kr/sol/gateway/oapi_relay.jsp | | -| [기업]개요-기본정보 (OA08) | 개발 | https://dev2.coocon.co.kr:8443/sol/gateway/oapi_relay.jsp | 업무구분 API_ID(OA08) | -| | 운영 | https://sgw.coocon.co.kr/sol/gateway/oapi_relay.jsp | | -| [기업]검색-통합기업검색 (OA09) | 개발 | https://dev2.coocon.co.kr:8443/sol/gateway/oapi_relay.jsp | 업무구분 API_ID(OA09) | -| | 운영 | https://sgw.coocon.co.kr/sol/gateway/oapi_relay.jsp | | -| [기업]등급-기업평가등급 (OA10) | 개발 | https://dev2.coocon.co.kr:8443/sol/gateway/oapi_relay.jsp | 업무구분 API_ID(OA10) | -| | 운영 | https://sgw.coocon.co.kr/sol/gateway/oapi_relay.jsp | | -| [기업]등급-WATCH 등급 (OA11) | 개발 | https://dev2.coocon.co.kr:8443/sol/gateway/oapi_relay.jsp | 업무구분 API_ID(OA11) | -| | 운영 | https://sgw.coocon.co.kr/sol/gateway/oapi_relay.jsp | | -| [기업]신용-신용요약정보 (OA12) | 개발 | https://dev2.coocon.co.kr:8443/sol/gateway/oapi_relay.jsp | 업무구분 API_ID(OA12) | -| | 운영 | https://sgw.coocon.co.kr/sol/gateway/oapi_relay.jsp | | -| [기업]신용-단기연체정보 (한국신용정보원) (OA13) | 개발 | https://dev2.coocon.co.kr:8443/sol/gateway/oapi_relay.jsp | 업무구분 API_ID(OA13) | -| | 운영 | https://sgw.coocon.co.kr/sol/gateway/oapi_relay.jsp | | -| [기업]신용-신용도 판단정보(공공정보 포함) (한국신용정보원) (OA14) | 개발 | https://dev2.coocon.co.kr:8443/sol/gateway/oapi_relay.jsp | 업무구분 API_ID(OA14) | -| | 운영 | https://sgw.coocon.co.kr/sol/gateway/oapi_relay.jsp | | -| [기업]신용-신용도-판단정보 (신용정보사) (OA15) | 개발 | https://dev2.coocon.co.kr:8443/sol/gateway/oapi_relay.jsp | 업무구분 API_ID(OA15) | -| | 운영 | https://sgw.coocon.co.kr/sol/gateway/oapi_relay.jsp | | -| [기업]신용-당좌거래정지 정보 (금융결제원) (OA16) | 개발 | https://dev2.coocon.co.kr:8443/sol/gateway/oapi_relay.jsp | 업무구분 API_ID(OA16) | -| | 운영 | https://sgw.coocon.co.kr/sol/gateway/oapi_relay.jsp | | -| [기업]신용-법정관리/워크아웃정보 (OA17) | 개발 | https://dev2.coocon.co.kr:8443/sol/gateway/oapi_relay.jsp | 업무구분 API_ID(OA17) | -| | 운영 | https://sgw.coocon.co.kr/sol/gateway/oapi_relay.jsp | | - -### 1.4 서버 접속 정보 - -> 전용선 및 VPN 이용고객은 아래 서버정보 참고 - -| 구분 | IP | PORT | -|------|-----|------| -| 개발 | #1 : 183.111.160.137 | 8443 | -| 운영 | #1 : 112.175.51.59 | 443 | - -### 1.5 API 구성/흐름도 - -``` -Application COOCON API Server OpenAPI Provider - │ │ │ - │ 1. INPUT 데이터 조립 │ │ - │ - API 인증키 │ │ - │ - 사업자정보 │ │ - │ │ │ - ├──────── 2. Request ──────────>│ │ - │ │ INPUT 데이터 수신 및 재조립 │ - │ │ [쿠콘 API GW] │ - │ │ │ - │ ├────── 3. Call ──────────────>│ - │ │ [나이스평가정보 API] │ - │ │ │ - │ │<───── 4. OUTPUT 데이터 수신 ──│ - │ │ │ - │<──────── 5. Response ─────────│ │ - │ │ │ - │ OUTPUT 데이터 추출 │ │ - │ - 결과코드/메시지 │ │ - │ - 출력값 │ │ -``` - -**흐름도 설명:** -1. Application에서 INPUT 데이터를 조립하여 [나이스 API]를 호출합니다. -2. INPUT 데이터가 API 서버로 전송되고, 쿠콘 API GW에서 INPUT 데이터를 수신합니다. -3. 쿠콘 API GW에서 수신된 INPUT 데이터를 오픈 API 포맷에 맞게 조립하고, 오픈 API 제공자에게 요청 후에 응답을 수신합니다. -4. Application에 수신받은 응답데이터를 전달합니다. -5. Application에서 필요한 데이터 추출 및 파싱을 합니다. - -### 1.6 API 인터페이스 구조 - -``` -S/W 개발사 Application 서버 COOCON API 서버 -┌─────────────────────────────────┐ ┌─────────────────┐ -│ ┌────────┐ ┌────────┐ │ │ │ -│ │ 공통 │ │ INPUT │ │ Request │ OUTPUT │ -│ │ 입력 │ -> │ │ ────────────────>│ │ -│ │ 항목 │ │ │ <────────────────│ │ -│ └────────┘ └────────┘ │ Response │ │ -└─────────────────────────────────┘ └─────────────────┘ -``` - ---- - -## 2. 용어정의 - -| 용어 | 정의 | -|------|------| -| 이용기업 | API 상품을 구매하여 Application을 개발하는 회사 (S/W 개발사) | -| Application | 이용기업에서 API를 적용하려는 Application | -| COOCON API Server | COOCON에서 제공하는 API가 실행되는 서버 | -| API 인증키 | COOCON에서 제공하는 API를 호출한 이용 기관을 인증하는 고유값. 이 때 COOCON에 등록된 이용 기관의 고유 IP에서 요청(Request)된 API 호출만 정상 처리됩니다. | - ---- - -## 3. 개발절차 - -``` -┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ -│ 1 │ │ 2 │ │ 3 │ │ 4 │ -│ API │ -> │ 개발 │ -> │ 테스트 │ -> │ 운영 │ -│ 인증키 │ │ │ │ │ │ 적용 │ -└─────────┘ └─────────┘ └─────────┘ └─────────┘ -``` - ---- - -## 4. API 인증키 - -### 4.1 발급 - -API 인증키 발급 과정은 다음과 같습니다. - -1. 구매신청 담당자에게 "API 인증키 신청서"가 이메일로 전달됩니다. -2. API 이용기업 담당자는 "API 인증키 신청서" 양식을 작성하여 이메일로 답장을 보냅니다. -3. COOCON 기술지원 담당자는 신청내용 검토 후 인증키를 이메일로 발송합니다. - -### 4.2 개발 - -1. API를 이용하여 Application 개발을 합니다. -2. 자세한 내용은 "5 개발 가이드"를 참조해 주세요. - -### 4.3 테스트 - -개발 혹은 테스트 시스템에서 API 호출 테스트를 진행합니다. - -1. 개발용 API를 이용해서 테스트해야 합니다. - -**[주의사항]** - -1. 개발 혹은 테스트 시스템에서 대량거래 혹은 부하테스트 같이 짧은 시간 내에 너무 많은 거래를 테스트하면 경우에 따라서 정보제공 기관(금융사 등)에서 테스트 거래를 차단할 수 있으니 주의하시기 바랍니다. -2. 테스트 시스템에서 확인한 금융 정보는 정보제공 기관(금융사) 시스템에 따라 정확하지 않을 수 있습니다. -3. 만일 운영 API를 이용하여 테스트를 하게 되면 수수료가 발생하니 유의하시기 바랍니다. - -### 4.4 운영적용 - -개발된 Application이 운영으로 이관되면 반드시 "운영 API 인증키"로 변경해 주어야 정상 거래가 가능합니다. - ---- - -## 5. 개발가이드 - -### 5.1 공통 입력 항목 - -| 공통 입력 ID | 공통 입력 명 | 타입 | 최대길이 | 필수여부 | 비고 | -|-------------|-------------|------|---------|---------|------| -| API_KEY | 인증키 | String | 20 | 필수 | 이용기업 인증키 값 (이용기업 별로 발급됨) | -| API_ID | 업무코드 | String | 4 | 필수 | 나이스 연동: 1.3 API 목록 참조 | -| TR_SEQ | 거래일련번호 | String | 20 | 옵션 | 거래추적 용도 번호 | - ---- - -### 5.2 [기업] 신용-신용요약정보 (OA12) - -#### [INPUT] - -| 개별 입력 ID | 개별 입력 명 | 타입 | 최대길이 | 필수여부 | 비고 | -|-------------|-------------|------|---------|---------|------| -| Companykey | 사업자정보 | String | 13 | 필수 | 조회할 기업의 사업자번호, 법인번호, 업체 코드 중 한 개만 입력 | - -#### [OUTPUT] - -| 출력 항목 | 반복여부 | 출력 항목 명 | 타입 | 최대길이 | 설명 | -|---------|---------|------------|------|---------|------| -| RSLT_CD | - | 결과코드 | String | 8 | 조회 결과 코드값, 정상 00000000 | -| RSLT_MSG | - | 결과메세지 | String | 255 | 조회 결과 메시지 | -| TR_SEQ | - | 거래일련번호 | String | 20 | 거래 추적용도 번호 | -| RSLT_DATA | - | 결과데이터 | Object | - | 나이스 결과데이터 | -| request | | 요청한 값 | Object | - | 단기연체정보 요청항목 | -| requestKey | | 요청 KEY | String | 13 | 사용자가요청한 companyKey | -| requestKeyType | | 요청한 KEY 타입 | String | 6 | BIZNO: 사업자번호, CRPNO: 법인번호, UPCHECD: 업체코드 | -| data | | 기업요약 신용정보 결과 | Object | | | -| listCount | | list 건수 | integer | | | -| creditSummaryList | | 기업신용 요약정보 | Array | | | -| shorttermOverdueCnt | ● | 단기연체정보(한국신용정보원) 건수 | integer | | | -| negativeInfoBbCnt | ● | 신용도판단정보(한국신용정보원) 건수 | integer | | | -| negativeInfoPbCnt | ● | 공공정보 건수 | integer | | | -| negativeInfoCbCnt | ● | 신용도판단정보(신용정보사) 건수 | integer | | | -| suspensionInfoCnt | ● | 당좌거래정지정보 건수 | integer | | | -| workoutCnt | ● | 법정관리/워크아웃정보 건수 | integer | | | - ---- - -### 5.3 [기업]신용-단기연체정보 (한국신용정보원) (OA13) - -#### [INPUT] - -| 개별 입력 ID | 개별 입력 명 | 타입 | 최대길이 | 필수여부 | 비고 | -|-------------|-------------|------|---------|---------|------| -| Companykey | 사업자정보 | String | 13 | 필수 | 조회대상 사업자번호, 법인번호, 업체코드 중 한개만 입력 | -| reqDate | 기준일자 | String | 8 | 옵션 | 기본값(현재날짜(YYYYMMDD) 미입력시 최신일자 기준으로 조회) | - -#### [OUTPUT] - -| 출력 항목 | 반복여부 | 출력 항목 명 | 타입 | 최대길이 | 설명 | -|---------|---------|------------|------|---------|------| -| RSLT_CD | - | 결과코드 | String | 8 | 조회 결과 코드값, 정상 00000000 | -| RSLT_MSG | - | 결과 메시지 | String | 255 | 조회 결과 메시지 | -| TR_SEQ | - | 거래일련번호 | String | 20 | 거래 추적용도 번호 | -| RSLT_DATA | - | 결과데이터 | Object | - | 나이스 결과데이터 | -| request | | 요청한 값 | Object | - | 단기연체정보 요청항목 | -| requestKey | | 요청 KEY | String | 13 | 사용자가요청한 companyKey | -| requestKeyType | | 요청 KEY 타입 | String | 6 | BIZNO: 사업자번호, CRPNO: 법인번호, UPCHECD: 업체코드 | -| reqDate | | 기준일자 | String | 8 | | -| data | | | Object | | 기업신용 단기연체 결과 | -| listCount | | 단기연체정보 건수 | Integer | | | -| creditShorttermOverdueList | | 단기연체정보 | Array | | | -| count | ● | 단기연체정보건수 | Integer | | | -| rcno | ● | 차주대상번호 | String | | | -| rcnoKind | ● | 차주대상구분 | String | | 2: 사업자등록번호, 3: 법인등록번호 | -| name | ● | 기관명 | String | | | -| reqdate | ● | 요청일자 | String | | yyyymmdd | -| basedate | ● | 기준일자 | String | | yyyymmdd | -| organnizationsList | ● | 단기연체정보 기관별 정보 | Array | | | -| orgcd | ● | 한국신용정보원 | String | | | -| orgname | ● | 한국신용정보원기관명 | String | | | -| orgnameEng | ● | 한국신용정보원기관영문명 | String | | | -| principlaOduYn | ● | 연체금액여부(계정과목코드 6909) | String | | | -| accountSubjectsList | ● | 단기연체정보 계정과목별정보 | Array | | | -| acccd | ● | 계정과목코드 | String | | | -| accname | ● | 계정과목명 | String | | | -| kindcode1 | ● | 계정과목대과목코드 | String | | | -| kind1 | ● | 계정과목대과목명 | String | | | -| kindcode2 | ● | 계정과목중과목코드 | String | | | -| kind2 | ● | 계정과목중과목명 | String | | | -| categorycd | ● | 한국신용정보원만기코드 | String | | | -| category | ● | 한국신용정보원만기코드명 | String | | | -| accamt | ● | 거래금액 | String | | | - ---- - -### 5.4 [기업]신용도 판단정보(공공정보 포함)(한국 신용정보원) (OA14) - -#### [INPUT] - -| 개별 입력 ID | 개별 입력 명 | 타입 | 최대길이 | 필수여부 | 비고 | -|-------------|-------------|------|---------|---------|------| -| Companykey | 사업자정보 | String | 13 | 필수 | 조회할 기업의 사업자번호, 법인번호, 업체코드 중 한개만 입력 | - -#### [OUTPUT] - -| 출력 항목 | 반복여부 | 출력 항목 명 | 타입 | 최대길이 | 설명 | -|---------|---------|------------|------|---------|------| -| RSLT_CD | - | 결과코드 | String | 8 | 조회 결과 코드값, 정상 00000000 | -| RSLT_MSG | - | 결과메세지 | String | 255 | 조회 결과 메시지 | -| TR_SEQ | - | 거래일련번호 | String | 20 | 거래 추적용도 번호 | -| RSLT_DATA | - | 결과데이터 | Object | - | 나이스 결과데이터 | -| request | | 요청한 값 | Object | - | 단기연체정보 요청항목 | -| requestKey | | 요청 KEY | String | 13 | 사용자가요청한 companyKey | -| requestKeyType | | 요청한 KEY 타입 | String | 6 | BIZNO: 사업자번호, CRPNO: 법인번호, UPCHECD: 업체코드 | -| data | | | Object | | 신용도판단정보 결과 | -| listCount | | list 건수 | Integer | | | -| creditNegativeInfoList | | 신용도판단정보 | Array | | | -| totaloccCnt | ● | 발생 총 건수 | integer | | | -| bbCnt | ● | 채무불이행건수 | integer | | | -| fdCnt | ● | 금용질서문란 건수 | String | | | -| pbCnt | ● | 공공기록정보건수 | integer | | | -| sbCnt | ● | 특수기록정보건수 | integer | | | -| totalrelCnt | ● | 해제 총건수 | integer | | | -| bbrelCnt | ● | 채무불이행 해제건수 | integer | | | -| fdrelCnt | ● | 금융질서문란 해제건수 | integer | | | -| pbrelCnt | ● | 공공기록정보 해제건수 | integer | | | -| sbrelCnt | ● | 특수기록정보 해제건수 | integer | | | -| negativeInfoDetailList | ● | 신용도판단정보 item | Array | | | -| typecode | ● | 유형구분코드 | String | | BB: 신용도판단정보(채무불이행), FD: 금융질서문란, PB: 공공정보, SB: 특수기록정보 | -| typename | ● | 용도판단정보 | String | | (한국 신용정보원), 신용도판단정보(공공기록정보) 등 | -| gubn | ● | 구분 | String | | | -| delayamt | ● | 연체금액 | String | | | -| causecode | ● | 등록코드 | String | | | -| causename | ● | 등록사유명 | String | | | -| causenameEng | ● | 등록사유영문명 | String | | | -| causecont | ● | 등록사유설명 | String | | | -| causedetail | ● | 등록사유상세설명 | String | | | -| regamt | ● | 등록금액 | String | | | -| regdate | ● | 등록일자 | String | | yyyymmdd | -| relscode | ● | 해제코드 | String | | | -| reldate | ● | 해재일자 | String | | yyyymmdd | -| orgname | ● | 발생기관명 | String | | | -| orgnameEng | ● | 발생기관영문명 | String | | | -| brcname | ● | 발생지점명 | String | | | -| occdate | ● | 발생일자 | String | | yyyymmdd | - ---- - -### 5.5 [기업]신용-신용도 판단정보(신용정보사) (OA15) - -#### [INPUT] - -| 개별 입력 ID | 개별 입력 명 | 타입 | 최대길이 | 필수여부 | 비고 | -|-------------|-------------|------|---------|---------|------| -| Companykey | 사업자정보 | String | 13 | 필수 | 조회할 기업의 사업자번호, 법인번호, 업체코드 중 한개만 입력 | - -#### [OUTPUT] - -| 출력 항목 | 반복여부 | 출력 항목 명 | 타입 | 최대길이 | 설명 | -|---------|---------|------------|------|---------|------| -| RSLT_CD | - | 결과코드 | String | 8 | 조회 결과 코드값, 정상 00000000 | -| RSLT_MSG | - | 결과메세지 | String | 255 | 조회 결과 메시지 | -| TR_SEQ | - | 거래일련번호 | String | 20 | 거래 추적용도 번호 | -| RSLT_DATA | - | 결과데이터 | Object | - | 나이스 결과데이터 | -| request | | 요청한 값 | Object | - | 단기연체정보 요청항목 | -| requestKey | | 요청 KEY | String | 13 | 사용자가요청한 companyKey | -| requestKeyType | | 요청한 KEY 타입 | String | 6 | BIZNO: 사업자번호, CRPNO: 법인번호, UPCHECD: 업체코드 | -| data | | | Object | | 기업 신용 신용도판단 정보(신용정보사) 결과 | -| listCount | | list 건수 | Integer | | | -| creditNegativeInfoCdList | | | Array | | 기업 신용 신용도판단 정보(신용정보사) | -| typecode | ● | 유형구분코드 | String | | CB: 신용도판단정보(신용정보사) | -| typename | ● | 유형구분명 | String | | (예: 신용도판단정보(신용정보사)) | -| causecode | ● | 등록코드 | String | | | -| causename | ● | 등록사유 명 | String | | | -| causenameEng | ● | 등록사유영문명 | String | | | -| causecont | ● | 등록사유설명 | String | | | -| causedetail | ● | 등록사유상세설명 | String | | | -| regamt | ● | 등록금액 | String | | | -| regdate | ● | 등록일자 | String | | yyyymmdd | -| relscode | ● | 해제코드 | String | | | -| relsdate | ● | 해제일자 | String | | yyyymmdd | -| relsname | ● | 해제 명 | String | | | -| orgname | ● | 발생기관명 | String | | | -| orgnameEng | ● | 발생기관영문명 | String | | | -| brcname | ● | 발생지점명 | String | | | -| occdate | ● | 발생일자 | String | | yyyymmdd | - ---- - -### 5.6 [기업]신용-당좌거래정지정보(금융결제원) (OA16) - -#### [INPUT] - -| 개별 입력 ID | 개별 입력 명 | 타입 | 최대길이 | 필수여부 | 비고 | -|-------------|-------------|------|---------|---------|------| -| Companykey | 사업자정보 | String | 13 | 필수 | 조회할 기업의 사업자번호, 법인번호, 업체코드 중 한개만 입력 | - -#### [OUTPUT] - -| 출력 항목 | 반복여부 | 출력 항목 명 | 타입 | 최대길이 | 설명 | -|---------|---------|------------|------|---------|------| -| RSLT_CD | - | 결과코드 | String | 8 | 조회 결과 코드값, 정상 00000000 | -| RSLT_MSG | - | 결과메세지 | String | 255 | 조회 결과 메시지 | -| TR_SEQ | - | 거래일련번호 | String | 20 | 거래 추적용도 번호 | -| RSLT_DATA | - | 결과데이터 | Object | - | 나이스 결과데이터 | -| request | | 요청한 값 | Object | - | 단기연체정보 요청항목 | -| requestKey | | 요청 KEY | String | 13 | 사용자가요청한 companyKey | -| requestKeyType | | 요청한 KEY 타입 | String | 6 | BIZNO: 사업자번호, CRPNO: 법인번호, UPCHECD: 업체코드 | -| data | | | Object | | 기업 신용 당좌거래정지정보 결과 | -| listCount | | list 건수 | Integer | | | -| creditSuspensionInfoList | | | Array | | 기업 신용 당좌거래정 지정보 | -| datSeq | ● | 데이터일련번호 | Integer | | | -| changeHouse | ● | 교환소 | String | 20 | | -| koreantrnm | ● | 업체 명 | String | 70 | | -| korrenprnm | ● | 대표자명 | String | 30 | | -| bizno | ● | 사업자등록번호 | String | 10 | | -| regno | ● | 주민등록번호 | String | 13 | | -| address | ● | 주소 | String | 100 | | -| occdate | ● | 발행일 | String | 8 | yyyymmdd | -| relsdate | ● | 해제일 | String | 8 | yyyymmdd | - ---- - -### 5.7 [기업]신용-법정관리/워크아웃정보 (OA17) - -#### [INPUT] - -| 개별 입력 ID | 개별 입력 명 | 타입 | 최대길이 | 필수여부 | 비고 | -|-------------|-------------|------|---------|---------|------| -| Companykey | 사업자정보 | String | 13 | 필수 | 조회할 기업의 사업자번호, 법인번호, 업체코드 중 한개만 입력 | -| pageNo | 페이지 번호 | String | | | | -| pageSize | 페이지 사이즈 | String | | | | - -#### [OUTPUT] - -| 출력 항목 | 반복여부 | 출력 항목 명 | 타입 | 최대길이 | 설명 | -|---------|---------|------------|------|---------|------| -| RSLT_CD | - | 결과코드 | String | 8 | 조회 결과 코드값, 정상 00000000 | -| RSLT_MSG | - | 결과메세지 | String | 255 | 조회 결과 메시지 | -| TR_SEQ | - | 거래일련번호 | String | 20 | 거래 추적용도 번호 | -| RSLT_DATA | - | 결과데이터 | Object | - | 나이스 결과데이터 | -| request | | 요청한 값 | Object | - | 단기연체정보 요청항목 | -| requestKey | | 요청 KEY | String | 13 | 사용자가요청한 companyKey | -| requestKeyType | | 요청 KEY 타입 | String | 6 | BIZNO: 사업자번호, CRPNO: 법인번호, UPCHECD: 업체코드 | -| pageNo | | | integer | | | -| pageSize | | | integer | | | -| data | | | Object | | 법정관리/워크아웃정보 결과 | -| listCount | | list 건수 | Integer | | | -| totalCount | | 총 건수 | integer | | | -| creditworkoutList | | 기업 신용 법정관리/워크아웃정보 | Array | | | -| upchecd | ● | 업체코드 | String | 6 | | -| lglmgmtRldDate | ● | 법정관리관례일자 | String | 8 | | -| hngno | ● | 사건번호 | String | 14 | | -| lwccd | ● | 법원코드 | String | 3 | | -| lwccd | ● | 법원 명 | String | 100 | | -| crgJudgDeptnm | ● | 담당판사부서명 | String | 30 | | -| crgJudgNam | ● | 담당판사 명 | String | 100 | | -| korentrnm | ● | 업체 명 | String | 100 | | -| lglmgmtdivcd | ● | 법정관리유형코드 | String | 2 | | -| lglmgmtdivnm | ● | 법정관리유형명 | String | 150 | | - ---- - -### 5.8 소스코딩 예제 - -#### 1. [기업]지표-주요경영지표 (OA07) - -**[입력값]** -```json -{ - "API_KEY": "업체 인증키", - "API_ID": "OA07", - "TR_SEQ": "123456789", - "Companykey": "2178149522", - "tpCd": "01", - "fatpCd": "0" -} -``` - -#### 2. [기업]개요-기본정보 (OA08) - -**[입력값]** -```json -{ - "API_KEY": "업체 인증키", - "API_ID": "OA08", - "TR_SEQ": "123456789", - "Companykey": "2178149522", - "idscdcg": "09" -} -``` - -#### 3. [검색]통합기업검색 (OA09) - -**[입력값]** -```json -{ - "API_KEY": "업체 인증키", - "API_ID": "OA09", - "TR_SEQ": "123456789", - "pageNo": "1", - "pageSize": "10", - "keyword": "삼성전자", - "upchecd": "380725" -} -``` - -#### 4. [기업]등급-기업평가등급 (OA10) - -**[입력값]** -```json -{ - "API_KEY": "업체 인증키", - "API_ID": "OA10", - "TR_SEQ": "123456789", - "Companykey": "2178149522", - "pageNo": "1", - "pageSize": "10", - "startDate": "20220101", - "endDate": "20240101" -} -``` - -#### 5. [기업]등급-WATCH 등급 (OA11) - -**[입력값]** -```json -{ - "API_KEY": "업체 인증키", - "API_ID": "OA11", - "TR_SEQ": "123456789", - "Companykey": "2178149522", - "addWatchRsn": "1", - "pageNo": "1", - "pageSize": "10", - "startDate": "20220101", - "endDate": "20240101" -} -``` - -#### 6. [기업]신용-신용요약정보 (OA12) - -**[입력값]** -```json -{ - "API_KEY": "업체 인증키", - "API_ID": "OA12", - "TR_SEQ": "123456789", - "Companykey": "2178149522" -} -``` - -#### 7. [기업]신용-단기연체정보(한국신용정보원) (OA13) - -**[입력값]** -```json -{ - "API_KEY": "업체 인증키", - "API_ID": "OA13", - "TR_SEQ": "123456789", - "Companykey": "2178149522", - "reqDate": "20220101" -} -``` - -#### 8. [기업]신용도-판단정보(공공정보 포함)(한국 신용정보원) (OA14) - -**[입력값]** -```json -{ - "API_KEY": "업체 인증키", - "API_ID": "OA14", - "TR_SEQ": "123456789", - "Companykey": "2178149522" -} -``` - -#### 9. [기업]신용-신용도 판단정보(신용정보사) (OA15) - -**[입력값]** -```json -{ - "API_KEY": "업체 인증키", - "API_ID": "OA15", - "TR_SEQ": "123456789", - "Companykey": "2178149522" -} -``` - -#### 10. [기업]신용-당좌거래정지정보(금융결제원) (OA16) - -**[입력값]** -```json -{ - "API_KEY": "업체 인증키", - "API_ID": "OA16", - "TR_SEQ": "123456789", - "Companykey": "2178149522" -} -``` - -#### 11. [기업]신용-법정관리/워크아웃정보 (OA17) - -**[입력값]** -```json -{ - "API_KEY": "업체 인증키", - "API_ID": "OA17", - "TR_SEQ": "123456789", - "Companykey": "5148145785", - "pageNo": "1", - "pageSize": "10" -} -``` - ---- - -## 6. 개발 유의사항 - -API를 호출하실 경우에는 자바스크립트, VB 스크립트 등의 클라이언트 사이트 스크립트 언어가 아닌 **서버 사이드 스크립트 언어(JSP, PHP, ASP 등)**로 호출하여 주셔야 정상적인 거래가 가능합니다. - -### 서버 사이드 스크립트 사용 JSP 페이지 샘플 - -```jsp -<%@ page contentType="text/html; charset=utf-8"%> -<%@ page import="java.net.*"%> -<%@ page import = "java.io.*" %> -<%@ page import = "java.net.URLConnection" %> -<%@ page import = "javax.net.ssl.HttpsURLConnection" %> -<% -response.setHeader("Cache-Control","no-store"); // HTTP 1.1 -response.setHeader("Pragma","no-cache"); // HTTP 1.0 -response.setDateHeader("Expires", 0); - -String url = "https://dev2.coocon.co.kr:8443/sol/gateway/oapi_relay.jsp"; -byte[] resMessage = null; -HttpsURLConnection conn; - -try { - conn = (HttpsURLConnection) new URL(url).openConnection(); - conn.setDoInput(true); - conn.setDoOutput(true); - conn.setRequestMethod("POST"); - conn.setRequestProperty("Content-Type","application/json"); - conn.setUseCaches(false); - OutputStreamWriter os = new OutputStreamWriter(conn.getOutputStream()); - - JSONObject inputObj = new JSONObject(); - inputObj.put("API_KEY","발급인증키"); - inputObj.put("API_ID","업무코드"); - inputObj.put("Companykey","사업자정보"); - os.write(inputObj.toString()); - os.flush(); - os.close(); - - DataInputStream in = new DataInputStream(conn.getInputStream()); - ByteArrayOutputStream bout = new ByteArrayOutputStream(); - int bcount = 0; - byte[] buf = new byte[2048]; - while (true) { - int n = in.read(buf); - if (n == -1) break; - bout.write(buf, 0, n); - } - bout.flush(); - resMessage = bout.toByteArray(); - conn.disconnect(); -} -catch (MalformedURLException e) { - System.out.println("MalformedURLException"); -} -catch (IOException e) { - e.printStackTrace(); -} - -//결과처리 -String temp = new String(resMessage, "UTF-8"); -temp = temp.replaceAll("\r\n",""); -temp = temp.replaceAll("\r",""); -temp = temp.replaceAll("\n",""); -out.println(temp.trim()); -%> -``` - ---- - -## [참조 1] 결과코드 - -| Code | 내용 | -|------|------| -| 00000000 | 정상처리되었습니다. | -| GWS06001 | 수신자료 포맷 오류. (REQ_DATA 미입력 오류로 입력값중에 개별입력값 확인 필요) | -| GWS06002 | 수신자료 변환 오류. (입력값 JSON 형식인지 확인필요) | -| GWS06003 | 잘못된 전문번호 입니다. (API ID 오입력으로 API ID 값 확인 필요) | -| GWS06004 | 응답시간을 초과하였습니다. (업무 담당자에게 문의) | -| GWS06005 | 결과처리중 오류가 발생하였습니다. (업무 담당자에게 문의) | -| GWS06006 | 정의되지 않은 응답오류입니다. (업무 담당자에게 문의) | -| GWS06013 | 거래고유번호(TR_SEQ)이 미입력되었습니다. | -| GWS06020 | 서비스가능한 시간대가 아닙니다. | -| GWS09979 | 내부 서버오류 (업무 담당자에게 문의) | -| GWS09984 | 잘못된 인증키 입니다. (API_KEY 값 오입력으로 API KEY 값 확인 필요) | -| GWS09985 | 보안키(API_KEY)값이 미입력되었습니다. | -| GWS09989 | 허용된 아이피가 아닙니다 (접속아이피 확인필요) | -| GWS09990 | 사용가능 아이피가 등록되지 않았습니다. | -| GWS09993 | 서비스 설정값이 잘못되었습니다. (업무 담당자에게 문의) | -| GWS09998 | 인증과정중 알수없는 오류가 발생했습니다. | -| OAPI0005 | Companykey 미입력 되었습니다. | diff --git a/sam/docker/api/opcache.ini b/sam/docker/api/opcache.ini deleted file mode 100644 index 137d2c0..0000000 --- a/sam/docker/api/opcache.ini +++ /dev/null @@ -1,33 +0,0 @@ -; OPcache 설정 (성능 향상) -; PHP OPcode 캐시를 활성화하여 애플리케이션 성능을 크게 향상시킵니다 - -[opcache] -; OPcache 활성화 -opcache.enable=1 - -; CLI 환경에서도 OPcache 활성화 (개발 환경) -opcache.enable_cli=1 - -; OPcache 메모리 사용량 (MB) -; 256MB 권장 (프로젝트 크기에 따라 조정) - 개발 환경 성능 향상 -opcache.memory_consumption=256 - -; 내부 문자열 버퍼 크기 (MB) -opcache.interned_strings_buffer=16 - -; 최대 가속화 파일 수 -opcache.max_accelerated_files=20000 - -; 타임스탬프 검증 활성화 (개발 환경) -; 프로덕션에서는 0으로 설정하여 성능 최적화 -opcache.validate_timestamps=1 - -; 재검증 주기 (초) - 개발 환경 성능 향상을 위해 단축 -; validate_timestamps가 1일 때만 사용됨 -opcache.revalidate_freq=1 - -; 빠른 종료 활성화 -opcache.fast_shutdown=1 - -; 최적화 레벨 (0-7, 높을수록 느리지만 더 최적화됨) -opcache.optimization_level=0x7FFFBFFF diff --git a/sam/docker/api/supervisord.conf b/sam/docker/api/supervisord.conf deleted file mode 100755 index be1dada..0000000 --- a/sam/docker/api/supervisord.conf +++ /dev/null @@ -1,36 +0,0 @@ -[supervisord] -nodaemon=true - -[program:php-fpm] -command=/usr/local/sbin/php-fpm - -[program:nginx] -command=nginx -g "daemon off;" - -[program:queue-worker] -command=php /var/www/api/artisan queue:work database --queue=api,default --sleep=3 --tries=3 --timeout=1800 --max-jobs=100 --max-time=3600 -process_name=%(program_name)s_%(process_num)02d -numprocs=1 -directory=/var/www/api -autostart=true -autorestart=true -startsecs=5 -startretries=3 -stopwaitsecs=1830 -stdout_logfile=/var/www/api/storage/logs/queue-worker.log -stdout_logfile_maxbytes=5MB -stderr_logfile=/var/www/api/storage/logs/queue-worker-error.log -stderr_logfile_maxbytes=5MB - -[program:scheduler] -command=bash -c "while true; do php /var/www/api/artisan schedule:run --no-interaction; sleep 60; done" -process_name=%(program_name)s -numprocs=1 -directory=/var/www/api -autostart=true -autorestart=true -startsecs=0 -stdout_logfile=/var/www/api/storage/logs/scheduler.log -stdout_logfile_maxbytes=5MB -stderr_logfile=/var/www/api/storage/logs/scheduler-error.log -stderr_logfile_maxbytes=5MB \ No newline at end of file diff --git a/sam/docker/docker-compose.yml b/sam/docker/docker-compose.yml deleted file mode 100644 index e89b1e8..0000000 --- a/sam/docker/docker-compose.yml +++ /dev/null @@ -1,225 +0,0 @@ -services: - nginx: - image: nginx:latest - ports: - - "80:80" - - "443:443" - volumes: - - /home/aweso/sam/api:/var/www/api - - /home/aweso/sam/admin:/var/www/admin - - /home/aweso/sam/mng:/var/www/mng - - /home/aweso/sam/5130:/var/www/5130 - - /home/aweso/sam/docker/nginx/nginx.conf:/etc/nginx/nginx.conf:ro - - /home/aweso/sam/docker/nginx/ssl:/etc/nginx/ssl:ro - command: > - sh -c "rm -f /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'" - depends_on: - - api - - admin - - mng - - react - - design - - sales - - php73 - networks: - - samnet - - api: - build: - context: . - dockerfile: /home/aweso/sam/docker/api/Dockerfile - volumes: - - /home/aweso/sam/api:/var/www/api - - api_vendor:/var/www/api/vendor - - api_node_modules:/var/www/api/node_modules - - /home/aweso/sam/docker/api/nginx.conf:/etc/nginx/conf.d/default.conf - - /home/aweso/sam/docker/api/supervisord.conf:/etc/supervisor/conf.d/supervisord.conf - - /home/aweso/sam/docker/api/uploads.ini:/usr/local/etc/php/conf.d/uploads.ini - - /home/aweso/sam/docker/api/opcache.ini:/usr/local/etc/php/conf.d/opcache.ini - - /home/aweso/sam/docker/mysql/client-skip-ssl.cnf:/etc/mysql/conf.d/disable-ssl.cnf:ro - environment: - - DB_HOST=sam-mysql-1 - - DB_PORT=3306 - - DB_DATABASE=samdb - - DB_USERNAME=samuser - - DB_PASSWORD=sampass - networks: - - samnet - working_dir: /var/www/api - - admin: - build: - context: . - dockerfile: /home/aweso/sam/docker/admin/Dockerfile - volumes: - - /home/aweso/sam/admin:/var/www/admin - - admin_vendor:/var/www/admin/vendor - - admin_node_modules:/var/www/admin/node_modules - - /home/aweso/sam/docker/admin/nginx.conf:/etc/nginx/conf.d/default.conf - - /home/aweso/sam/docker/admin/supervisord.conf:/etc/supervisor/conf.d/supervisord.conf - - /home/aweso/sam/docker/admin/uploads.ini:/usr/local/etc/php/conf.d/uploads.ini - environment: - - DB_HOST=sam-mysql-1 - - DB_PORT=3306 - - DB_DATABASE=samdb - - DB_USERNAME=samuser - - DB_PASSWORD=sampass - networks: - - samnet - working_dir: /var/www/admin - - mng: - build: - context: . - dockerfile: mng/Dockerfile - volumes: - - ../mng:/var/www/mng - - mng_vendor:/var/www/mng/vendor - - mng_node_modules:/var/www/mng/node_modules - - ./mng/nginx.conf:/etc/nginx/conf.d/default.conf - - ./mng/supervisord.conf:/etc/supervisor/conf.d/supervisord.conf - - ./mng/opcache.ini:/usr/local/etc/php/conf.d/opcache.ini - - ./mng/uploads.ini:/usr/local/etc/php/conf.d/uploads.ini - # - ./mng/www.conf:/usr/local/etc/php-fpm.d/www.conf - - ../api/storage/logs:/var/www/api/storage/logs:ro - - ./mysql/client-skip-ssl.cnf:/etc/mysql/conf.d/disable-ssl.cnf:ro - - ../sales/apikey:/var/www/sales/apikey:ro # Google 서비스 계정 파일 접근용 - - ../sales:/var/www/sales-docs:ro # 영업 PPTX 문서 접근용 - # shared-storage 제거됨 → mng/storage/app/tenants 로 이동 (2026-02-23) - - ../docs:/var/www/docs:ro # SAM 프로젝트 문서 (RAG 검색용) - environment: - - DB_HOST=sam-mysql-1 - - DB_PORT=3306 - - DB_DATABASE=samdb - - DB_USERNAME=samuser - - DB_PASSWORD=sampass - networks: - - samnet - working_dir: /var/www/mng - - react: - build: - context: /home/aweso/sam - dockerfile: docker/react/Dockerfile - volumes: - - /home/aweso/sam/react:/app - - /app/node_modules - - /app/.next - environment: - - NEXT_PUBLIC_API_URL=https://api.sam.kr - - NEXT_PUBLIC_ADMIN_URL=https://admin.sam.kr - - NEXT_PUBLIC_API_KEY=42Jfwc6EaRQ04GNRmLR5kzJp5UudSOzGGqjmdk1a - - NEXT_PUBLIC_APP_NAME=SAM - - NODE_ENV=development - - NODE_TLS_REJECT_UNAUTHORIZED=0 - extra_hosts: - - "api.sam.kr:host-gateway" - networks: - - samnet - working_dir: /app - - design: - build: - context: /home/aweso/sam - dockerfile: docker/design/Dockerfile - volumes: - - /home/aweso/sam/design:/app - - /app/node_modules - environment: - - NODE_ENV=development - networks: - - samnet - working_dir: /app - - sales: - build: - context: . - dockerfile: /home/aweso/sam/docker/sales/Dockerfile - volumes: - - /home/aweso/sam/sales:/var/www/sales - - sales_vendor:/var/www/sales/vendor - - sales_node_modules:/var/www/sales/node_modules - - /home/aweso/sam/docker/sales/nginx.conf:/etc/nginx/conf.d/default.conf - - /home/aweso/sam/docker/sales/supervisord.conf:/etc/supervisor/conf.d/supervisord.conf - - /home/aweso/sam/docker/sales/uploads.ini:/usr/local/etc/php/conf.d/uploads.ini - environment: - - TZ=Asia/Seoul - networks: - - samnet - working_dir: /var/www/sales - - php73: - build: - context: . - dockerfile: /home/aweso/sam/docker/5130/Dockerfile - volumes: - - /home/aweso/sam/5130:/var/www/5130 - - php73_vendor:/var/www/5130/vendor - - php73_node_modules:/var/www/5130/node_modules - - /home/aweso/sam/docker/5130/nginx.conf:/etc/nginx/conf.d/default.conf - - /home/aweso/sam/docker/5130/supervisord.conf:/etc/supervisor/conf.d/supervisord.conf - - /home/aweso/sam/docker/5130/uploads.ini:/usr/local/etc/php/conf.d/uploads.ini - environment: - - DB_HOST=sam-mysql-1 - - DB_PORT=3306 - - DB_DATABASE=chandj - - DB_USERNAME=root - - DB_PASSWORD=root - - TZ=Asia/Seoul - networks: - - samnet - working_dir: /var/www/5130 - - mysql: - image: mysql:8.0 - restart: always - environment: - MYSQL_DATABASE: samdb - MYSQL_USER: samuser - MYSQL_PASSWORD: sampass - MYSQL_ROOT_PASSWORD: root - TZ: Asia/Seoul - command: --sql-mode="NO_ENGINE_SUBSTITUTION" --default-time-zone="+09:00" --default-authentication-plugin=mysql_native_password - volumes: - - db_data:/var/lib/mysql - - /home/aweso/sam/docker/mysql/init.sql:/docker-entrypoint-initdb.d/01-init.sql - # - /home/aweso/sam/chandj_dump.sql:/docker-entrypoint-initdb.d/02-chandj-dump.sql - ports: - - "3306:3306" - networks: - - samnet - - phpmyadmin: - image: phpmyadmin:latest - restart: always - ports: - - "8080:80" - environment: - - PMA_ARBITRARY=1 - - PMA_HOST=mysql - - PMA_PORT=3306 - - PMA_USER=root - - PMA_PASSWORD=root - - TZ=Asia/Seoul - depends_on: - - mysql - networks: - - samnet - -volumes: - db_data: - # 의존성 디렉토리 분리 (성능 향상) - api_vendor: - api_node_modules: - mng_vendor: - mng_node_modules: - admin_vendor: - admin_node_modules: - sales_vendor: - sales_node_modules: - php73_vendor: - php73_node_modules: - -networks: - samnet: - driver: bridge diff --git a/sam/docker/mng/Dockerfile b/sam/docker/mng/Dockerfile deleted file mode 100755 index f19b269..0000000 --- a/sam/docker/mng/Dockerfile +++ /dev/null @@ -1,43 +0,0 @@ -FROM php:8.4-fpm - -# 필수 패키지/확장 설치 -RUN apt-get update && apt-get install -y \ - git \ - unzip \ - libzip-dev \ - libicu-dev \ - libxml2-dev \ - libpng-dev \ - libfreetype-dev \ - libjpeg62-turbo-dev \ - nginx \ - supervisor \ - libreoffice-writer-nogui \ - fonts-nanum fonts-nanum-extra \ - ffmpeg \ - wget \ - && docker-php-ext-configure gd --with-freetype --with-jpeg \ - && docker-php-ext-install zip mysqli pdo pdo_mysql intl soap gd \ - # Pretendard 폰트 설치 (Word→PDF 변환 시 한글 폰트 지원) - && mkdir -p /usr/share/fonts/truetype/pretendard \ - && wget -q "https://github.com/orioncactus/pretendard/releases/download/v1.3.9/Pretendard-1.3.9.zip" -O /tmp/pretendard.zip \ - && unzip -jo /tmp/pretendard.zip "*/Pretendard-*.otf" -d /usr/share/fonts/truetype/pretendard/ \ - && rm -f /tmp/pretendard.zip \ - && fc-cache -f - -# Composer 설치 -COPY --from=composer:2 /usr/bin/composer /usr/bin/composer - -# 타임존 설정 -RUN echo "date.timezone=Asia/Seoul" > /usr/local/etc/php/conf.d/timezone.ini - -# 포트 개방 -EXPOSE 80 - -# supervisor로 nginx+php-fpm 동시 기동 -CMD ["/usr/bin/supervisord"] - -# entrypoint.sh 복사 및 권한 -COPY ./mng/entrypoint.sh /entrypoint.sh -RUN chmod +x /entrypoint.sh -ENTRYPOINT ["/entrypoint.sh"] \ No newline at end of file diff --git a/sam/docker/mng/entrypoint.sh b/sam/docker/mng/entrypoint.sh deleted file mode 100755 index f5dcbc9..0000000 --- a/sam/docker/mng/entrypoint.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -# 0. Nginx 기본 사이트 설정 비활성화 (충돌 방지) -rm -f /etc/nginx/sites-enabled/default - -# 1. 퍼미션 설정 (mng) -chown -R www-data:www-data /var/www/mng/storage /var/www/mng/bootstrap/cache -chmod -R 775 /var/www/mng/storage /var/www/mng/bootstrap/cache - -# 2. tenant storage 퍼미션 (명함/신분증/통장/게시판 첨부파일 등) -mkdir -p /var/www/mng/storage/app/tenants -chown -R www-data:www-data /var/www/mng/storage/app/tenants -chmod -R 775 /var/www/mng/storage/app/tenants - -# 3. storage:link (실패해도 무시) -cd /var/www/mng && php artisan storage:link || true - -# 4. supervisor 실행(nginx+php-fpm) -exec /usr/bin/supervisord \ No newline at end of file diff --git a/sam/docker/mng/nginx.conf b/sam/docker/mng/nginx.conf deleted file mode 100755 index 32136d4..0000000 --- a/sam/docker/mng/nginx.conf +++ /dev/null @@ -1,32 +0,0 @@ -server { - listen 80; - server_name _; - - root /var/www/mng/public; - index index.php index.html; - - access_log /var/log/nginx/mng_access.log; - error_log /var/log/nginx/mng_error.log; - - # 심볼릭 링크 허용 - disable_symlinks off; - - # tenant-storage 정적 파일 서빙 - location /tenant-storage/ { - alias /var/www/mng/storage/app/tenants/; - expires 7d; - add_header Cache-Control "public, immutable"; - } - - location / { - try_files $uri $uri/ /index.php?$query_string; - } - - location ~ \.php$ { - fastcgi_pass 127.0.0.1:9000; - fastcgi_index index.php; - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - include fastcgi_params; - fastcgi_read_timeout 300s; - } -} \ No newline at end of file diff --git a/sam/docker/mng/supervisord.conf b/sam/docker/mng/supervisord.conf deleted file mode 100755 index acdf92b..0000000 --- a/sam/docker/mng/supervisord.conf +++ /dev/null @@ -1,23 +0,0 @@ -[supervisord] -nodaemon=true - -[program:php-fpm] -command=/usr/local/sbin/php-fpm - -[program:nginx] -command=nginx -g "daemon off;" - -[program:queue-worker] -command=php /var/www/mng/artisan queue:work database --queue=mng,default --sleep=3 --tries=1 --timeout=1800 --max-jobs=10 --max-time=3600 -process_name=%(program_name)s_%(process_num)02d -numprocs=2 -directory=/var/www/mng -autostart=true -autorestart=true -startsecs=5 -startretries=3 -stopwaitsecs=1830 -stdout_logfile=/var/www/mng/storage/logs/queue-worker.log -stdout_logfile_maxbytes=5MB -stderr_logfile=/var/www/mng/storage/logs/queue-worker-error.log -stderr_logfile_maxbytes=5MB \ No newline at end of file diff --git a/sam/docs/CLAUDE.md b/sam/docs/CLAUDE.md deleted file mode 100644 index cce4943..0000000 --- a/sam/docs/CLAUDE.md +++ /dev/null @@ -1,876 +0,0 @@ -# Claude Code 전역 설정 - -> 이 파일은 모든 프로젝트에 적용되는 전역 규칙입니다. - -## 메모리 - -### sam설명 -SAM 프로젝트의 기술적 개요 문서입니다. 이 문서를 참조하면 SAM 프로젝트가 무엇인지 이해할 수 있습니다. - -**파일 경로**: `/home/aweso/sam/docs/SAM_PROJECT_OVERVIEW_FOR_AI.md` - -**핵심 요약**: -- **회사**: 주일/경동 (블라인드/스크린 제조업체) -- **프로젝트**: SAM (Smart Automation Management) - 차세대 ERP/MES 통합 시스템 -- **기술 스택**: Laravel 12 + HTMX + Tailwind CSS + MySQL 8.0 (PHP 8.4) -- **아키텍처**: Multi-tenant (tenant_id 기반 데이터 격리) -- **레거시**: 5130.co.kr (PHP 기반) → SAM으로 마이그레이션 중 - -**사용자가 'sam설명'이라고 말하면**: -1. 위 경로의 `SAM_PROJECT_OVERVIEW_FOR_AI.md` 파일을 읽어서 전체 내용을 파악하세요 -2. SAM 프로젝트의 비즈니스 도메인, 기술 스택, 현재 작업 현황을 이해한 상태로 작업하세요 - ---- - -## Git 커밋 규칙 (최우선 필수 규칙) - -> **경고: 이 규칙은 절대 누락되어서는 안 됩니다!** -> **기준 문서**: `sam/docs/standards/git-conventions.md` - -### 필수 수행 절차 - -**모든 코드 작업 완료 후 반드시 다음을 수행:** - -1. 변경된 파일이 있는 Git 저장소로 이동 -2. `git status`로 변경사항 확인 -3. `git add <파일들>` 로 스테이징 -4. `git commit -m "type: [scope] 작업내용"` 로 커밋 - -### 커밋 메시지 형식 (필수) - -``` -type: [scope] 작업내용 - -- 세부항목 (생략가능) -- 세부항목 2 - -Issue: URL (생략가능) -``` - -**예시:** -```bash -feat: [calendar] 달력 기능 개선 - -- 클릭시 오류 기능 개선 -- 색상 변경 -``` - -```bash -fix: [auth] 로그인 시 세션 만료 오류 수정 -``` - -### Commit Types - -| Type | 설명 | 예시 | -|------|------|------| -| `feat` | 새로운 기능 추가 | `feat: [file] 파일 업로드 기능 추가` | -| `fix` | 버그 수정 | `fix: [auth] 세션 만료 오류 수정` | -| `chore` | 설정, 빌드 등 변경 | `chore: composer 패키지 업데이트` | -| `refactor` | 프로덕션 코드 리팩토링 | `refactor: [user] 서비스 메서드 분리` | -| `style` | 포맷/코딩 스타일 수정 | `style: Pint 포맷팅 적용` | -| `test` | 테스트 추가/수정 | `test: Product API 테스트 추가` | -| `docs` | 문서 변경 | `docs: API 문서 업데이트` | - -### Claude 서명 제외 (필수) - -``` -❌ Co-Authored-By: Claude — 포함 금지 -❌ 🤖 Generated with Claude Code — 포함 금지 -``` - -- Git hooks로 자동 제거됨 -- 간결하고 명확한 한글 커밋 메시지만 유지 - -### 푸시 정책 - -- **사용자가 수동으로 푸시 진행** -- 자동 푸시 하지 않음 -- 커밋 후 푸시 여부를 묻지 않음 - -### Claude Code 설정 파일도 커밋 대상 - -다음 파일들이 변경되면 반드시 커밋: - -| 파일/폴더 | 설명 | 커밋 예시 | -|-----------|------|----------| -| `CLAUDE.md` | 프로젝트 설정 | `docs: CLAUDE.md 규칙 업데이트` | -| `claudedocs/` | Claude 관련 문서 | `docs: 기능 분석 문서 추가` | -| `.claude/settings.json` | Claude 설정 | `chore: Claude 설정 변경` | -| `agents/`, `skills/` | 커스텀 에이전트/스킬 | `feat: [claude] 새 스킬 추가` | - -### 커밋 전 체크리스트 - -- [ ] `./vendor/bin/pint` 실행 (코드 포맷팅, 해당 시) -- [ ] `git diff`로 변경사항 검토 -- [ ] 불필요한 파일 제외 (.env, node_modules 등) -- [ ] 변경된 파일이 있는 저장소에서 git add → git commit -- [ ] CLAUDE.md, claudedocs/, agents/, skills/ 변경 확인 → git commit -- [ ] 커밋 메시지: `type: [scope] 한글 작업내용` 형식 준수 -- [ ] Co-Authored-By 서명 미포함 확인 - ---- - -## 주요 프로젝트 경로 - -| 경로 | 설명 | Git 저장소 | -|------|------|-----------| -| `/home/aweso/sam/mng` | 관리자 웹 (Laravel) | 독립 저장소 | -| `/home/aweso/sam/api` | API 서버 (Laravel) | 독립 저장소 | -| `/home/aweso/sam/react` | 프론트엔드 (Next.js) | 독립 저장소 | - -**각 폴더는 독립적인 Git 저장소입니다. 해당 폴더에서 git 명령을 실행해야 합니다.** - -> **서버 경로 참고**: -> - 개발/운영 서버 모두 `/home/webservice/` 하위에 동일한 구조로 배치 -> - 서버: `/home/webservice/api`, `/home/webservice/mng`, `/home/webservice/react`, `/home/webservice/sales` - ---- - -## 서버 직접 접근 금지 (최우선 필수 규칙) - -> **경고: 운영/개발 서버에 SSH로 직접 접속하여 파일을 수정하거나 명령을 실행하지 마세요!** -> **2026-02-21 사고**: Claude가 서버에 SSH로 직접 접속하여 설정을 변경한 결과 502 Bad Gateway 발생. 개발팀장이 복구함. - -### 핵심 원칙 - -서버는 **개발팀장이 관리**한다. Claude는 서버에 절대 직접 접근하지 않는다. - -### 금지 사항 - -``` -❌ ssh pro@114.203.209.83 ... 로 서버 접속 금지 -❌ ssh hskwon@114.203.209.83 ... 로 서버 접속 금지 -❌ 서버에서 파일 수정, 프로세스 종료/시작, 설정 변경 금지 -❌ 서버에서 npm run build, npm start, node server.js 등 실행 금지 -❌ 서버에서 git pull, composer install, php artisan 등 실행 금지 -❌ scp, rsync로 서버에 파일 직접 전송 금지 -``` - -### 허용 사항 - -``` -✅ 로컬에서 코드 작성 및 수정 -✅ 로컬에서 git add → git commit -✅ 사용자에게 git push 안내 (사용자가 수동으로 실행) -✅ 사용자에게 서버 배포 절차 안내 (사용자가 수동으로 실행) -``` - -### 서버 접속 정보 - -| 서버 | 호스트 | 계정 | 역할 | -|------|--------|------|------| -| 개발 서버 | `114.203.209.83` | `pro`, `hskwon` | 개발/스테이징 + Jenkins CI/CD + Gitea | -| 운영 서버 | (신규, 미확정) | 별도 계정 | 정식 서비스 | - -> **참고**: Jenkins(`114.203.209.83:8080`)와 Gitea(`114.203.209.83:3000`)는 개발 서버에서 운영한다. - -### 배포 흐름 (Jenkins CI/CD) - -``` -Claude 역할 Jenkins (자동) 운영 서버 -┌───────────────────┐ ┌──────────────────┐ ┌──────────────┐ -│ 코드 작성/수정 │ │ │ │ │ -│ git add / commit │ │ │ │ │ -│ │─push──→ │ Gitea Webhook │ │ │ -│ │(사용자) │ → Jenkins 빌드 │ │ │ -│ │ │ → Lint/Test │ │ │ -│ │ │ → SSH Deploy ────│──→ │ git pull │ -│ │ │ │ │ composer │ -│ │ │ │ │ migrate │ -└───────────────────┘ └──────────────────┘ └──────────────┘ -``` - -> **브랜치 전략**: `develop` → 개발 서버 (자동 배포), `main`/`master` → 운영 서버 (PR 머지 + 팀장 승인) - -### 서버 작업이 필요한 경우 - -사용자에게 명령어를 안내만 한다: - -``` -서버에서 다음 명령을 실행해주세요: -cd /home/webservice/api && git pull && composer install && php artisan migrate -``` - -### 체크리스트 (모든 작업 시) - -- [ ] SSH 명령 사용하지 않음 -- [ ] 서버 파일 직접 수정하지 않음 -- [ ] 배포가 필요하면 사용자에게 안내만 제공 -- [ ] git push까지만 Claude 역할 - ---- - -## React 빌드/배포 정책 (필수 규칙) - -> **경고: React(Next.js) 빌드를 운영 서버에서 직접 실행하지 않는다!** - -### 배경 - -개발 서버(2코어, 3.8GB RAM + Swap 4GB)에서 Jenkins가 React 빌드를 수행한다. -Jenkins 빌드 실패 시 로컬(WSL)에서 빌드 후 결과물을 서버에 배포한다(fallback). - -### 금지 사항 - -``` -❌ 운영 서버에서 npm run build 실행 금지 -❌ 서버 SSH 접속 후 빌드 명령 실행 금지 -❌ Claude가 직접 npm run build 실행 금지 (로컬 포함) -``` - -### 빌드/배포 방법 (Jenkins 자동화) - -``` -Claude 역할 Jenkins (자동) 운영 서버 -┌─────────────────┐ ┌──────────────────┐ ┌──────────────┐ -│ 코드 작성/수정 │ │ Checkout │ │ │ -│ git commit │─push──→ │ Install + Lint │ │ │ -│ │(사용자) │ Build (Next.js) │ │ │ -│ │ │ Package (tar.gz) │──scp→ │ 압축 해제 │ -│ │ │ │ │ node 재시작 │ -└─────────────────┘ └──────────────────┘ └──────────────┘ -``` - -> **Fallback**: Jenkins 빌드 실패(OOM) 시 로컬에서 `react/deploy.sh`로 수동 배포 - -### 빌드가 필요한 상황 - -사용자에게 다음과 같이 안내한다: - -``` -React 코드가 변경되었습니다. git push 후 Jenkins가 자동 배포합니다. -(Jenkins 실패 시 로컬에서 deploy.sh로 수동 배포해주세요.) -``` - ---- - -## 데이터베이스 아키텍처 (필수 규칙) - -> **경고: 이 규칙을 반드시 준수하세요!** - -### 핵심 원칙 - -**모든 데이터베이스 관련 파일은 API 프로젝트에서만 관리합니다.** - -| 항목 | API (`/home/aweso/sam/api`) | MNG (`/home/aweso/sam/mng`) | -|------|----------------------------|----------------------------| -| 마이그레이션 | ✅ 여기에 생성 | ❌ 생성 금지 | -| 시더 | ✅ 여기에 생성 | ⚠️ MNG 전용만 허용 | -| 팩토리 | ✅ 여기에 생성 | ❌ 생성 금지 | - -### 금지 사항 - -``` -❌ /home/aweso/sam/mng/database/migrations/ 에 파일 생성 금지 -❌ MNG에서 테이블 생성/수정 마이그레이션 작성 금지 -``` - -### 허용 사항 - -``` -✅ /home/aweso/sam/api/database/migrations/ 에 모든 마이그레이션 생성 -✅ MNG에서는 MngMenuSeeder 같은 MNG 전용 시더만 허용 -``` - -### 마이그레이션 실행 - -```bash -# 로컬: 마이그레이션은 반드시 API 컨테이너에서 실행 -docker exec sam-api-1 php artisan migrate - -# 개발 서버: Docker 없음, 직접 실행 -cd /home/webservice/api && php artisan migrate - -# 운영 서버: --force 플래그 필수 (production 환경) -cd /home/webservice/api && php artisan migrate --force - -# MNG에서 마이그레이션 실행 금지 (로컬/서버 모두) -``` - -### DB 환경 분리 - -| 환경 | DB명 | 호스트 | 용도 | -|------|------|--------|------| -| 로컬 (Docker) | `samdb` | `sam-mysql-1:3306` | 개발/테스트 | -| 개발 서버 | `samdb` | `localhost` | 스테이징 | -| 운영 서버 | `sam_prod` | `localhost` | 정식 서비스 | -| 통계 DB | `sam_stat` | 동일 서버 | StatMonitorService 전용 | - -> **참고**: `sam_stat`은 API/MNG 모두 `config/database.php`의 별도 connection으로 접속한다. - -### 이유 - -- MNG: 프론트엔드/관리자 화면 담당 (컨트롤러, 뷰, 라우트) -- API: 백엔드/데이터베이스 담당 (마이그레이션, 모델 정의, API) -- 단일 DB를 두 프로젝트가 공유하므로 마이그레이션은 한 곳에서만 관리 - ---- - -## 메뉴 관리 규칙 (필수) - -> **경고: 메뉴 시더(Seeder)를 절대 실행하지 마세요!** - -### 배경 - -메뉴 시더 실행 시 부서별 권한 설정(permission_overrides)이 초기화되는 문제가 반복 발생합니다. -메뉴 ID가 변경되면 기존 부서-메뉴 권한 매핑이 깨지기 때문입니다. - -### 금지 사항 - -``` -❌ php artisan db:seed --class=MngMenuSeeder 실행 금지 -❌ php artisan db:seed --class=*MenuSeeder 실행 금지 -❌ 메뉴 시더 파일 생성 금지 -❌ 메뉴 데이터를 일괄 삭제 후 재생성하는 방식 금지 -``` - -### 메뉴 변경 시 올바른 절차 - -메뉴 추가/수정/삭제/이동이 필요할 때는 **사용자에게 수동 실행 안내**를 제공합니다: - -1. **tinker 명령어를 안내** (사용자가 직접 실행) -2. **또는 SQL 쿼리를 안내** (사용자가 phpMyAdmin 등에서 직접 실행) -3. **절대 시더를 만들어 실행하지 않음** - -### 안내 예시 - -``` -메뉴를 추가하려면 아래 명령을 서버에서 실행해 주세요: - -# 개발 서버 -ssh pro@114.203.209.83 "cd /home/webservice/mng && php artisan tinker --execute=\" -App\\Models\\Commons\\Menu::create([ - 'tenant_id' => 1, - 'parent_id' => <부모ID>, - 'name' => '새 메뉴', - 'url' => '/new-menu', - 'icon' => 'icon-name', - 'sort_order' => 1, - 'is_active' => true, -]); -\"" - -# 운영 서버 (동일 경로, 서버 주소만 변경) -ssh <운영계정>@<운영서버IP> "cd /home/webservice/mng && php artisan tinker --execute=\"...동일...\"" -``` - -### 체크리스트 (메뉴 변경 요청 시) - -- [ ] 시더 파일 생성하지 않음 -- [ ] 시더 실행하지 않음 -- [ ] tinker 또는 SQL로 개별 레코드만 수정 -- [ ] 변경 후 부서 권한 설정이 유지되는지 확인 - ---- - -## 실행 환경 (필수 인지) - -> **중요: 로컬 / 개발 서버 / 운영 서버의 환경이 다릅니다!** - -### 환경 비교 (3-Tier) - -| 항목 | 로컬 (WSL) | 개발 서버 | 운영 서버 | -|------|-----------|----------|----------| -| **구성 방식** | Docker 컨테이너 | Bare-metal (네이티브) | Bare-metal (네이티브) | -| **PHP** | 컨테이너 내부 (8.4) | 직접 설치 (8.4) | 직접 설치 (8.4) | -| **MySQL** | 컨테이너 (sam-mysql-1) | 직접 설치 (8.0) | 직접 설치 (8.0) | -| **Nginx** | 컨테이너 (sam-nginx-1) | 직접 설치 | 직접 설치 | -| **명령 실행** | `docker exec` 필요 | 직접 실행 | 직접 실행 | -| **서버 IP** | localhost | `114.203.209.83` | (신규, 미확정) | -| **추가 서비스** | — | Jenkins, Gitea | — | -| **DB** | `samdb` | `samdb` | `sam_prod` | - -> **배경**: 서버는 Docker가 무거워서 PHP, Nginx, MySQL 등을 네이티브로 설치하여 운영한다. - -### 로컬 환경 (Docker) - -PHP, Laravel, Node.js 등이 **Docker 컨테이너 안에** 설치되어 있다. -로컬 PC(WSL)에는 이런 도구들이 없으므로, 반드시 Docker 컨테이너를 통해 실행한다. - -``` -로컬 PC (WSL) -└── Docker - ├── sam-mng-1 ← PHP + Laravel (MNG 앱) - ├── sam-api-1 ← PHP + Laravel (API 앱) - ├── sam-mysql-1 ← MySQL DB - └── sam-nginx-1 ← Nginx 웹서버 -``` - -### 서버 환경 (Bare-metal — 개발/운영 동일 구조) - -서버에는 Docker가 없다. PHP 8.4, Nginx, MySQL 8.0이 직접 설치되어 있다. - -``` -개발 서버 (114.203.209.83) 운영 서버 (신규) -├── Nginx ├── Nginx -├── PHP-FPM (3 pools) ├── PHP-FPM (3 pools) -│ ├── api.sock │ ├── api.sock -│ ├── mng.sock │ ├── mng.sock -│ └── sales.sock │ └── sales.sock -├── MySQL 8.0 (samdb) ├── MySQL 8.0 (sam_prod) -├── Supervisor ├── Supervisor -│ ├── sam-api-worker (x1) │ ├── sam-api-worker (x1) -│ ├── sam-mng-worker (x2) │ ├── sam-mng-worker (x2) -│ └── sam-api-scheduler │ └── sam-api-scheduler -├── Node.js (React SSR :3000) ├── Node.js (React SSR :3000) -├── Jenkins (:8080) │ -├── Gitea (:3000) │ -├── /home/webservice/api ├── /home/webservice/api -├── /home/webservice/mng ├── /home/webservice/mng -├── /home/webservice/react ├── /home/webservice/react -└── /home/webservice/sales └── /home/webservice/sales -``` - -### 도메인 매핑 - -| 서비스 | 로컬 (Docker) | 개발 서버 | 운영 서버 | -|--------|--------------|----------|----------| -| React (사용자) | `dev.sam.kr` | `dev.codebridge-x.com` | `codebridge-x.com` | -| API | `api.sam.kr` | `api.dev.codebridge-x.com` | `api.codebridge-x.com` | -| MNG (관리자) | `mng.sam.kr` | `admin.codebridge-x.com` | `mng.codebridge-x.com` | -| Sales | `sales.sam.kr` | `sales.dev.codebridge-x.com` | `sales.codebridge-x.com` | -| 5130 (레거시) | `5130.sam.kr` | — | — | - -### 명령어 비교 (로컬 vs 개발 vs 운영) - -| 작업 | 로컬 (Docker) | 개발/운영 서버 (네이티브) | -|------|--------------|-------------------------| -| artisan 실행 | `docker exec sam-api-1 php artisan <명령>` | `cd /home/webservice/api && php artisan <명령>` | -| composer 실행 | `docker exec sam-api-1 composer install` | `cd /home/webservice/api && composer install` | -| 마이그레이션 | `docker exec sam-api-1 php artisan migrate` | 개발: `php artisan migrate` / 운영: `php artisan migrate --force` | -| 캐시 클리어 | `docker exec sam-mng-1 php artisan cache:clear` | `cd /home/webservice/mng && php artisan cache:clear` | -| Queue 재시작 | — | `sudo supervisorctl restart sam-api-worker:*` | - -### 로컬 Docker 명령어 패턴 - -```bash -# MNG 앱에서 artisan 명령 실행 -docker exec sam-mng-1 php artisan <명령어> - -# API 앱에서 artisan 명령 실행 -docker exec sam-api-1 php artisan <명령어> - -# 예시: 시더 실행 -docker exec sam-mng-1 php artisan db:seed --class=MngMenuSeeder - -# 예시: 마이그레이션 실행 (API에서만!) -docker exec sam-api-1 php artisan migrate - -# 예시: 캐시 클리어 -docker exec sam-mng-1 php artisan cache:clear -``` - -### 체크리스트 (명령 실행 시) - -- [ ] **로컬**: `php artisan` → `docker exec sam-mng-1 php artisan` 또는 `sam-api-1` 사용 -- [ ] **로컬**: `composer` → `docker exec sam-mng-1 composer` 또는 `sam-api-1` 사용 -- [ ] **서버**: `php artisan`, `composer` 직접 실행 (Docker 없음) -- [ ] **운영 서버 마이그레이션**: `--force` 플래그 필수 -- [ ] **마이그레이션은 반드시 API에서 실행** (로컬: `docker exec sam-api-1`, 서버: 직접) - ---- - -## 공동 개발 워크플로우 (필수) - -> **중요: 코드를 pull 받은 후 반드시 필요한 명령을 실행하세요!** - -### 브랜치 전략 - -| 브랜치 | 배포 대상 | 트리거 | 승인 | -|--------|----------|--------|------| -| `feature/*` | — | — | — | -| `develop` | 개발 서버 (`dev.codebridge-x.com`) | Push 시 자동 배포 | 불필요 | -| `main`/`master` | 운영 서버 (`codebridge-x.com`) | PR 머지 시 Jenkins 배포 | 팀장 승인 필수 | - -``` -feature/* ──→ develop ──→ main/master - (push) (PR merge) - ↓ ↓ - 개발 서버 운영 서버 - (자동 배포) (Jenkins CI/CD) -``` - -### 로컬 환경 (Docker) 업데이트 - -```bash -# 1. 코드 받기 (WSL에서 실행) -cd /home/aweso/sam/api -git pull - -cd /home/aweso/sam/mng -git pull - -# 2. 의존성 업데이트 (composer.json 변경 시) -docker exec sam-api-1 composer install -docker exec sam-mng-1 composer install - -# 3. DB 마이그레이션 (API에서만!) -docker exec sam-api-1 php artisan migrate - -# 4. 캐시 클리어 (설정 변경 시) -docker exec sam-api-1 php artisan config:clear -docker exec sam-mng-1 php artisan config:clear -``` - -### 개발 서버 업데이트 (자동) - -> `develop` 브랜치에 Push 시 Gitea Webhook → Jenkins가 자동으로 배포한다. -> 수동 배포가 필요한 경우: - -```bash -# API 프로젝트 -cd /home/webservice/api -git pull origin develop -composer install -php artisan migrate -php artisan config:clear - -# MNG 프로젝트 (마이그레이션 없음) -cd /home/webservice/mng -git pull origin develop -composer install -php artisan config:clear -``` - -### 운영 서버 배포 (Jenkins 자동화) - -> `main`/`master` 브랜치에 PR 머지 시 Jenkins가 자동으로 배포한다. -> 수동 배포는 **비상 절차**로만 사용한다. - -```bash -# 비상 수동 배포 (Jenkins 장애 시에만) -# API 프로젝트 -cd /home/webservice/api -git pull origin main -composer install --no-dev --optimize-autoloader -php artisan migrate --force -php artisan config:clear && php artisan cache:clear && php artisan route:cache && php artisan view:cache -sudo supervisorctl restart sam-api-worker:* - -# MNG 프로젝트 -cd /home/webservice/mng -git pull origin master -composer install --no-dev --optimize-autoloader -php artisan config:clear && php artisan cache:clear && php artisan view:cache -sudo supervisorctl restart sam-mng-worker:* -``` - -### 요약 표 - -| 작업 | 로컬 (Docker) | 개발 서버 | 운영 서버 | -|------|--------------|----------|----------| -| 배포 방식 | 수동 | Jenkins 자동 (develop push) | Jenkins 자동 (main/master PR) | -| git pull | WSL에서 직접 | Jenkins 자동 | Jenkins 자동 | -| composer install | `docker exec sam-api-1 composer install` | Jenkins 자동 | `--no-dev --optimize-autoloader` | -| migrate | `docker exec sam-api-1 php artisan migrate` | Jenkins 자동 | `--force` 플래그 포함 | -| config:clear | `docker exec sam-api-1 php artisan config:clear` | Jenkins 자동 | `route:cache` + `view:cache` 포함 | - -### 체크리스트 (pull 후) - -- [ ] API: `git pull` → `composer install` → `php artisan migrate` → `config:clear` -- [ ] MNG: `git pull` → `composer install` → `config:clear` (마이그레이션 없음) -- [ ] 운영 배포: `main`/`master`에 PR 머지 → Jenkins 자동 처리 (수동 금지) - ---- - -## 사용 가능한 Agents - -`~/.claude/agents/` 폴더에 있는 에이전트들: - -### 코드 품질 & 개발 - -| Agent | 모델 | 설명 | 출처 | -|-------|------|------|------| -| `code-reviewer` | sonnet | 코드 리뷰 (품질/보안/유지보수성), 메모리 학습 지원 | 공식 문서 패턴 | -| `debugger` | sonnet | 에러/테스트 실패 근본 원인 분석 및 수정 | 공식 문서 패턴 | -| `test-runner` | haiku | 테스트 실행 및 결과 분석/요약 | 커뮤니티 인기 | -| `security-auditor` | sonnet | OWASP Top 10 기반 보안 취약점 감사 | 커뮤니티 인기 | -| `performance-optimizer` | sonnet | N+1 쿼리, 알고리즘, 캐싱 최적화 | 커뮤니티 인기 | -| `refactoring-agent` | sonnet | 코드 구조 개선, SOLID 원칙, DRY 위반 제거 | 커뮤니티 인기 | -| `laravel-expert` | sonnet | Laravel 전문가 (SAM 프로젝트 환경 인지) | 커스텀 | - -### 워크플로우 & 문서 - -| Agent | 모델 | 설명 | 출처 | -|-------|------|------|------| -| `git-manager` | haiku | Git 브랜치/커밋/머지/PR 관리 | 커뮤니티 인기 | -| `doc-writer` | haiku | API 문서, README, 기술 가이드 작성 | 커뮤니티 인기 | -| `research-agent` | sonnet | 웹 리서치 및 자료 조사 | 기존 | -| `organizer-agent` | - | 프로젝트 구조화 및 정리 | 기존 | -| `proposal-agent` | - | 제안서 작성 | 기존 | - ---- - -## 사용 가능한 Skills - -`~/.claude/skills/` 폴더에 있는 스킬들 (슬래시 명령어로 사용): - -### 문서/프레젠테이션 - -| Skill | 설명 | -|-------|------| -| `pptx-skill` | PowerPoint 생성 | -| `ppt-auto-generator` | 마크다운/텍스트에서 PPT 생성 | -| `pdf-template-skill` | PDF 템플릿 분석/생성 | -| `text-analyzer-skill` | 텍스트 분석 및 PDF 구조 매핑 | -| `proposal-skill` | 제안서 생성 | -| `storyboard-generator` | 스토리보드 생성 | -| `design-skill` | 프레젠테이션 HTML 디자인 | - -### 코드 분석/시각화 - -| Skill | 설명 | -|-------|------| -| `code-flow-web-report` | 웹 앱 런타임 흐름 시각화 리포트 | -| `code-flow-web-doc-generator` | 소스 코드 호출/데이터 흐름 다이어그램 HTML 생성 | -| `codebase-analysis-web-report` | 코드베이스 아키텍처 인터랙티브 HTML 리포트 | -| `uml-generator` | UML 다이어그램 생성 | - -### 코드 품질 (levnikolaevich/claude-code-skills) - -| Skill | 설명 | 출처 | -|-------|------|------| -| `code-bug-finder` | 버그 자동 탐지 및 보고서 생성 | 기존 | -| `code-refactoring` | 리팩토링 권장사항/성능 분석/코드 패치 | 기존 | -| `code-commenter` | 소스 코드에 이해하기 쉬운 주석 추가 | 기존 | -| `async-await-keyword-fixer` | JS/TS 누락된 async/await 수정 | 기존 | -| `code-quality-checker` | DRY/KISS/YAGNI 위반 탐지 | levnikolaevich | -| `code-quality-auditor` | 코드 복잡도, 매직넘버 분석 | levnikolaevich | -| `code-principles-auditor` | DRY/KISS/YAGNI, TODO, DI 패턴 검사 | levnikolaevich | -| `dead-code-auditor` | 미사용 코드 탐지 | levnikolaevich | -| `build-auditor` | 컴파일러/타입 에러 검사 | levnikolaevich | -| `concurrency-auditor` | 레이스 컨디션 탐지 | levnikolaevich | -| `layer-boundary-auditor` | 레이어 위반, I/O 격리 검사 | levnikolaevich | -| `observability-auditor` | 로깅, 메트릭 적절성 검사 | levnikolaevich | -| `query-efficiency-auditor` | DB 쿼리 효율성 분석 | levnikolaevich | -| `dependencies-auditor` | 오래된 패키지, CVE 취약점 검사 | levnikolaevich | -| `regression-checker` | 기존 테스트 실행으로 사이드이펙트 탐지 | levnikolaevich | -| `story-quality-gate` | 코드리뷰 + 테스트 2단계 품질 검증 | levnikolaevich | - -### 테스트/커버리지 - -| Skill | 설명 | 출처 | -|-------|------|------| -| `app-comprehensive-test-generator` | 테스트 시나리오 생성/실행, QA 리포트 | 기존 | -| `coverage-improvement-planner` | 테스트 커버리지 분석 및 개선 계획 | 기존 | -| `test-coverage-auditor` | 테스트 커버리지 측정/분석 | levnikolaevich | -| `test-isolation-auditor` | 테스트 독립성/격리 검사 | levnikolaevich | -| `webapp-testing` | Playwright 기반 웹 앱 UI 테스트 | anthropics 공식 | - -### 보안 (Trail of Bits) - -| Skill | 설명 | 출처 | -|-------|------|------| -| `security-auditor` | 시크릿 노출, Injection, XSS 탐지 | levnikolaevich | -| `static-analysis` | CodeQL/Semgrep/SARIF 정적 분석 (3개 하위 스킬) | Trail of Bits | -| `insecure-defaults` | 위험한 기본 설정, 하드코딩 자격증명 탐지 | Trail of Bits | -| `sharp-edges` | 에러 유발 API, 위험한 디자인 패턴 탐지 | Trail of Bits | -| `differential-review` | 보안 중심 코드 변경 리뷰 | Trail of Bits | - -### 디버깅/로깅 - -| Skill | 설명 | -|-------|------| -| `system-debug-logger` | 에러/예외 자동 캡처 디버그 로깅 | -| `node-debug-logging-middleware` | Node.js Express/Koa 디버깅 로그 미들웨어 | - -### 프론트엔드/UI - -| Skill | 설명 | 출처 | -|-------|------|------| -| `frontend-design` | 프론트엔드 디자인 품질 향상 (AI slop 방지) | anthropics 공식 | -| `flutter-ux-hardening` | Flutter 앱 UI/UX 강화 | 기존 | -| `웹문서` | SAM 프로젝트 웹문서 디자인 표준 | 기존 | - -### 유틸리티 - -| Skill | 설명 | -|-------|------| -| `duplicate-file-cleaner` | 중복 이미지/미디어 파일 정리 | -| `npm-release-manager` | NPM 패키지 배포 자동화 | - -**사용 방법**: `/skill-name` 형식으로 호출 (예: `/code-quality-checker`) - ---- - -## 문서 작성 규칙 (개발팀 협약 - 필수 준수) - -> **경고: 개발자들이 `sam/docs`의 문서 작성 기법을 준용하기로 협약했습니다. 모든 문서 작성 시 반드시 따르세요!** - -### 참조 경로 - -- **인덱스**: `/home/aweso/sam/docs/INDEX.md` (전체 문서 목록 및 폴더 구조) -- **작업 전 확인**: 작업 유형에 맞는 문서를 `INDEX.md`에서 찾아 먼저 읽고 시작 - -### 폴더 선택 기준 (의미 기반 분류) - -| 폴더 | 질문 | 설명 | -|------|------|------| -| `plans/` | "무슨 작업을 할 것인가?" | 임시 개발 계획 (완료 후 삭제) | -| `standards/` | "어떻게 코드를 작성할 것인가?" | 코딩 컨벤션, 스타일 가이드 | -| `architecture/` | "왜 이렇게 설계하는가?" | 시스템 설계, 아키텍처 결정 | -| `rules/` | "무엇이 유효한 데이터인가?" | 비즈니스 규칙, 검증 규칙 | -| `specs/` | "무엇을 구현할 것인가?" | 기술 스펙, DB 스키마 | -| `guides/` | "어떻게 구현할 것인가?" | 단계별 구현 매뉴얼 | -| `features/` | 기능별 상세 | 기능 단위 심층 문서 | -| `changes/` | "무엇이 변경되었는가?" | 완료된 변경 이력 | - -### 파일명 규칙 - -- **일반 문서**: `kebab-case.md` (소문자 + 하이픈) 예: `api-rules.md`, `item-policy.md` -- **변경 이력**: `YYYYMMDD_short_description.md` 예: `20260109_handover_report_api.md` -- **폴더 인덱스**: `README.md` (대문자) -- **크기 목표**: 10KB 이하 -- **새 문서 작성 시**: 반드시 `docs/INDEX.md`에 추가 - -### 문서 구조 템플릿 - -#### 정책/규칙 문서 (`rules/`, `standards/`) - -```markdown -# 제목 - -> **작성일**: YYYY-MM-DD -> **상태**: 설계 확정 - ---- - -## 1. 개요 -### 1.1 목적 -### 1.2 핵심 원칙 - ---- - -## 2. 테이블 구조 (해당 시) -### 2.1 ERD 개요 - ---- - -## N. 비즈니스 규칙 -### N.1 검증 규칙 - ---- - -## N. API 엔드포인트 - ---- - -## 관련 문서 - ---- - -**최종 업데이트**: YYYY-MM-DD -``` - -#### 변경 이력 문서 (`changes/`) - -```markdown -# 변경 내용 요약 - -**날짜:** YYYY-MM-DD -**작업자:** Claude Code - -## 변경 개요 - -## 수정된 파일 -| 파일 | 변경 내용 | -|------|----------| - -## 상세 변경 사항 - -## 테스트 체크리스트 -- [x] 완료 항목 -- [ ] 미완료 항목 - -## 관련 문서 -``` - -### 작성 스타일 규칙 - -| 항목 | 규칙 | -|------|------| -| **언어** | 한글 기본, 코드/경로/기술 식별자만 영어 | -| **어조** | 서술형 ("X를 해야 한다" 아닌 "X 한다") | -| **경고** | `> **경고: ...**` 블록인용 형식 | -| **금지/필수** | `❌` 금지, `✅` 필수 접두사 | -| **우선순위** | `🔴 필수`, `🟡 중요`, `🟢 권장` | -| **섹션 번호** | `## 1.`, `### 1.1` 번호 매기기 | -| **규칙 번호** | R1, R2, R3... 순차 라벨 | -| **코드 블록** | 반드시 언어 지정 (```php, ```bash, ```json, ```sql) | -| **인라인 코드** | 파일 경로, 메서드명, 변수명, 컬럼명에 백틱 | -| **다이어그램** | `┌─┐│└─┘` 박스 문자, `→` 화살표 사용 | -| **구분선** | `---` 주요 섹션 사이마다 | -| **테이블** | API: `| Method | Path | 설명 |`, 필드: `| 필드 | 타입 | 설명 |` | - -### plans/ 워크플로우 - -1. 개발 계획 문서를 `plans/`에 작성 -2. 작업 진행 -3. 완료 후 결과물을 해당 폴더(`features/`, `changes/` 등)에 정리 -4. plan 문서 삭제 - -### 체크리스트 (문서 작성 시) - -- [ ] 적절한 폴더에 배치 (위 폴더 선택 기준 참고) -- [ ] `kebab-case.md` 파일명 사용 -- [ ] 문서 구조 템플릿 준수 -- [ ] 한글 기본, 기술 용어만 영어 -- [ ] 코드 블록에 언어 지정 -- [ ] `docs/INDEX.md`에 새 문서 등록 -- [ ] 10KB 이하 크기 유지 - ---- - -## PPT / 프레젠테이션 제작 규칙 (필수 준수) - -> **경고: 모든 프레젠테이션 및 문서 제작 시 반드시 따르세요!** - -### 회사 정보 - -| 항목 | 값 | -|------|------| -| **공식 회사명** | **(주)코드브릿지엑스** | -| **서비스명** | **SAM** (Smart Automation Management) | -| **푸터 표기 예시** | `SAM 서비스 요금 안내 | (주)코드브릿지엑스` | - -### 금지 사항 - -``` -❌ "주일/경동" — 문서, 슬라이드, 푸터 어디에도 사용 금지 -❌ "주일", "경동" 단독 사용 금지 -❌ 내부 제조사(주일/경동) 이름을 외부 문서에 노출 금지 -``` - -> **배경**: 주일/경동은 SAM을 기반으로 만든 내부 제조업체 이름이며, 대외 문서에 노출되어서는 안 된다. -> 모든 대외 문서의 회사명은 **(주)코드브릿지엑스**를 사용한다. - -### SAM BI (Brand Identity) 이미지 - -**프로젝트 내 경로**: `/home/aweso/sam/docs/assets/bi/` - -| 파일 | 용도 | 배경 | -|------|------|------| -| `sam_bi_black.png` | 밝은 배경 슬라이드 | 투명 배경, 검정 로고 | -| `sam_bi_white.png` | 다크 배경 슬라이드 | 투명 배경, 흰색 로고 | -| `sam_bi_blue.png` | 청색 테마 슬라이드 | 투명 배경, 파란 로고 | -| `sam_bi_green.png` | 녹색 테마 슬라이드 | 녹색 배경, 흰색 로고 | -| `sam_bi_red.png` | 적색/대외비 슬라이드 | 적색 배경, 흰색 로고 | -| `sam_bi_orange.png` | 주황 포인트 슬라이드 | 주황 배경, 흰색 로고 | -| `sam_bi_purple.png` | 보라 테마 슬라이드 | 보라 배경, 흰색 로고 | - -### PPT 슬라이드 제작 시 적용 규칙 - -1. **표지(slide-01)에 BI 로고 필수** — 배경색에 맞는 BI 이미지 사용 -2. **푸터에 회사명**: `(주)코드브릿지엑스` (주일/경동 절대 금지) -3. **BI 로고 + "SAM" 텍스트** 조합 사용 권장 -4. **배경색별 BI 선택**: - - 다크 배경 → `sam_bi_white.png` - - 밝은 배경 → `sam_bi_black.png` - - 테마 컬러 배경 → 해당 색상 BI (green, blue, red 등) - -### 체크리스트 (PPT 제작 시) - -- [ ] 회사명: (주)코드브릿지엑스 사용 -- [ ] "주일/경동" 미포함 확인 -- [ ] 표지에 SAM BI 로고 포함 -- [ ] 푸터에 (주)코드브릿지엑스 표기 -- [ ] 배경색에 맞는 BI 색상 선택 diff --git a/sam/docs/INDEX.md b/sam/docs/INDEX.md deleted file mode 100644 index cbc7d50..0000000 --- a/sam/docs/INDEX.md +++ /dev/null @@ -1,421 +0,0 @@ -# SAM 프로젝트 문서 인덱스 - -> **Claude Code 작업 전 필수 확인** — 작업 유형에 맞는 문서를 먼저 읽고 시작하세요. -> **최종 갱신**: 2026-03-08 - ---- - -## 🎯 작업별 필수 문서 - -| 작업 유형 | 필수 문서 | 용도 | -|----------|----------|------| -| **API 개발** | `standards/api-rules.md` | Service-First, FormRequest, i18n 규칙 | -| **DB 변경** | `system/database/README.md` | 테이블 구조, 관계, 컬럼 규칙 | -| **새 기능 구현** | `system/overview.md` | 전체 아키텍처 이해 | -| **보안 관련** | `system/security-policy.md` | 인증/인가, 보안 규칙 | -| **Git 커밋** | `standards/git-conventions.md` | 커밋 메시지, 브랜치 전략 | -| **품질 검증** | `standards/quality-checklist.md` | 코드 품질 체크리스트 | -| **Swagger 작성** | `guides/swagger-guide.md` | API 문서 작성 방법 | -| **품목관리** | `rules/item-policy.md` | 품목 정책 (유형, 예약어, API 규칙) | -| **단가관리** | `rules/pricing-policy.md` | 원가/판매가 계산, 리비전 관리 | -| **견적관리** | `features/quotes/README.md` | 견적 시스템, BOM 계산, 10단계 로직 | -| **결재관리** | `features/approvals/README.md` | 결재 시스템 (워크플로우, API, UI) | -| **운영 배포** | `plans/production-deployment-plan.md` | 운영 환경 배포 계획 | -| **서버 운영** | `deploys/ops-manual/README.md` | 서버 운영 매뉴얼 | -| **MES 개발** | `projects/mes/README.md` | MES 프로젝트 개요 | - ---- - -## 📁 폴더 구조 - -``` -docs/ -├── system/ # 시스템 현황 — 아키텍처, DB 스키마, 인프라 (architecture/ + specs/ 통합) -├── standards/ # 개발 표준 — "어떻게 코드를 작성할 것인가" -├── rules/ # 비즈니스 규칙 — "무엇이 유효한 데이터인가" -├── features/ # 기능별 상세 — 도메인별 기능 문서 -├── guides/ # 구현 가이드 — "어떻게 구현할 것인가" -├── quickstart/ # 빠른 시작 — 핵심 요약, 명령어 -├── plans/ # 작업 추적 — 예정 → 진행 → 완료 → archive/ -├── projects/ # 프로젝트 자료 — 프로젝트성 분석, 설계, 참고 -├── deploys/ # 운영 매뉴얼 — 서버 운영, 배포 -├── changes/ # 변경 이력 -├── data/ # 데이터 분석 -├── history/ # 히스토리 기록 -├── api/ # API 통합 문서 -├── requests/ # 요청/기획 문서 -└── assets/ # BI 등 정적 자산 -``` - ---- - -## 📚 폴더별 문서 목록 - -### system/ — 시스템 현황 -> 아키텍처, DB 스키마, 기술 스펙, 인프라 (기존 architecture/ + specs/ 통합) - -| 문서 | 설명 | -|------|------| -| [overview.md](system/overview.md) | 전체 시스템 아키텍처 (api/react/mng 구조, 기술 스택) | -| [api-structure.md](system/api-structure.md) | API 서버 구조 (~1,027 엔드포인트, 18 도메인) | -| [react-structure.md](system/react-structure.md) | React 프론트엔드 구조 (249 페이지, 612 컴포넌트) | -| [mng-structure.md](system/mng-structure.md) | MNG 관리자 패널 구조 (171 컨트롤러, 436 뷰) | -| [docker-setup.md](system/docker-setup.md) | Docker 환경 + CI/CD (7 서비스, Jenkins) | -| [database/README.md](system/database/README.md) | DB 스키마 인덱스 (220 모델, 32 도메인, 459 마이그레이션) | - -**DB 도메인별 스키마:** - -| 문서 | 포함 도메인 | -|------|-----------| -| [database/tenants.md](system/database/tenants.md) | 테넌트, 사용자, 권한 (63 모델) | -| [database/products.md](system/database/products.md) | 제품, 품목, 설계 (21 모델) | -| [database/sales.md](system/database/sales.md) | 영업, 수주, 견적 (18 모델) | -| [database/production.md](system/database/production.md) | 생산, 시공, 자재, 품질 (20 모델) | -| [database/finance.md](system/database/finance.md) | 재무, 회계 | -| [database/hr.md](system/database/hr.md) | 인사, 면접 | -| [database/documents.md](system/database/documents.md) | 문서, 전자서명 (19 모델) | -| [database/commons.md](system/database/commons.md) | 공통, 게시판, 감사 (17 모델) | -| [database/stats.md](system/database/stats.md) | 통계 (21 모델, sam_stat DB) | -| [database/codebridge-separation.md](system/database/codebridge-separation.md) | codebridge DB 분리 (MNG 전용 118 테이블, 78 모델) | - -**이관 완료 (architecture/ + specs/ → system/):** - -| 문서 | 설명 | -|------|------| -| [security-policy.md](system/security-policy.md) | 보안 정책 (다층 방어, Sanctum, RBAC) | -| [scaling-roadmap.md](system/scaling-roadmap.md) | 10K 테넌트 스케일링 로드맵 | -| [ai-automation-vision.md](system/ai-automation-vision.md) | SAM AI 자동화 비전 및 장기 로드맵 | -| [board-system-spec.md](system/board-system-spec.md) | 게시판 시스템 설계 스펙 | -| [item-master-integration.md](system/item-master-integration.md) | 품목 마스터 통합 설계 | -| [remote-work-setup.md](system/remote-work-setup.md) | 원격 개발 설정 (DEPRECATED) | -| [erp-analysis/](system/erp-analysis/) | ERP 스토리보드 분석 (9개 파일) | - ---- - -### standards/ — 개발 표준 -> 코딩 컨벤션, 스타일 가이드, 품질 기준 - -| 문서 | 설명 | 필수 확인 시점 | -|------|------|--------------| -| [api-rules.md](standards/api-rules.md) | API 개발 규칙 (Service-First, FormRequest, i18n) | API 개발 전 | -| [git-conventions.md](standards/git-conventions.md) | Git 커밋 메시지, 브랜치 전략 | 커밋 전 | -| [quality-checklist.md](standards/quality-checklist.md) | 코드 품질 체크리스트 | PR 전 | -| [pagination-policy.md](standards/pagination-policy.md) | 페이지네이션 표준 | 목록 API 구현 시 | -| [options-column-policy.md](standards/options-column-policy.md) | JSON options 컬럼 표준 정책 (마이그레이션, 모델, 쿼리) | 테이블 생성/확장 시 | - ---- - -### rules/ — 비즈니스 규칙 -> 도메인 로직, 검증 규칙, 정책 - -| 문서 | 설명 | 필수 확인 시점 | -|------|------|--------------| -| [README.md](rules/README.md) | 비즈니스 규칙 개요 | 도메인 로직 구현 전 | -| [item-policy.md](rules/item-policy.md) | 품목 정책 (유형, 예약어, API 규칙) | 품목 관련 작업 전 | -| [pricing-policy.md](rules/pricing-policy.md) | 단가 정책 (원가/판매가, 리비전) | 단가 관련 작업 전 | -| [customer-pricing.md](rules/customer-pricing.md) | 고객 안내용 서비스 요금표 | 고객 요금 안내 시 | -| [partner-commission.md](rules/partner-commission.md) | 영업파트너 수당 체계 및 정산 | 수당/정산 관련 작업 전 | -| [billing-policy.md](rules/billing-policy.md) | 내부용 원가/마진/코드참조 (CONFIDENTIAL) | 과금 코드 개발 전 | -| [client-policy.md](rules/client-policy.md) | 고객사 관리 정책 | 고객 관련 작업 전 | -| [attendance-api.md](rules/attendance-api.md) | 근태 API 규칙 | 근태 관련 작업 전 | -| [department-tree-api.md](rules/department-tree-api.md) | 부서 트리 API 규칙 | 부서 관련 작업 전 | -| [employee-api.md](rules/employee-api.md) | 직원 API 규칙 | 직원 관련 작업 전 | -| [numbering-rules.md](rules/numbering-rules.md) | 채번규칙 (패턴 기반 자동 번호 생성) | 채번 로직 수정 전 | - ---- - -### features/ — 기능별 문서 -> 도메인별 기능 상세 (기능 설명 + 엔드포인트 경로 + Swagger 참조) - -| 문서 | 설명 | -|------|------| -| [quotes/README.md](features/quotes/README.md) | 견적 시스템 (BOM 계산, 10단계 로직) | -| [boards/README.md](features/boards/README.md) | 게시판 시스템 구현 | -| [boards/mng-implementation.md](features/boards/mng-implementation.md) | MNG 게시판 구현 상세 | -| [hr/attendance-management-spec.md](features/hr/attendance-management-spec.md) | 근태관리 기획서 | -| [hr/hr-api-analysis.md](features/hr/hr-api-analysis.md) | HR API 분석 (근태/직원/부서) | -| [barobill-kakaotalk/README.md](features/barobill-kakaotalk/README.md) | 바로빌 카카오톡 + 세금계산서 연동 | -| ~~business-card-request.md~~ | 명함신청 관리 (DB 마이그레이션만 존재, 문서 미작성) | -| [sales/README.md](features/sales/README.md) | 영업 관리 (면접 시나리오 포함) | -| [crm/README.md](features/crm/README.md) | CRM (거래처, 미수금, 미지급금) | -| [finance/README.md](features/finance/README.md) | 재무 관리 (14개 하위 문서) | -| [card-vehicle/README.md](features/card-vehicle/README.md) | 법인카드·차량 관리 | -| [settlement/README.md](features/settlement/README.md) | 정산 관리 | -| [esign/README.md](features/esign/README.md) | 전자서명 (계약·OTP·PDF 합성) | -| [documents/README.md](features/documents/README.md) | 문서관리 (EAV 기반 서식·결재) | -| [ai/README.md](features/ai/README.md) | AI 분석 리포트 (Gemini 연동) | -| [equipment/README.md](features/equipment/README.md) | 설비관리 (MNG 전용) | -| [approvals/README.md](features/approvals/README.md) | 결재관리 시스템 (순차결재, 보류/전결/참조/복사재기안) | -| [planning/README.md](features/planning/README.md) | 주일기업 기획 (견적/프로젝트/사진대지/회의록/AI) | -| [rd/README.md](features/rd/README.md) | R&D (조직도/AI견적/기획디자인/디자인 인사이트/사운드 로고/CM송) | -| [rd/planning-design.md](features/rd/planning-design.md) | 기획디자인 스토리보드 에디터 기술 명세 | -| [rd/design-insight.md](features/rd/design-insight.md) | 디자인 인사이트 UI/UX 연구 도구 (100종 패턴, AI 프롬프트) | -| [rd/sound-logo-studio.md](features/rd/sound-logo-studio.md) | 사운드 로고 스튜디오 (시퀀서 + Gemini TTS + Lyria BGM 합성) | - ---- - -### guides/ — 구현 가이드 -> 특정 기능 구현을 위한 단계별 매뉴얼 - -| 문서 | 설명 | 필수 확인 시점 | -|------|------|--------------| -| [swagger-guide.md](guides/swagger-guide.md) | Swagger API 문서 작성법 | API 문서 작성 전 | -| [file-storage-guide.md](guides/file-storage-guide.md) | 파일 업로드/다운로드 구현 | 파일 기능 구현 전 | -| [item-management-migration.md](guides/item-management-migration.md) | Item 시스템 전환 가이드 | 마이그레이션 작업 전 | -| [project-launch-roadmap.md](guides/project-launch-roadmap.md) | 런칭 준비 현황 | 런칭 관련 작업 시 | -| [production-env-sync.md](guides/production-env-sync.md) | 운영 전환 시 .env 동기화 | 테스트→운영 전환 시 | -| [server-how-it-works.md](guides/server-how-it-works.md) | 서버 동작 원리 | 신규 합류 시 | -| [nginx-fastcgi-guide.md](guides/nginx-fastcgi-guide.md) | Nginx & FastCGI 가이드 | 서버 이해 시 | -| [php-fpm-guide.md](guides/php-fpm-guide.md) | PHP-FPM 가이드 | 서버 이해 시 | -| [jenkins-setup-guide.md](guides/jenkins-setup-guide.md) | Jenkins CI/CD 셋업 | Jenkins 설치/설정 시 | -| [auto-login-guide.md](guides/auto-login-guide.md) | MNG→DEV 자동 로그인 | 자동 로그인 구현 시 | -| [erp-api-list.md](guides/erp-api-list.md) | ERP API 목록 (List vs Detail 구분) | 프론트 API 연동 시 | -| [erp-api-detail.md](guides/erp-api-detail.md) | ERP API 상세 스펙 | 프론트 API 연동 시 | -| [table-design-guide.md](guides/table-design-guide.md) | 테이블 설계 가이드 (비전문가용, options JSON 패턴) | 테이블 구조 이해 시 | -| [item-master-guide.md](guides/item-master-guide.md) | 품목기준관리 페이지-섹션-필드 구조 | 품목 UI 구현 시 | -| [item-master-items-api.md](guides/item-master-items-api.md) | ItemMaster & Items API 문서 | 품목 API 연동 시 | -| [ai-management.md](guides/ai-management.md) | AI 관리 종합 가이드 (아키텍처, 버전 이력, 온보딩) | AI 관련 작업 시 | -| [ai-model-update-workflow.md](guides/ai-model-update-workflow.md) | AI 모델 업데이트 표준 절차 (7단계) | AI 모델 변경 시 | -| [ai-config-settings.md](guides/ai-config-settings.md) | AI 설정 기술문서 (DB 구조, 메서드) | AI 설정 구현 시 | - ---- - -### quickstart/ — 빠른 시작 -> 핵심 규칙 요약, 자주 쓰는 명령어 - -| 문서 | 설명 | -|------|------| -| [quick-start.md](quickstart/quick-start.md) | 프로젝트 핵심 규칙 요약 | -| [dev-commands.md](quickstart/dev-commands.md) | 일상 개발 명령어 모음 | - ---- - -### plans/ — 작업 추적 -> 예정 → 진행 → 완료 → archive/ (이미 정리 완료, 현행 유지) - -| 문서 | 설명 | -|------|------| -| [index_plans.md](plans/index_plans.md) | 계획 인덱스 (ACTIVE + PLANNED) | -| [GUIDE.md](plans/GUIDE.md) | 계획 문서 작성 가이드 | -| [fire-shutter-drawing-generator-plan.md](plans/fire-shutter-drawing-generator-plan.md) | 방화셔터 도면생성 기능 기획서 (가이드레일 단면도 + 셔터박스 + 3D 렌더링) | - ---- - -### projects/ — 프로젝트 자료 -> 프로젝트성 분석, 설계, 참고 자료 (지속 보관) - -| 프로젝트 | 문서 | 설명 | -|---------|------|------| -| [index_projects.md](projects/index_projects.md) | 프로젝트 인덱스 | | -| **MES** | [README.md](projects/mes/README.md) | MES 프로젝트 개요 | -| **MES** | [MES_PROJECT_ROADMAP.md](projects/mes/MES_PROJECT_ROADMAP.md) | 개발 로드맵 | -| **5130 이관** | [MASTER_PLAN.md](projects/5130-migration/MASTER_PLAN.md) | 레거시 이관 마스터 플랜 | -| **API 연동** | [MASTER_PLAN.md](projects/api-integration/MASTER_PLAN.md) | React↔API 연동 | -| **Legacy** | [draw-module.md](projects/legacy-5130/draw-module.md) | 레거시 드로우 모듈 | -| **견적** | [quotation/](projects/quotation/) | 견적 프로젝트 자료 | -| **전자서명** | [e-sign/](projects/e-sign/) | 전자서명 프로젝트 자료 | -| **조직도** | [org-chart/README.md](projects/org-chart/README.md) | 조직도 관리 (트리형, 드래그앤드롭, 숨기기) | - ---- - -### deploys/ — 운영 매뉴얼 -> 서버 운영, 배포 (현행 유지) - -| 문서 | 설명 | -|------|------| -| [ops-manual/README.md](deploys/ops-manual/README.md) | 서버 운영 매뉴얼 (11부 구성) | - ---- - -### changes/ — 변경 이력 -> 파일명 형식: `YYYYMMDD_description.md` - -| 문서 | 설명 | -|------|------| -| [20260304_eaccount_infinite_loop_fix.md](changes/20260304_eaccount_infinite_loop_fix.md) | 계좌 입출금내역 부분 월 조회 시 무한루프 크래시 수정 | -| [20260306_purchase_request_payment_method.md](changes/20260306_purchase_request_payment_method.md) | 품의서 지급방법 UI 개선 (구매품의서 추가, 비용정산품의서 행별 변경) | - ---- - -### data/ — 데이터 분석 - -| 문서 | 설명 | -|------|------| -| [analysis/item-db-analysis.md](data/analysis/item-db-analysis.md) | Item DB/API 분석 최종본 | -| [analysis/bom-item-mapping-analysis.md](data/analysis/bom-item-mapping-analysis.md) | BOM-품목 매핑 분석 | - -### contracts/ - 전자계약서 버전 관리 -> DOCX 배포본 + Markdown 추적본 + 자동화 스크립트 - -| 문서 | 설명 | -|------|------| -| [CHANGELOG.md](contracts/CHANGELOG.md) | 전체 개정이력 | -| [revisions.json](contracts/revisions.json) | 개정 데이터 | -| [docx/](contracts/docx/) | DOCX 배포본 (전자서명용 4종, 바로 사용 가능) | -| [markdown/](contracts/markdown/) | Markdown 추적본 (Git diff용 4종) | -| [scripts/extract_to_markdown.py](contracts/scripts/extract_to_markdown.py) | DOCX → Markdown 추출 | -| [scripts/sync_check.py](contracts/scripts/sync_check.py) | DOCX ↔ Markdown 동기화 검증 | - -### plans/ - 개발 계획 -> 임시 개발 계획 문서 (작업 완료 후 정리 → 삭제) - -| 문서 | 설명 | -|------|------| -| [SAM_ERP_Storyboard_D1.4_260116.md](plans/SAM_ERP_Storyboard_D1.4_260116.md) | ERP 전체 스토리보드 D1.4 (167p PDF → 마크다운 변환, 14개 섹션 146개 화면) | -| [SAM_ERP_Storyboard_D1.4.md](plans/SAM_ERP_Storyboard_D1.4.md) | ERP 스토리보드 D1.4 AI 최적화 버전 (구조화된 한글 마크다운, 15개 섹션) | -| [SAM_ERP_회계관리_Storyboard_D1.6.md](plans/SAM_ERP_회계관리_Storyboard_D1.6.md) | ERP 회계관리 스토리보드 D1.6 (65p PDF → 마크다운 변환) | -| [SAM_General_Rule_Storyboard_D1.0.md](plans/SAM_General_Rule_Storyboard_D1.0.md) | General Rule 스토리보드 D1.0 (43p PDF → 마크다운 변환, UIUX 공통 규칙) | -| [production-deployment-plan.md](plans/production-deployment-plan.md) | 운영 환경 배포 계획 (CI/CD, 서버 아키텍처) | -| [attendance-management-plan.md](plans/attendance-management-plan.md) | 근태현황 개발 계획 (Phase 1~2, HTMX 기반) | -| [leave-management-plan.md](plans/leave-management-plan.md) | 휴가관리 모듈 개발 계획 (연차 발생/신청/승인/정책) | -| [approval-management-system-plan.md](plans/approval-management-system-plan.md) | 결재관리 시스템 기획서 (전자결재 전체 설계: 기안~회수, DB 설계, 17개 양식, 4 Phase) | -| [block-builder-evolution-plan.md](plans/block-builder-evolution-plan.md) | 양식 디자이너(Block Builder) 고도화 계획 (6 Phase: 렌더러→결재→동적테이블→수식→인쇄→Legacy 대체) | -| [design-insight-menu-plan.md](plans/design-insight-menu-plan.md) | UI/UX 디자인 인사이트 연구 메뉴 기획서 (레퍼런스 수집, 화면 분석, 패턴 라이브러리, Before/After) | -| [sound-logo-generator-plan.md](plans/sound-logo-generator-plan.md) | 사운드 로고 생성기 기획서 (Web Audio + Gemini AI 어시스트 + Lyria 자동 생성) | - -### features/ - 기능별 문서 - -| 문서 | 설명 | -|------|------| -| [barobill-kakaotalk/README.md](features/barobill-kakaotalk/README.md) | 바로빌 카카오톡 (알림톡/친구톡) 연동 | -| [boards/README.md](features/boards/README.md) | 게시판 시스템 구현 | -| [boards/mng-implementation.md](features/boards/mng-implementation.md) | MNG 게시판 구현 상세 | -| [hr/attendance-management-spec.md](features/hr/attendance-management-spec.md) | 근태관리 기획서 (화면/데이터/비즈니스규칙/API) | -| [hr/hr-api-analysis.md](features/hr/hr-api-analysis.md) | HR API 분석 (근태/직원/부서) | -| [quotes/README.md](features/quotes/README.md) | 견적 시스템 분석 (BOM 계산, 10단계 로직) | -| [business-card-request.md](features/business-card-request.md) | 명함신청 관리 (3단계 워크플로우: 요청→제작의뢰→처리완료) | -| [academy/fire-shutter-image-prompts.md](features/academy/fire-shutter-image-prompts.md) | 방화셔터 백과사전 이미지 생성 프롬프트 (Gemini용) | -| [approvals/README.md](features/approvals/README.md) | 결재관리 시스템 개요 (아키텍처, DB, 상태관리, 권한) | -| [approvals/workflows.md](features/approvals/workflows.md) | 결재관리 워크플로우 상세 (승인/반려/회수/보류/전결/복사재기안) | -| [approvals/api-reference.md](features/approvals/api-reference.md) | 결재관리 API 명세 (20개 엔드포인트) | -| [approvals/ui-screens.md](features/approvals/ui-screens.md) | 결재관리 UI 화면 구성 (Blade + HTMX) | -| [approvals/db-changes-and-model-sync.md](features/approvals/db-changes-and-model-sync.md) | 결재관리 DB 변경사항 및 API 모델 동기화 현황 (2026-02~03) | - -### projects/ - 프로젝트별 문서 - -| 프로젝트 | 문서 | 설명 | -|---------|------|------| -| **MES** | [README.md](projects/mes/README.md) | MES 프로젝트 개요 | -| **MES** | [MES_PROJECT_ROADMAP.md](projects/mes/MES_PROJECT_ROADMAP.md) | 개발 로드맵 | -| **Legacy** | [draw-module.md](projects/legacy-5130/draw-module.md) | 레거시 드로우 모듈 | -| **조직도** | [README.md](projects/org-chart/README.md) | 조직도 관리 (Alpine.js + SortableJS) | - -### history/ - 히스토리 - -| 기간 | 문서 | -|------|------| -| **2025-11** | [item-master-gap-analysis.md](history/2025-11/item-master-gap-analysis.md), [item-master-spec.md](history/2025-11/item-master-spec.md), [front-requests/](history/2025-11/front-requests/), [item-master-archived/](history/2025-11/item-master-archived/) | -| **2025-09** | [checkpoint.md](history/2025-09/checkpoint.md), [database-schema.md](history/2025-09/database-schema.md) | -| **Roadmaps** | [december-2025.md](history/roadmaps/december-2025.md) | - ---- - -### 서브프로젝트 문서 - -각 서브프로젝트는 독립적인 `docs/` 디렉토리를 가집니다. - -| 프로젝트 | 문서 경로 | 설명 | -|---------|----------|------| -| **API** | [api/docs/](../api/docs/) | REST API 프로젝트 | -| **MNG** | [mng/docs/](../mng/docs/) | Plain Laravel 관리자 | -| **React** | [react/docs/](../react/docs/) | Next.js 프론트엔드 | - ---- - -## 📝 문서 작성 규칙 - -### 폴더 선택 기준 - -| 질문 | 폴더 | -|------|------| -| "시스템이 현재 어떤 상태인가?" | `system/` | -| "어떻게 코드를 작성할 것인가?" | `standards/` | -| "무엇이 유효한 데이터인가?" | `rules/` | -| "이 기능은 어떻게 동작하는가?" | `features/` | -| "어떻게 구현할 것인가?" | `guides/` | -| "무슨 작업을 할 것인가?" | `plans/` | -| "프로젝트 자료를 보관하고 싶다" | `projects/` | -| "무엇이 변경되었는가?" | `changes/` | - -### 파일명 규칙 - -| 유형 | 규칙 | 예시 | -|------|------|------| -| 기술 문서 (코드 참조) | 영문 kebab-case | `api-rules.md`, `database-schema.md` | -| 업무/비즈니스 문서 | 한글 허용 | `영업파트너가이드북.md`, `수당지급.md` | -| 변경 이력 | `YYYYMMDD_description.md` | `20260205_sus_inspection_template.md` | -| 폴더 인덱스 | `README.md` (대문자) | `features/finance/README.md` | -| **혼용 금지** | 한글+영문 섞지 않음 | ❌ `영업partner가이드.md` | - -### 크기 제한 -- **목표**: 10KB 이하 -- 초과 시 도메인별로 분할 - -### 문서 구조 템플릿 - -#### 정책/규칙 문서 (`rules/`, `standards/`) - -```markdown -# 제목 - -> **작성일**: YYYY-MM-DD -> **상태**: 설계 확정 - ---- - -## 1. 개요 -## 2. 핵심 원칙 -## 3. 상세 규칙 -## 4. API 엔드포인트 (해당 시) -## 관련 문서 - ---- - -**최종 업데이트**: YYYY-MM-DD -``` - -#### 변경 이력 문서 (`changes/`) - -```markdown -# 변경 내용 요약 - -**날짜:** YYYY-MM-DD - -## 변경 개요 -## 수정된 파일 -## 상세 변경 사항 -## 테스트 체크리스트 -``` - -### 작성 스타일 - -| 항목 | 규칙 | -|------|------| -| **언어** | 한글 기본, 코드/경로/기술 식별자만 영어 | -| **어조** | 서술형 ("X 한다") | -| **경고** | `> **경고: ...**` 블록인용 | -| **금지/필수** | `❌` 금지, `✅` 필수 | -| **우선순위** | `🔴 필수`, `🟡 중요`, `🟢 권장` | -| **코드 블록** | 반드시 언어 지정 (```php, ```bash 등) | -| **인라인 코드** | 파일 경로, 메서드명, 변수명에 백틱 | -| **구분선** | `---` 주요 섹션 사이 | - -### 새 문서 작성 시 체크리스트 -- [ ] 적절한 폴더에 배치 -- [ ] 파일명 규칙 준수 -- [ ] 문서 구조 템플릿 준수 -- [ ] 이 INDEX.md에 등록 - ---- - -## 🔄 문서 정비 진행 현황 - -> 참조: [docs-comprehensive-update-plan.md](plans/docs-comprehensive-update-plan.md) - -| Phase | 작업 | 상태 | -|-------|------|------| -| **Phase 0** | 문서 정책 재정립 | ✅ 완료 | -| **Phase 1** | 시스템 현황 문서화 (DB, API, React, MNG, Docker) | ✅ 완료 (14개 문서) | -| **Phase 2** | 기존 문서 정비 (architecture/+specs/ → system/ 이관) | ⏳ 대기 | -| **Phase 3** | 신규 도메인 기능 문서 작성 | ⏳ 대기 | -| **Phase 4** | 최종 검증 및 INDEX 갱신 | ⏳ 대기 | \ No newline at end of file diff --git a/sam/docs/assets/bi/sam_bi_black.png b/sam/docs/assets/bi/sam_bi_black.png deleted file mode 100755 index e83d284..0000000 Binary files a/sam/docs/assets/bi/sam_bi_black.png and /dev/null differ diff --git a/sam/docs/assets/bi/sam_bi_blue.png b/sam/docs/assets/bi/sam_bi_blue.png deleted file mode 100755 index a5cde92..0000000 Binary files a/sam/docs/assets/bi/sam_bi_blue.png and /dev/null differ diff --git a/sam/docs/assets/bi/sam_bi_green.png b/sam/docs/assets/bi/sam_bi_green.png deleted file mode 100755 index ff0afc0..0000000 Binary files a/sam/docs/assets/bi/sam_bi_green.png and /dev/null differ diff --git a/sam/docs/assets/bi/sam_bi_orange.png b/sam/docs/assets/bi/sam_bi_orange.png deleted file mode 100755 index 85aceb3..0000000 Binary files a/sam/docs/assets/bi/sam_bi_orange.png and /dev/null differ diff --git a/sam/docs/assets/bi/sam_bi_purple.png b/sam/docs/assets/bi/sam_bi_purple.png deleted file mode 100755 index 7b9dc0c..0000000 Binary files a/sam/docs/assets/bi/sam_bi_purple.png and /dev/null differ diff --git a/sam/docs/assets/bi/sam_bi_red.png b/sam/docs/assets/bi/sam_bi_red.png deleted file mode 100755 index 93d566f..0000000 Binary files a/sam/docs/assets/bi/sam_bi_red.png and /dev/null differ diff --git a/sam/docs/assets/bi/sam_bi_white.png b/sam/docs/assets/bi/sam_bi_white.png deleted file mode 100755 index 34a5a8c..0000000 Binary files a/sam/docs/assets/bi/sam_bi_white.png and /dev/null differ diff --git a/sam/docs/brochure/README.md b/sam/docs/brochure/README.md deleted file mode 100644 index 9fc78d2..0000000 --- a/sam/docs/brochure/README.md +++ /dev/null @@ -1,370 +0,0 @@ -# SAM 브로셔 버전 관리 - -> **작성일**: 2026-03-01 -> **상태**: 운영 중 - ---- - -## 1. 개요 - -SAM CEO Dashboard 및 ERP/MES 영업 브로셔의 버전별 디자인 변천을 기록한다. -모든 브로셔는 세로형(9:16) HTML로 작성하며, `pptx-skill`(html2pptx.js)로 PPTX 변환한다. - ---- - -## 2. 버전 요약 - -| 버전 | 대상 | 테마 | 배경색 | 주 액센트 | 비고 | -|------|------|------|--------|-----------|------| -| **v1** | 전체 고객 | 다크 | `#0F2439` | `#10B981` (에메랄드) | SAM ERP/MES 범용 | -| **v2** | 경영진 | 다크 | `#0B1929` | `#0EA5E9` (스카이블루) | CEO Dashboard 초판 | -| **v3** | 경영진 | 다크 | `#0B1929` | `#0EA5E9` (스카이블루) | v2 개선, Before/After 추가 | -| **v4** | 경영진 | 라이트 | `#F8FAFC` | `#0EA5E9` (스카이블루) | v3의 밝은 배경 변환 | -| **v5** | 경영진 | 프리미엄 그래디언트 | `#0F172A→#312E81` | `#FBBF24` (골드) | 글래스모피즘 + 골드 | -| **v6** | 경영진 | 코퍼레이트 블루 | `#FFFFFF` | `#2563EB` (블루) | 대기업/공공기관 스타일 | -| **v7** | 경영진 | 웜 그레이 + 틸 | `#FAFAF9` | `#0D9488` (틸) | IT/SaaS 스타일 | -| **v8** | 경영진 | 투톤 스플릿 | `#1E293B` / `#FFFFFF` | `#F97316` (오렌지) | 금융/컨설팅 스타일 | -| **v9** | 경영진 | 미니멀 화이트 | `#FFFFFF` | `#6366F1` (인디고) | Apple/디자인 에이전시 | - ---- - -## 3. 버전별 상세 - -### 3.1 v1 — SAM ERP/MES 범용 브로셔 - -**컨셉**: 중소 제조업 대상 SAM 플랫폼 전체 기능 소개 - -| 항목 | 값 | -|------|------| -| 배경 | `#0F2439` (네이비) | -| 주 액센트 | `#10B981` (에메랄드 그린) | -| 보조 액센트 | `#2E86AB`, `#8B5CF6`, `#E86F2C` | -| 카드 스타일 | 반투명 배경 + 컬러 보더 | -| BI 로고 | `sam_bi_white.png` | - -**앞면 구성**: -- 히어로: "중소 제조업을 위한 ERP/MES 통합 플랫폼" -- 고민 포인트: Excel 과의존, 실시간 가시성, 품질관리, 높은 ERP 비용 -- 효과 지표: 시간 절감 80%, 납기 준수 95%, 추적성 100%, 인사/회계 무료 -- 기술 태그: 클라우드, 모바일 대응, 멀티테넌트 - -**뒷면 구성**: -- 8대 핵심 모듈 (01~08 번호 뱃지): 품목/BOM, 견적/수주, 생산/MES, 출하, 품질, 자재, 인사/회계, 대시보드 -- 확장 기능: 전자서명, 알림톡, AI Lab, QR -- 가격표: 기본 2,000만원 + 월 50만원 -- 도입 프로세스: 인터뷰 → 개발 → 이관 → 교육 - ---- - -### 3.2 v2 — CEO Dashboard 초판 - -**컨셉**: 경영진 타겟, 대시보드 중심 소개. 문제→해결 스토리텔링 - -| 항목 | 값 | -|------|------| -| 배경 | `#0B1929` (짙은 네이비) | -| 주 액센트 | `#0EA5E9` (스카이블루) | -| 보조 액센트 | `#10B981`, `#8B5CF6`, `#F59E0B`, `#EF4444`, `#EC4899` | -| 카드 스타일 | 반투명 다크 카드 | -| BI 로고 | `sam_bi_white.png` | - -**앞면 구성**: -- 히어로: "대표님, 지금 우리 회사 어떻게 돌아가고 있나요?" -- 시간대별 고민: 오전 9시(매출 보고 대기), 오후 2시(수주 취합), 오후 5시(결재 서류) -- 대시보드 Mock UI: KPI 카드 4개 + 매출 추이 차트 + 조직 성과 바 차트 -- 약속 박스: "실시간 KPI 파악" - -**뒷면 구성**: -- 대시보드 7대 기능 (01~07 뱃지) -- 역할별 맞춤 화면: CEO, 관리자, 운영자, 영업자 -- SAM 플랫폼 연동: 견적/수주, 생산, 품질, 재고, 인사/회계 -- 가격표 + 도입 프로세스 - -**v1 대비 차이**: -- 타겟이 전체→경영진으로 좁혀짐 -- 타임라인 기반 문제 제시 (시간대별 고민) -- 대시보드 UI Mock 삽입 -- 역할별 화면 분리 소개 - ---- - -### 3.3 v3 — CEO Dashboard 개선판 (다크) - -**컨셉**: v2 기반 개선. Before/After 인포그래픽 추가, SVG 아이콘 강화 - -| 항목 | 값 | -|------|------| -| 배경 | `#0B1929` (짙은 네이비) | -| 주 액센트 | `#0EA5E9` (스카이블루) | -| 카드 스타일 | 반투명 다크 + 컬러 보더 | -| BI 로고 | `sam_bi_white.png` | - -**v2 대비 개선사항**: -- 1page 통합본 추가 -- Before/After 비교 인포그래픽 도입 -- 핵심 가치 3카드: 즉시 현황 파악, 데이터로 판단, 모바일 승인 -- SVG 인라인 아이콘 전면 적용 (외부 이미지 의존 제거) -- PPTX 텍스트 줄바꿈 방지 패턴 적용 (`white-space: nowrap`, 개별 `

` 분리) - ---- - -### 3.4 v4 — CEO Dashboard 라이트 버전 - -**컨셉**: v3와 동일 콘텐츠, 밝은 배경으로 색상 전환 - -| 항목 | 값 | -|------|------| -| 배경 | `#F8FAFC` (밝은 슬레이트) | -| 주 액센트 | `#0EA5E9` (스카이블루) | -| 제목 텍스트 | `#0F172A` | -| 본문 텍스트 | `#475569` | -| 보조 텍스트 | `#94A3B8` | -| 카드 스타일 | 화이트 + `box-shadow` + `#E2E8F0` 보더 | -| BI 로고 | `sam_bi_black.png` | - -**v3 → v4 색상 변환 규칙**: - -| 요소 | v3 (다크) | v4 (라이트) | -|------|-----------|------------| -| 배경 | `#0B1929` | `#F8FAFC` | -| 카드 | `#111D2E` 반투명 | `#FFFFFF` + shadow | -| 제목 | `#FFFFFF` | `#0F172A` | -| 본문 | `rgba(255,255,255,0.55)` | `#475569` | -| 보조 | `rgba(255,255,255,0.3)` | `#94A3B8` | -| 구분선 | `rgba(14,165,233,0.15)` | `#E2E8F0` | -| 기술 태그 | `rgba(255,255,255,0.03)` | `#F1F5F9` | -| 액센트 | 동일 유지 | 동일 유지 | - ---- - -### 3.5 v5 — Premium Executive Gradient - -**컨셉**: 고급 프리미엄 감성. 네이비→인디고 그래디언트 + 골드 액센트 + 글래스모피즘 - -| 항목 | 값 | -|------|------| -| 배경 | `#0F172A → #1E1B4B → #312E81` (175deg 그래디언트) | -| 주 액센트 | `#FBBF24` (골드/앰버) | -| 보조 액센트 | `#10B981`, `#8B5CF6`, `#EF4444`, `#F59E0B`, `#EC4899` | -| 카드 스타일 | 글래스모피즘 (`rgba(255,255,255,0.05)` + `rgba(255,255,255,0.1)` border) | -| BI 로고 | `sam_bi_white.png` | -| 뱃지 | "EXECUTIVE EDITION" 골드 뱃지 | - -**앞면 구성**: -- 히어로: "대표님의 시간은 보고를 기다리는 데 쓰여선 안 됩니다." -- 잃어버린 시간 카드: 1~2일(매출), 반나절(수주), 30분(결재) — 빨간 톤 -- 골드 전환 구분선: "SAM 도입 후" -- 대시보드 Mock: 골드 차트 라인, 글래스모피즘 카드 -- 약속 박스: 골드 테두리 - -**뒷면 구성**: -- 7대 기능 리스트 (글래스모피즘 카드) -- 역할별 맞춤 화면: CEO(골드), 관리자(그린), 운영자(앰버), 영업자(퍼플) -- 가격표: 골드 강조 -- 도입 프로세스: 골드 화살표 연결 - -**기술 특이사항**: -- body CSS gradient → PPTX 미지원 → Sharp로 PNG 사전 렌더링 -- HTML body는 `#1A1640`(단색 fallback), convert 스크립트에서 `slide.background`로 그래디언트 PNG 덮어쓰기 -- 구분선 gradient도 solid rgba로 변환 (PPTX 호환) - ---- - -### 3.6 v6 — Corporate Blue & White - -**컨셉**: 대기업/공공기관 프레젠테이션 스타일. 정돈된 블루 헤더 바 + 순백색 본문 - -| 항목 | 값 | -|------|------| -| 배경 | `#FFFFFF` (순백) | -| 헤더 바 | `#1E40AF` (로열 블루) | -| 주 액센트 | `#2563EB` (블루) | -| 보조 배경 | `#EFF6FF` (블루-50), `#DBEAFE` (블루-100) | -| 카드 스타일 | 화이트 + `#DBEAFE` 보더 | -| BI 로고 | `sam_bi_white.png` (헤더), `sam_bi_black.png` (본문) | - -**특징**: -- 풀 폭 블루 헤더 바에 흰색 BI 로고 + 뱃지 배치 -- 섹션 라벨은 블루-50 배경 + 로열블루 텍스트 뱃지 -- 대시보드 Mock UI: `#DBEAFE` 보더 카드 -- CTA: 블루 배경 풀 폭 바 - ---- - -### 3.7 v7 — Warm Gray + Teal - -**컨셉**: IT/SaaS 기업 스타일. 따뜻한 그레이 배경 + 틸(Teal) 액센트 - -| 항목 | 값 | -|------|------| -| 배경 | `#FAFAF9` (웜 그레이) | -| 주 액센트 | `#0D9488` (틸) | -| 보조 액센트 | `#10B981`, `#8B5CF6`, `#EF4444`, `#F59E0B`, `#EC4899` | -| 카드 스타일 | 화이트 + `#E7E5E4` 보더 + 미세 그림자 | -| 구분선 | `#D6D3D1` | -| BI 로고 | `sam_bi_black.png` | - -**특징**: -- 부드러운 웜 톤 배경으로 눈의 피로 감소 -- 틸 계열 SVG 아이콘 전면 적용 -- 가벼운 카드 스타일로 정보 구분 -- 타임라인 인포그래픽: 시간대별 고민 (9AM/2PM/5PM) - ---- - -### 3.8 v8 — Two-Tone Navy/White Split - -**컨셉**: 금융/컨설팅 프레젠테이션 스타일. 다크 상단 + 화이트 하단 투톤 분할 - -| 항목 | 값 | -|------|------| -| 상단 배경 | `#1E293B` (슬레이트-800) | -| 하단 배경 | `#FFFFFF` (순백) | -| 주 액센트 | `#F97316` (오렌지) | -| 보조 액센트 | `#FB923C` (오렌지-400) | -| 카드 (다크) | `rgba(255,255,255,0.08)` + `rgba(255,255,255,0.12)` 보더 | -| 카드 (라이트) | 화이트 + `#E2E8F0` 보더 + 컬러 좌측 보더 | -| BI 로고 | `sam_bi_white.png` (다크), `sam_bi_black.png` (라이트) | - -**특징**: -- 앞면 상단: 다크 존에 KPI 카드 + 히어로 메시지 -- 앞면 하단: 화이트 존에 가치 카드 + 기능 그리드 -- 기능 카드에 컬러 좌측 보더 포인트 (오렌지/그린/퍼플/레드) -- 다크 CTA 박스: 하단 풀 폭 다크 배경 + 오렌지 액센트 - ---- - -### 3.9 v9 — Minimal White + Indigo - -**컨셉**: Apple/디자인 에이전시 스타일. 극도의 미니멀리즘 + 인디고 수직 액센트 라인 - -| 항목 | 값 | -|------|------| -| 배경 | `#FFFFFF` (순백) | -| 주 액센트 | `#6366F1` (인디고) | -| 카드 배경 | `#F8FAFC` (거의 투명한 그레이) | -| 카드 보더 | `#F1F5F9` | -| 본문 텍스트 | `#334155` (슬레이트-700) | -| 보조 텍스트 | `#94A3B8` | -| BI 로고 | `sam_bi_black.png` | - -**특징**: -- 좌측 3pt 인디고 수직 액센트 라인 (풀 하이트) -- 타이포그래피 중심 레이아웃 (아이콘 최소화) -- 거의 보이지 않는 카드 구분 (barely-there cards) -- 기능은 텍스트 로우 형태 (인디고 불릿 도트만) -- 가격/프로세스도 텍스트 기반 미니멀 표현 - ---- - -## 4. 폴더 구조 - -``` -docs/brochure/ -├── README.md ← 이 파일 -├── v1/ -│ ├── slides/ -│ │ ├── brochure-2page-front.html -│ │ ├── brochure-2page-back.html -│ │ └── brochure-1page.html -│ ├── convert-1page.cjs -│ ├── convert-2page.cjs -│ ├── sam-brochure-1page.pptx -│ └── sam-brochure-2page.pptx -├── v2/ -│ ├── slides/ -│ │ ├── brochure-dashboard-front.html -│ │ ├── brochure-dashboard-back.html -│ │ └── brochure-dashboard-1page.html -│ ├── convert-1page.cjs -│ ├── convert-2page.cjs -│ ├── sam-brochure-v2-dashboard-1page.pptx -│ └── sam-brochure-v2-dashboard-2page.pptx -├── v3/ -│ ├── slides/ -│ │ ├── brochure-dashboard-front.html -│ │ ├── brochure-dashboard-back.html -│ │ └── brochure-dashboard-1page.html -│ ├── convert-1page.cjs -│ ├── convert-2page.cjs -│ ├── sam-brochure-v3-dashboard-1page.pptx -│ └── sam-brochure-v3-dashboard-2page.pptx -├── v4/ -│ ├── slides/ -│ │ ├── brochure-dashboard-front.html -│ │ ├── brochure-dashboard-back.html -│ │ └── brochure-dashboard-1page.html -│ ├── convert-1page.cjs -│ ├── convert-2page.cjs -│ ├── sam-brochure-v4-dashboard-1page.pptx -│ └── sam-brochure-v4-dashboard-2page.pptx -├── v5/ -│ ├── slides/ -│ │ ├── brochure-dashboard-front.html -│ │ ├── brochure-dashboard-back.html -│ │ └── brochure-dashboard-1page.html -│ ├── convert-1page.cjs ← Sharp 그래디언트 배경 생성 포함 -│ ├── convert-2page.cjs ← Sharp 그래디언트 배경 생성 포함 -│ ├── sam-brochure-v5-dashboard-1page.pptx -│ └── sam-brochure-v5-dashboard-2page.pptx -├── v6/ ← Corporate Blue & White -│ ├── slides/ (front, back, 1page) -│ ├── convert-1page.cjs -│ ├── convert-2page.cjs -│ ├── sam-brochure-v6-dashboard-1page.pptx -│ └── sam-brochure-v6-dashboard-2page.pptx -├── v7/ ← Warm Gray + Teal -│ ├── slides/ (front, back, 1page) -│ ├── convert-1page.cjs -│ ├── convert-2page.cjs -│ ├── sam-brochure-v7-dashboard-1page.pptx -│ └── sam-brochure-v7-dashboard-2page.pptx -├── v8/ ← Two-Tone Navy/White Split -│ ├── slides/ (front, back, 1page) -│ ├── convert-1page.cjs -│ ├── convert-2page.cjs -│ ├── sam-brochure-v8-dashboard-1page.pptx -│ └── sam-brochure-v8-dashboard-2page.pptx -└── v9/ ← Minimal White + Indigo - ├── slides/ (front, back, 1page) - ├── convert-1page.cjs - ├── convert-2page.cjs - ├── sam-brochure-v9-dashboard-1page.pptx - └── sam-brochure-v9-dashboard-2page.pptx -``` - ---- - -## 5. PPTX 변환 방법 - -```bash -# 각 버전 폴더에서 실행 -cd docs/brochure/v5 -node convert-1page.cjs # 1페이지 통합본 -node convert-2page.cjs # 앞면+뒷면 2페이지 -``` - ---- - -## 6. PPTX 변환 시 주의사항 - -### 6.1 텍스트 줄바꿈 방지 - -- 단일행 `

` 태그에 `white-space: nowrap` 필수 -- `
` 멀티라인 `

`는 개별 `

` 태그로 분리 -- `` 포함 텍스트도 개별 `

` 처리 (PPTX 폰트 폭 차이 보정) - -### 6.2 CSS gradient 미지원 - -- html2pptx.js는 CSS `linear-gradient`를 지원하지 않음 -- body gradient → Sharp로 PNG 사전 렌더링 후 `slide.background`에 설정 -- 구분선 gradient → solid `rgba()` 색상으로 변환 - -### 6.3 SVG 처리 - -- 인라인 SVG는 html2pptx가 자동으로 PNG 래스터화 -- SVG 내부 fill 색상은 배경에 맞게 조정 필요 - ---- - -**최종 업데이트**: 2026-03-01 (v6~v9 추가) diff --git a/sam/docs/brochure/v1/convert-1page.cjs b/sam/docs/brochure/v1/convert-1page.cjs deleted file mode 100644 index 5252ffa..0000000 --- a/sam/docs/brochure/v1/convert-1page.cjs +++ /dev/null @@ -1,28 +0,0 @@ -const path = require('path'); -module.paths.unshift(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/node_modules')); - -const PptxGenJS = require('pptxgenjs'); -const html2pptx = require(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/html2pptx.js')); - -async function main() { - const pres = new PptxGenJS(); - - // 9:16 세로형 (Portrait) - pres.defineLayout({ name: 'PORTRAIT_9x16', width: 5.625, height: 10 }); - pres.layout = 'PORTRAIT_9x16'; - - const htmlFile = path.join(__dirname, 'slides', 'brochure-1page.html'); - console.log('Converting 1-page brochure...'); - - try { - await html2pptx(htmlFile, pres); - } catch (err) { - console.error(`Error: ${err.message}`); - } - - const outputPath = path.join(__dirname, 'sam-brochure-1page.pptx'); - await pres.writeFile({ fileName: outputPath }); - console.log(`\nPPTX created: ${outputPath}`); -} - -main().catch(console.error); diff --git a/sam/docs/brochure/v1/convert-2page.cjs b/sam/docs/brochure/v1/convert-2page.cjs deleted file mode 100644 index d3590f5..0000000 --- a/sam/docs/brochure/v1/convert-2page.cjs +++ /dev/null @@ -1,32 +0,0 @@ -const path = require('path'); -module.paths.unshift(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/node_modules')); - -const PptxGenJS = require('pptxgenjs'); -const html2pptx = require(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/html2pptx.js')); - -async function main() { - const pres = new PptxGenJS(); - - // 9:16 세로형 (Portrait) - pres.defineLayout({ name: 'PORTRAIT_9x16', width: 5.625, height: 10 }); - pres.layout = 'PORTRAIT_9x16'; - - const slidesDir = path.join(__dirname, 'slides'); - const slides = ['brochure-2page-front.html', 'brochure-2page-back.html']; - - for (const file of slides) { - const htmlFile = path.join(slidesDir, file); - console.log(`Converting ${file} ...`); - try { - await html2pptx(htmlFile, pres); - } catch (err) { - console.error(`Error on ${file}: ${err.message}`); - } - } - - const outputPath = path.join(__dirname, 'sam-brochure-2page.pptx'); - await pres.writeFile({ fileName: outputPath }); - console.log(`\nPPTX created: ${outputPath}`); -} - -main().catch(console.error); diff --git a/sam/docs/brochure/v1/sam-brochure-1page.pptx b/sam/docs/brochure/v1/sam-brochure-1page.pptx deleted file mode 100644 index 5fe19a4..0000000 Binary files a/sam/docs/brochure/v1/sam-brochure-1page.pptx and /dev/null differ diff --git a/sam/docs/brochure/v1/sam-brochure-2page.pptx b/sam/docs/brochure/v1/sam-brochure-2page.pptx deleted file mode 100644 index 016084a..0000000 Binary files a/sam/docs/brochure/v1/sam-brochure-2page.pptx and /dev/null differ diff --git a/sam/docs/brochure/v1/slides/brochure-1page.html b/sam/docs/brochure/v1/slides/brochure-1page.html deleted file mode 100644 index 8eea8ab..0000000 --- a/sam/docs/brochure/v1/slides/brochure-1page.html +++ /dev/null @@ -1,210 +0,0 @@ - - - - - - - - -

- -
-

PRODUCT BROCHURE 2026

-
- - -
-

SMART AUTOMATION MANAGEMENT

-

중소 제조업을 위한
ERP/MES 통합 플랫폼

-

품목관리, 견적, 수주, 생산, 출하, 품질, 인사/회계까지
제조업의 모든 업무를 하나의 시스템으로 통합합니다.

-
- - -
- - -
-

현재 업무 과제

-
-
-

Excel 수작업

-

오류 잦음, 시간 낭비

-
-
-

현황 파악 불가

-

생산/재고 실시간 X

-
-
-

ERP 도입비 부담

-

수천만~수억원

-
-
-
- - -
-

SAM 핵심 기능

-
- -
-
-
-
-

01

-
-

견적/수주 자동화

-
-

BOM 전개, 단가 적용, PDF 견적서 자동 생성

-
-
-
-
-

02

-
-

생산관리 (MES)

-
-

바코드/QR 공정추적, 실시간 현황 대시보드

-
-
- -
-
-
-
-

03

-
-

품질/검사 관리

-
-

수입/공정/출하 3단계 검사, 인증 자동 알림

-
-
-
-
-

04

-
-

자재/재고 추적

-
-

안전재고, LOT 추적, 바코드 입출고 관리

-
-
- -
-
-
-
-

05

-
-

인사/회계 (무료)

-
-

근태, 급여, 매입매출, 세금계산서 자동 발행

-
-
-
-
-

06

-
-

경영 대시보드

-
-

수주/생산/매출/품질 KPI 실시간 모니터링

-
-
-
-
- - -
-
-

전자서명

-
-
-

카카오 알림톡

-
-
-

AI 실험실

-
-
-

바로빌 연동

-
-
- - -
- - -
- -
-

도입 기대 효과

-
-
-
-

80%

-

업무 시간 단축

-
-
-

95%

-

납기 준수율

-
-
-
-
-

100%

-

이력 추적성

-
-
-

Free

-

인사/회계 포함

-
-
-
-
- -
-

투자 비용

-
-

제조업 기본 패키지

-

2,000만원

-

+ 월 50만원 (유지보수)

-
-

품목-견적-수주-생산-출하
인사/회계 무료 포함

-
-
-
- - -
-
-

클라우드 기반 (설치 불필요)

-
-
-

모바일 대응

-
-
-

Multi-tenant

-
-
- - -
-
-
-

(주)코드브릿지엑스

-

www.codebridge-x.com

-
-
-

무료 데모 및 상담

-

contact@codebridge-x.com

-
-
-
- - \ No newline at end of file diff --git a/sam/docs/brochure/v1/slides/brochure-2page-back.html b/sam/docs/brochure/v1/slides/brochure-2page-back.html deleted file mode 100644 index a285d16..0000000 --- a/sam/docs/brochure/v1/slides/brochure-2page-back.html +++ /dev/null @@ -1,227 +0,0 @@ - - - - - - - - -
- -
-

FEATURES & PRICING

-
- - -
-

SAM 핵심 모듈

-
- -
-
-

01

-
-

품목/BOM 관리

-

품목 마스터, 다단계 BOM 전개, 단가 관리

-
- -
-
-

02

-
-

견적/수주 자동화

-

견적서 자동 생성, 수주 전환, PDF 출력

-
- -
-
-

03

-
-

생산관리 (MES)

-

작업지시, 바코드/QR 공정추적, 실시간 현황

-
- -
-
-

04

-
-

출하/물류 관리

-

출하 지시, 거래명세서, 배송 추적

-
- -
-
-

05

-
-

품질/검사 관리

-

수입/공정/출하 검사, 인증 만료 자동 알림

-
- -
-
-

06

-
-

자재/재고 관리

-

안전재고, 입출고, LOT 추적, 바코드 관리

-
- -
-
-

07

-
-

인사/회계 (무료)

-

근태, 급여, 매입매출, 세금계산서 자동 발행

-
- -
-
-

08

-
-

경영 대시보드

-

수주/생산/매출/품질 KPI 실시간 모니터링

-
-
-
- - -
- - -
-

확장 기능

-
-
-

전자서명

-

계약/확인서

-
-
-

알림톡

-

카카오 자동발송

-
-
-

AI 실험실

-

음성요약/문서분류

-
-
-

QR 코드

-

설비/장비 점검

-
-
-
- - -
- - -
-

투자 비용

-
- -
-
-

제조업 기본 패키지

-

2,000만원

-

+ 월 50만원 (유지보수)

-
-
-

품목 - 견적 - 수주 - 생산 - 출하
인사/회계 무료 포함

-
-
- -
-
-

추가 옵션 (선택)

-
-
-

생산공정 추가

-

+500만원

-
-
-

품질관리(인정검사)

-

+2,000만원

-
-
-

사진등록/챗봇/녹음

-

월 10~20만원

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

도입 프로세스

-
-
-

Step 1

-

1~2주

-

현장 인터뷰

-
-
-

Step 2

-

2~4주

-

맞춤 개발

-
-
-

Step 3

-

1~2주

-

데이터 이관

-
-
-

Step 4

-

1~2주

-

교육/안정화

-
-
-
- - -
-
-

바로빌 API

-

세금계산서 자동

-
-
-

카카오 알림톡

-

점검/납기 알림

-
-
-

이카운트 연동

-

기존 ERP 동기화

-
-
- - -
-
-
-

무료 데모를 신청하세요

-

귀사에 최적화된 맞춤 데모를 제공합니다

-
-
-

contact@codebridge-x.com

-

www.codebridge-x.com

-
-
-
- - -
-

(주)코드브릿지엑스 | SAM - Smart Automation Management

-
- - \ No newline at end of file diff --git a/sam/docs/brochure/v1/slides/brochure-2page-front.html b/sam/docs/brochure/v1/slides/brochure-2page-front.html deleted file mode 100644 index fe6da03..0000000 --- a/sam/docs/brochure/v1/slides/brochure-2page-front.html +++ /dev/null @@ -1,122 +0,0 @@ - - - - - - - - -
- -
-

PRODUCT BROCHURE 2026

-
- - -
-

SMART AUTOMATION MANAGEMENT

-

중소 제조업을 위한
ERP/MES 통합 플랫폼

-

품목관리, 견적, 수주, 생산, 출하, 품질, 인사/회계까지
제조업의 모든 업무를 하나의 시스템으로 통합합니다.

-
- - -
- - -
-

이런 고민이 있으신가요?

-
-
-
-

Excel 견적서, 수기 전표로 업무 시간 낭비가 심하다

-
-
-
-

생산 현황을 실시간으로 파악할 수 없다

-
-
-
-

품질/검사 기록이 체계적으로 관리되지 않는다

-
-
-
-

ERP 도입비가 수천만원~수억원으로 부담된다

-
-
-
- - -
-

SAM이 해결합니다

-

- SAM은 중소 제조업에 특화된 클라우드 ERP/MES 통합 플랫폼입니다. - 품목/BOM 관리, 견적 자동화, 바코드 생산추적, 품질검사, 인사/회계까지 - 별도 설치 없이 웹 브라우저만으로 모든 업무를 통합 관리합니다. -

-
- - -
- - -
-

도입 기대 효과

-
-
-

80%

-

업무 시간 단축

-
-
-

95%

-

납기 준수율

-
-
-

100%

-

이력 추적성

-
-
-

Free

-

인사/회계 포함

-
-
-
- - -
-
-

클라우드 기반

-

설치 불필요

-
-
-

모바일 대응

-

현장 태블릿/폰

-
-
-

Multi-tenant

-

데이터 완전 격리

-
-
- - -
-
-
-

(주)코드브릿지엑스

-

www.codebridge-x.com

-
-
-

뒷면에서 상세 기능과 가격을 확인하세요

-
-
-
- - \ No newline at end of file diff --git a/sam/docs/brochure/v2/convert-1page.cjs b/sam/docs/brochure/v2/convert-1page.cjs deleted file mode 100644 index d11c9ee..0000000 --- a/sam/docs/brochure/v2/convert-1page.cjs +++ /dev/null @@ -1,28 +0,0 @@ -const path = require('path'); -module.paths.unshift(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/node_modules')); - -const PptxGenJS = require('pptxgenjs'); -const html2pptx = require(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/html2pptx.js')); - -async function main() { - const pres = new PptxGenJS(); - - // 9:16 세로형 (Portrait) - pres.defineLayout({ name: 'PORTRAIT_9x16', width: 5.625, height: 10 }); - pres.layout = 'PORTRAIT_9x16'; - - const htmlFile = path.join(__dirname, 'slides', 'brochure-dashboard-1page.html'); - console.log('Converting CEO Dashboard 1-page brochure...'); - - try { - await html2pptx(htmlFile, pres); - } catch (err) { - console.error(`Error: ${err.message}`); - } - - const outputPath = path.join(__dirname, 'sam-brochure-v2-dashboard-1page.pptx'); - await pres.writeFile({ fileName: outputPath }); - console.log(`\nPPTX created: ${outputPath}`); -} - -main().catch(console.error); diff --git a/sam/docs/brochure/v2/convert-2page.cjs b/sam/docs/brochure/v2/convert-2page.cjs deleted file mode 100644 index 7d4aed0..0000000 --- a/sam/docs/brochure/v2/convert-2page.cjs +++ /dev/null @@ -1,32 +0,0 @@ -const path = require('path'); -module.paths.unshift(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/node_modules')); - -const PptxGenJS = require('pptxgenjs'); -const html2pptx = require(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/html2pptx.js')); - -async function main() { - const pres = new PptxGenJS(); - - // 9:16 세로형 (Portrait) - pres.defineLayout({ name: 'PORTRAIT_9x16', width: 5.625, height: 10 }); - pres.layout = 'PORTRAIT_9x16'; - - const slidesDir = path.join(__dirname, 'slides'); - const slides = ['brochure-dashboard-front.html', 'brochure-dashboard-back.html']; - - for (const file of slides) { - const htmlFile = path.join(slidesDir, file); - console.log(`Converting ${file} ...`); - try { - await html2pptx(htmlFile, pres); - } catch (err) { - console.error(`Error on ${file}: ${err.message}`); - } - } - - const outputPath = path.join(__dirname, 'sam-brochure-v2-dashboard-2page.pptx'); - await pres.writeFile({ fileName: outputPath }); - console.log(`\nPPTX created: ${outputPath}`); -} - -main().catch(console.error); diff --git a/sam/docs/brochure/v2/sam-brochure-v2-dashboard-1page.pptx b/sam/docs/brochure/v2/sam-brochure-v2-dashboard-1page.pptx deleted file mode 100644 index d5fb878..0000000 Binary files a/sam/docs/brochure/v2/sam-brochure-v2-dashboard-1page.pptx and /dev/null differ diff --git a/sam/docs/brochure/v2/sam-brochure-v2-dashboard-2page.pptx b/sam/docs/brochure/v2/sam-brochure-v2-dashboard-2page.pptx deleted file mode 100644 index 315707d..0000000 Binary files a/sam/docs/brochure/v2/sam-brochure-v2-dashboard-2page.pptx and /dev/null differ diff --git a/sam/docs/brochure/v2/slides/brochure-dashboard-1page.html b/sam/docs/brochure/v2/slides/brochure-dashboard-1page.html deleted file mode 100644 index eca646a..0000000 --- a/sam/docs/brochure/v2/slides/brochure-dashboard-1page.html +++ /dev/null @@ -1,261 +0,0 @@ - - - - - - - - -
- -
-

CEO DASHBOARD EDITION 2026

-
- - -
-

EXECUTIVE DASHBOARD

-

대표님, 지금 우리 회사
어떻게 돌아가고 있나요?

-

보고를 기다리지 마세요. SAM 대시보드 하나면
매출, 수주, 조직 실적, 승인 대기까지 한눈에 파악합니다.

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

SAM CEO Dashboard

-
- -
-
-

월 매출

-

5.2억

-

+15.3%

-
-
-

수주 잔량

-

127건

-

+8건

-
-
-

납기 준수율

-

96%

-

목표 초과

-
-
-

승인 대기

-

5건

-

즉시 처리

-
-
- -
- -
-

월별 매출 추이

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

조직별 실적

-
-
-
-

영업1팀

-
-
-
-
-
-
-

영업2팀

-
-
-
-
-
-
-

생산팀

-
-
-
-
-
-
-

품질팀

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

대표님이 얻는 것

-
-
-
-
-

1

-
-

즉시 현황 파악

-
-

보고를 기다릴 필요 없이
로그인만으로 전사 현황 확인

-
-
-
-
-

2

-
-

데이터 기반 의사결정

-
-

감이 아닌 숫자로 판단
매출 추이, KPI, 팀 성과 비교

-
-
-
-
-

3

-
-

빠른 승인/결재

-
-

대기 건수를 실시간 알림
모바일에서도 즉시 승인 처리

-
-
-
- - -
- - -
-

대시보드 핵심 기능

-
-
-
-
-

실시간 매출/수주 KPI

-
-
-
-

조직 계층별 실적 트리

-
-
-
-
-
-

역할별 수당 현황

-
-
-
-

미승인 건수 실시간 알림

-
-
-
-
-
-

기간별 트렌드 분석

-
-
-
-

수익 시뮬레이터

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

BEFORE

-
-
-

"매출 얼마야?" → 보고 대기 1~2일

-

"수주 현황?" → Excel 취합 반나절

-

"승인할 것 있어?" → 서류 뒤지기

-

"팀별 실적?" → 각 팀장 개별 보고

-
-
-
- -
-

AFTER (SAM)

-
-
-

로그인 → 3초만에 전사 현황

-

클릭 한 번 → 실시간 수주 데이터

-

빨간 뱃지 → 즉시 승인 처리

-

트리 구조 → 전 조직 실적 한눈에

-
-
-
-
- - -
-
-

PC + 모바일

-
-
-

실시간 업데이트

-
-
-

역할별 권한

-
-
-

클라우드 기반

-
-
-

데이터 암호화

-
-
- - -
-
-
-

(주)코드브릿지엑스

-

www.codebridge-x.com

-
-
-

무료 데모 신청

-

contact@codebridge-x.com

-
-
-
- - \ No newline at end of file diff --git a/sam/docs/brochure/v2/slides/brochure-dashboard-back.html b/sam/docs/brochure/v2/slides/brochure-dashboard-back.html deleted file mode 100644 index 147b8bf..0000000 --- a/sam/docs/brochure/v2/slides/brochure-dashboard-back.html +++ /dev/null @@ -1,242 +0,0 @@ - - - - - - - - -
- -
-

DASHBOARD FEATURES & PRICING

-
- - -
-

대시보드 핵심 기능

-
- -
-
-

01

-
-

실시간 KPI 카드

-

월 매출, 수주 잔량, 납기 준수율, 승인 대기 한눈에

-
- -
-
-

02

-
-

조직 실적 트리

-

계층 구조로 각 팀/개인 실적 펼쳐보기

-
- -
-
-

03

-
-

역할별 수당 현황

-

판매자/관리자/협업자 수당 배분 실시간 확인

-
- -
-
-

04

-
-

승인 대기 알림

-

가입/지급 승인 미처리 건수 빨간 뱃지로 강조

-
- -
-
-

05

-
-

기간별 트렌드

-

당월/분기/연간 매출 추이 차트, 성장률 비교

-
- -
-
-

06

-
-

수익 시뮬레이터

-

가상 시나리오로 수당/마진 사전 계산

-
- -
-
-

07

-
-

모바일 대응

-

이동중에도 스마트폰으로 KPI 확인 및 승인

-
-
-
- - -
- - -
-

역할별 맞춤 화면

-
-
-

CEO

-

전사 KPI

-

매출/수주/조직 총괄

-
-
-

관리자

-

팀 실적 관리

-

하위 조직 성과 추적

-
-
-

운영자

-

인력/승인 관리

-

가입/지급 승인 처리

-
-
-

영업자

-

내 실적 조회

-

계약/수당 현황 확인

-
-
-
- - -
- - -
-

대시보드 + SAM 통합 플랫폼

-
-
-

견적/수주

-
-
-

생산 (MES)

-
-
-

품질/검사

-
-
-

재고/자재

-
-
-

인사/회계

-
-
-

대시보드에 표시되는 모든 데이터는 SAM ERP/MES 실시간 데이터 기반

-
- - -
- - -
-

투자 비용

-
- -
-
-

대시보드 포함 기본 패키지

-

2,000만원

-

+ 월 50만원 (유지보수)

-
-
-

CEO 대시보드 + 견적/수주 + 생산
인사/회계 무료 포함

-
-
- -
-
-

추가 옵션 (선택)

-
-
-

생산공정 관리

-

+500만원

-
-
-

품질관리(인정검사)

-

+2,000만원

-
-
-

AI 견적 자동 생성

-

월 10~20만원

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

도입 프로세스

-
-
-

1

-

1~2주

-

현장 인터뷰

-
-
-

-
-
-

2

-

2~4주

-

맞춤 개발

-
-
-

-
-
-

3

-

1~2주

-

데이터 이관

-
-
-

-
-
-

4

-

1~2주

-

교육/안정화

-
-
-
- - -
-
-
-

무료 데모를 신청하세요

-

대표님 전용 대시보드를 직접 체험해 보세요

-
-
-

contact@codebridge-x.com

-

www.codebridge-x.com

-
-
-
- - -
-

(주)코드브릿지엑스 | SAM - Smart Automation Management

-
- - \ No newline at end of file diff --git a/sam/docs/brochure/v2/slides/brochure-dashboard-front.html b/sam/docs/brochure/v2/slides/brochure-dashboard-front.html deleted file mode 100644 index 0df1434..0000000 --- a/sam/docs/brochure/v2/slides/brochure-dashboard-front.html +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - - - -
- -
-

CEO DASHBOARD EDITION

-
- - -
-

EXECUTIVE DASHBOARD

-

대표님, 지금 우리 회사
어떻게 돌아가고 있나요?

-

매출이 얼마인지, 수주가 밀려있는지, 승인할 건이 있는지
더 이상 보고를 기다리지 마세요.

-
- - -
- - -
-

대표님의 하루

-
-
-

AM 9:00

-

"어제 매출 얼마야?" → 팀장 보고 대기중...

-
-
-

PM 2:00

-

"수주 밀린 거 없어?" → Excel 취합중...

-
-
-

PM 5:00

-

"결재할 것 좀 정리해줘" → 서류 찾는중...

-
-
-
- - -
-

-

SAM으로 바꾸면

-
- - -
- -
-
-
-
-

SAM CEO Dashboard ― 로그인 후 3초

-
- -
-
-

월 매출

-

5.2억

-

▲ 15.3%

-
-
-

누적 수주

-

127건

-

▲ 8건

-
-
-

납기 준수율

-

96%

-

목표 달성

-
-
-

승인 대기

-

5건

-

즉시 처리

-
-
- -
-
-

월별 매출 추이

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

조직별 실적

-
-
-
-

영업1팀

-
-
-
-
-
-
-

영업2팀

-
-
-
-
-
-
-

생산팀

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

SAM 대시보드가 드리는 약속

-

- 로그인 한 번이면 전사 매출, 수주, 조직 실적, 승인 대기 건수를 - 한눈에 파악합니다. 보고를 기다리는 시간을 제로로 만들어 드립니다. -

-
- - -
-
-

클라우드 기반 (설치 불필요)

-
-
-

모바일 대응

-
-
-

역할별 권한 분리

-
-
- - -
-
-
-

(주)코드브릿지엑스

-

www.codebridge-x.com

-
-
-

뒷면에서 상세 기능을 확인하세요

-
-
-
- - \ No newline at end of file diff --git a/sam/docs/brochure/v3/convert-1page.cjs b/sam/docs/brochure/v3/convert-1page.cjs deleted file mode 100644 index 38f401a..0000000 --- a/sam/docs/brochure/v3/convert-1page.cjs +++ /dev/null @@ -1,27 +0,0 @@ -const path = require('path'); -module.paths.unshift(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/node_modules')); - -const PptxGenJS = require('pptxgenjs'); -const html2pptx = require(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/html2pptx.js')); - -async function main() { - const pres = new PptxGenJS(); - - pres.defineLayout({ name: 'PORTRAIT_9x16', width: 5.625, height: 10 }); - pres.layout = 'PORTRAIT_9x16'; - - const htmlFile = path.join(__dirname, 'slides', 'brochure-dashboard-1page.html'); - console.log('Converting CEO Dashboard v3 1-page brochure...'); - - try { - await html2pptx(htmlFile, pres); - } catch (err) { - console.error(`Error: ${err.message}`); - } - - const outputPath = path.join(__dirname, 'sam-brochure-v3-dashboard-1page.pptx'); - await pres.writeFile({ fileName: outputPath }); - console.log(`\nPPTX created: ${outputPath}`); -} - -main().catch(console.error); diff --git a/sam/docs/brochure/v3/convert-2page.cjs b/sam/docs/brochure/v3/convert-2page.cjs deleted file mode 100644 index ee5132c..0000000 --- a/sam/docs/brochure/v3/convert-2page.cjs +++ /dev/null @@ -1,31 +0,0 @@ -const path = require('path'); -module.paths.unshift(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/node_modules')); - -const PptxGenJS = require('pptxgenjs'); -const html2pptx = require(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/html2pptx.js')); - -async function main() { - const pres = new PptxGenJS(); - - pres.defineLayout({ name: 'PORTRAIT_9x16', width: 5.625, height: 10 }); - pres.layout = 'PORTRAIT_9x16'; - - const slidesDir = path.join(__dirname, 'slides'); - const slides = ['brochure-dashboard-front.html', 'brochure-dashboard-back.html']; - - for (const file of slides) { - const htmlFile = path.join(slidesDir, file); - console.log(`Converting ${file} ...`); - try { - await html2pptx(htmlFile, pres); - } catch (err) { - console.error(`Error on ${file}: ${err.message}`); - } - } - - const outputPath = path.join(__dirname, 'sam-brochure-v3-dashboard-2page.pptx'); - await pres.writeFile({ fileName: outputPath }); - console.log(`\nPPTX created: ${outputPath}`); -} - -main().catch(console.error); diff --git a/sam/docs/brochure/v3/sam-brochure-v3-dashboard-1page.pptx b/sam/docs/brochure/v3/sam-brochure-v3-dashboard-1page.pptx deleted file mode 100644 index cbb6084..0000000 Binary files a/sam/docs/brochure/v3/sam-brochure-v3-dashboard-1page.pptx and /dev/null differ diff --git a/sam/docs/brochure/v3/sam-brochure-v3-dashboard-2page.pptx b/sam/docs/brochure/v3/sam-brochure-v3-dashboard-2page.pptx deleted file mode 100644 index cdc1014..0000000 Binary files a/sam/docs/brochure/v3/sam-brochure-v3-dashboard-2page.pptx and /dev/null differ diff --git a/sam/docs/brochure/v3/slides/brochure-dashboard-1page.html b/sam/docs/brochure/v3/slides/brochure-dashboard-1page.html deleted file mode 100644 index 8547c7d..0000000 --- a/sam/docs/brochure/v3/slides/brochure-dashboard-1page.html +++ /dev/null @@ -1,405 +0,0 @@ - - - - - - - - -
- -
-

CEO DASHBOARD v3

-
- - -
-
-

EXECUTIVE DASHBOARD

-

대표님, 우리 회사
지금 어떤 상태인가요?

-

보고 대기 없이, 로그인 한 번이면
전사 현황이 한눈에 들어옵니다.

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

SAM CEO Dashboard

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

5.2억

-

▲ 15.3%

-

월 매출

-
- -
- - - - -

127건

-

▲ 8건

-

수주 잔량

-
- -
- - - - 96 - -

96%

-

목표 달성

-

납기 준수율

-
- -
- - - - - -

5건

-

즉시 처리

-

승인 대기

-
-
- -
- -
-

월별 매출 추이

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

영업1팀 38%

-
-
-
-

영업2팀 25%

-
-
-
-

생산팀 22%

-
-
-
-

품질팀 15%

-
-
-
-
-
- - -
-

대표님이 얻는 것

-
- -
- - - - - - - -

즉시 현황 파악

-

로그인 3초면
전사 현황 확인

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

데이터로 판단

-

감이 아닌 숫자로
KPI/팀 성과 비교

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

모바일 승인

-

이동중에도 즉시
결재/승인 처리

-
-
-
- - -
- - -
-

대시보드 핵심 기능

-
-
- -
- - - - - -

실시간 매출/수주 KPI

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

조직 계층별 실적 트리

-
-
-
- -
- - - - -

역할별 수당 현황

-
- -
- - - - 5 - - -

미승인 실시간 알림

-
-
-
- -
- - - - -

기간별 트렌드 분석

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

수익 시뮬레이터

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

BEFORE

-
-

매출? → 보고 대기 1~2일

-

수주? → Excel 취합 반나절

-

승인? → 서류 찾기 30분

-

실적? → 각 팀장 개별 보고

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

AFTER (SAM)

-
-

로그인 → 3초 전사 현황

-

클릭 → 실시간 수주 데이터

-

뱃지 → 즉시 승인 처리

-

트리 → 전 조직 한눈에

-
-
- - -
-
- - - - -

실시간 업데이트

-
-
- - - - -

PC + 모바일

-
-
- - - - - -

역할별 권한

-
-
- - - - - -

데이터 암호화

-
-
- - - - - -

클라우드

-
-
- - -
-
-
-

(주)코드브릿지엑스

-

www.codebridge-x.com

-
-
-

무료 데모 신청

-

contact@codebridge-x.com

-
-
-
- - \ No newline at end of file diff --git a/sam/docs/brochure/v3/slides/brochure-dashboard-back.html b/sam/docs/brochure/v3/slides/brochure-dashboard-back.html deleted file mode 100644 index f199750..0000000 --- a/sam/docs/brochure/v3/slides/brochure-dashboard-back.html +++ /dev/null @@ -1,373 +0,0 @@ - - - - - - - - -
- -
-

FEATURES & PRICING

-
- - -
-

대시보드 핵심 기능

-
- -
- - - - - -
-

실시간 KPI 카드

-
-

매출, 수주, 납기율, 승인 대기

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

조직 실적 트리

-
-

계층별 팀/개인 실적 펼쳐보기

-
- -
- - - - -
-

역할별 수당 현황

-
-

판매자/관리자/협업자 배분 확인

-
- -
- - - - ! - - -
-

승인 대기 알림

-
-

가입/지급 미처리 빨간 뱃지

-
- -
- - - - -
-

기간별 트렌드

-
-

당월/분기/연간 추이 차트

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

수익 시뮬레이터

-
-

가상 시나리오 수당/마진 계산

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

모바일 대응

-
-

스마트폰으로 KPI 확인/승인

-
-
-
- - -
- - -
-

역할별 맞춤 화면

-
- -
- - - - - -

CEO

-

전사 KPI 총괄

-
- -
- - - - - - -

관리자

-

팀 실적 관리

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

운영자

-

인력/승인 관리

-
- -
- - - - - - - -

영업자

-

내 실적 조회

-
-
-
- - -
- - -
-

대시보드 + SAM ERP/MES 통합

-
-
- - - - - - -

견적/수주

-
-
- - - - - - -

생산 MES

-
-
- - - - - -

품질/검사

-
-
- - - - - -

재고/자재

-
-
- - - - -

인사/회계

-
-
-

대시보드의 모든 데이터는 SAM ERP/MES 실시간 데이터 기반

-
- - -
- - -
-

투자 비용

-
- -
-
-
- - - - -

대시보드 포함 기본 패키지

-
-

2,000만원

-

+ 월 50만원 (유지보수)

-
-
-

CEO 대시보드 + 견적/수주 + 생산
인사/회계 무료 포함

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

추가 옵션 (선택)

-
-
-
-

생산공정 관리

-

+500만원

-
-
-

품질관리(인정검사)

-

+2,000만원

-
-
-

AI 견적 자동 생성

-

월 10~20만원

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

도입 프로세스

-
-
- - - - - -

1~2주

-

현장 인터뷰

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

2~4주

-

맞춤 개발

-
- - - -
- - - - - -

1~2주

-

데이터 이관

-
- - - -
- - - - -

1~2주

-

교육/안정화

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

무료 데모를 신청하세요

-

대표님 전용 대시보드를 직접 체험

-
-
-
-

contact@codebridge-x.com

-

www.codebridge-x.com

-
-
-
- - -
-

(주)코드브릿지엑스 | SAM - Smart Automation Management

-
- - \ No newline at end of file diff --git a/sam/docs/brochure/v3/slides/brochure-dashboard-front.html b/sam/docs/brochure/v3/slides/brochure-dashboard-front.html deleted file mode 100644 index b1d8828..0000000 --- a/sam/docs/brochure/v3/slides/brochure-dashboard-front.html +++ /dev/null @@ -1,262 +0,0 @@ - - - - - - - - -
- -
-

CEO DASHBOARD v3

-
- - -
-
-

EXECUTIVE DASHBOARD

-

대표님, 우리 회사
지금 어떤 상태인가요?

-

매출, 수주, 조직 실적, 승인 대기
더 이상 보고를 기다리지 마세요.

-
- -
- - - - - - - - - - - - - - - - - - - - 5 - - - - - - - - - - - -
-
- - -
- - -
-

대표님의 하루

-
- -
- - - - - 9AM - -
-

"어제 매출 얼마야?" → 팀장 보고 대기중...

-
-
- -
- - - - - 2PM - -
-

"수주 밀린 거 없어?" → Excel 취합중...

-
-
- -
- - - - - 5PM - -
-

"결재할 것 정리해줘" → 서류 찾는중...

-
-
-
-
- - -
- - - -

SAM 도입 후

-
- - -
- -
-
-
-
-

SAM CEO Dashboard ― 로그인 후 3초

-
- -
-
- - - - - -

5.2억

-

▲ 15.3%

-

월 매출

-
-
- - - - -

127건

-

▲ 8건

-

누적 수주

-
-
- - - - -

96%

-

목표 달성

-

납기 준수율

-
-
- - - - - -

5건

-

즉시 처리

-

승인 대기

-
-
- -
-
-

월별 매출 추이

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

영업1팀

-
-
-
-

영업2팀

-
-
-
-

생산팀

-
-
-
-

품질팀

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

SAM 대시보드가 드리는 약속

-

로그인 한 번이면 전사 매출, 수주, 승인 대기를 한눈에.
보고를 기다리는 시간을 제로로 만들어 드립니다.

-
-
-
- - -
-
- -

클라우드 기반

-
-
- -

PC + 모바일

-
-
- -

역할별 권한

-
-
- - -
-
-
-

(주)코드브릿지엑스

-

www.codebridge-x.com

-
-
-

뒷면에서 상세 기능을 확인하세요 ▶

-
-
-
- - \ No newline at end of file diff --git a/sam/docs/brochure/v4/convert-1page.cjs b/sam/docs/brochure/v4/convert-1page.cjs deleted file mode 100644 index e218f62..0000000 --- a/sam/docs/brochure/v4/convert-1page.cjs +++ /dev/null @@ -1,27 +0,0 @@ -const path = require('path'); -module.paths.unshift(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/node_modules')); - -const PptxGenJS = require('pptxgenjs'); -const html2pptx = require(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/html2pptx.js')); - -async function main() { - const pres = new PptxGenJS(); - - pres.defineLayout({ name: 'PORTRAIT_9x16', width: 5.625, height: 10 }); - pres.layout = 'PORTRAIT_9x16'; - - const htmlFile = path.join(__dirname, 'slides', 'brochure-dashboard-1page.html'); - console.log('Converting CEO Dashboard v4 (Light) 1-page brochure...'); - - try { - await html2pptx(htmlFile, pres); - } catch (err) { - console.error(`Error: ${err.message}`); - } - - const outputPath = path.join(__dirname, 'sam-brochure-v4-dashboard-1page.pptx'); - await pres.writeFile({ fileName: outputPath }); - console.log(`\nPPTX created: ${outputPath}`); -} - -main().catch(console.error); diff --git a/sam/docs/brochure/v4/convert-2page.cjs b/sam/docs/brochure/v4/convert-2page.cjs deleted file mode 100644 index f8c691d..0000000 --- a/sam/docs/brochure/v4/convert-2page.cjs +++ /dev/null @@ -1,31 +0,0 @@ -const path = require('path'); -module.paths.unshift(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/node_modules')); - -const PptxGenJS = require('pptxgenjs'); -const html2pptx = require(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/html2pptx.js')); - -async function main() { - const pres = new PptxGenJS(); - - pres.defineLayout({ name: 'PORTRAIT_9x16', width: 5.625, height: 10 }); - pres.layout = 'PORTRAIT_9x16'; - - const slidesDir = path.join(__dirname, 'slides'); - const slides = ['brochure-dashboard-front.html', 'brochure-dashboard-back.html']; - - for (const file of slides) { - const htmlFile = path.join(slidesDir, file); - console.log(`Converting ${file} ...`); - try { - await html2pptx(htmlFile, pres); - } catch (err) { - console.error(`Error on ${file}: ${err.message}`); - } - } - - const outputPath = path.join(__dirname, 'sam-brochure-v4-dashboard-2page.pptx'); - await pres.writeFile({ fileName: outputPath }); - console.log(`\nPPTX created: ${outputPath}`); -} - -main().catch(console.error); diff --git a/sam/docs/brochure/v4/sam-brochure-v4-dashboard-1page.pptx b/sam/docs/brochure/v4/sam-brochure-v4-dashboard-1page.pptx deleted file mode 100644 index 747d4f4..0000000 Binary files a/sam/docs/brochure/v4/sam-brochure-v4-dashboard-1page.pptx and /dev/null differ diff --git a/sam/docs/brochure/v4/sam-brochure-v4-dashboard-2page.pptx b/sam/docs/brochure/v4/sam-brochure-v4-dashboard-2page.pptx deleted file mode 100644 index c56e36e..0000000 Binary files a/sam/docs/brochure/v4/sam-brochure-v4-dashboard-2page.pptx and /dev/null differ diff --git a/sam/docs/brochure/v4/slides/brochure-dashboard-1page.html b/sam/docs/brochure/v4/slides/brochure-dashboard-1page.html deleted file mode 100644 index 8792a24..0000000 --- a/sam/docs/brochure/v4/slides/brochure-dashboard-1page.html +++ /dev/null @@ -1,405 +0,0 @@ - - - - - - - - -
- -
-

CEO DASHBOARD v4

-
- - -
-
-

EXECUTIVE DASHBOARD

-

대표님, 우리 회사
지금 어떤 상태인가요?

-

보고 대기 없이, 로그인 한 번이면
전사 현황이 한눈에 들어옵니다.

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

SAM CEO Dashboard

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

5.2억

-

▲ 15.3%

-

월 매출

-
- -
- - - - -

127건

-

▲ 8건

-

수주 잔량

-
- -
- - - - 96 - -

96%

-

목표 달성

-

납기 준수율

-
- -
- - - - - -

5건

-

즉시 처리

-

승인 대기

-
-
- -
- -
-

월별 매출 추이

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

영업1팀 38%

-
-
-
-

영업2팀 25%

-
-
-
-

생산팀 22%

-
-
-
-

품질팀 15%

-
-
-
-
-
- - -
-

대표님이 얻는 것

-
- -
- - - - - - - -

즉시 현황 파악

-

로그인 3초면
전사 현황 확인

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

데이터로 판단

-

감이 아닌 숫자로
KPI/팀 성과 비교

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

모바일 승인

-

이동중에도 즉시
결재/승인 처리

-
-
-
- - -
- - -
-

대시보드 핵심 기능

-
-
- -
- - - - - -

실시간 매출/수주 KPI

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

조직 계층별 실적 트리

-
-
-
- -
- - - - -

역할별 수당 현황

-
- -
- - - - 5 - - -

미승인 실시간 알림

-
-
-
- -
- - - - -

기간별 트렌드 분석

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

수익 시뮬레이터

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

BEFORE

-
-

매출? → 보고 대기 1~2일

-

수주? → Excel 취합 반나절

-

승인? → 서류 찾기 30분

-

실적? → 각 팀장 개별 보고

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

AFTER (SAM)

-
-

로그인 → 3초 전사 현황

-

클릭 → 실시간 수주 데이터

-

뱃지 → 즉시 승인 처리

-

트리 → 전 조직 한눈에

-
-
- - -
-
- - - - -

실시간 업데이트

-
-
- - - - -

PC + 모바일

-
-
- - - - - -

역할별 권한

-
-
- - - - - -

데이터 암호화

-
-
- - - - - -

클라우드

-
-
- - -
-
-
-

(주)코드브릿지엑스

-

www.codebridge-x.com

-
-
-

무료 데모 신청

-

contact@codebridge-x.com

-
-
-
- - \ No newline at end of file diff --git a/sam/docs/brochure/v4/slides/brochure-dashboard-back.html b/sam/docs/brochure/v4/slides/brochure-dashboard-back.html deleted file mode 100644 index 6b64b85..0000000 --- a/sam/docs/brochure/v4/slides/brochure-dashboard-back.html +++ /dev/null @@ -1,373 +0,0 @@ - - - - - - - - -
- -
-

FEATURES & PRICING

-
- - -
-

대시보드 핵심 기능

-
- -
- - - - - -
-

실시간 KPI 카드

-
-

매출, 수주, 납기율, 승인 대기

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

조직 실적 트리

-
-

계층별 팀/개인 실적 펼쳐보기

-
- -
- - - - -
-

역할별 수당 현황

-
-

판매자/관리자/협업자 배분 확인

-
- -
- - - - ! - - -
-

승인 대기 알림

-
-

가입/지급 미처리 빨간 뱃지

-
- -
- - - - -
-

기간별 트렌드

-
-

당월/분기/연간 추이 차트

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

수익 시뮬레이터

-
-

가상 시나리오 수당/마진 계산

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

모바일 대응

-
-

스마트폰으로 KPI 확인/승인

-
-
-
- - -
- - -
-

역할별 맞춤 화면

-
- -
- - - - - -

CEO

-

전사 KPI 총괄

-
- -
- - - - - - -

관리자

-

팀 실적 관리

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

운영자

-

인력/승인 관리

-
- -
- - - - - - - -

영업자

-

내 실적 조회

-
-
-
- - -
- - -
-

대시보드 + SAM ERP/MES 통합

-
-
- - - - - - -

견적/수주

-
-
- - - - - - -

생산 MES

-
-
- - - - - -

품질/검사

-
-
- - - - - -

재고/자재

-
-
- - - - -

인사/회계

-
-
-

대시보드의 모든 데이터는 SAM ERP/MES 실시간 데이터 기반

-
- - -
- - -
-

투자 비용

-
- -
-
-
- - - - -

대시보드 포함 기본 패키지

-
-

2,000만원

-

+ 월 50만원 (유지보수)

-
-
-

CEO 대시보드 + 견적/수주 + 생산
인사/회계 무료 포함

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

추가 옵션 (선택)

-
-
-
-

생산공정 관리

-

+500만원

-
-
-

품질관리(인정검사)

-

+2,000만원

-
-
-

AI 견적 자동 생성

-

월 10~20만원

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

도입 프로세스

-
-
- - - - - -

1~2주

-

현장 인터뷰

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

2~4주

-

맞춤 개발

-
- - - -
- - - - - -

1~2주

-

데이터 이관

-
- - - -
- - - - -

1~2주

-

교육/안정화

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

무료 데모를 신청하세요

-

대표님 전용 대시보드를 직접 체험

-
-
-
-

contact@codebridge-x.com

-

www.codebridge-x.com

-
-
-
- - -
-

(주)코드브릿지엑스 | SAM - Smart Automation Management

-
- - \ No newline at end of file diff --git a/sam/docs/brochure/v4/slides/brochure-dashboard-front.html b/sam/docs/brochure/v4/slides/brochure-dashboard-front.html deleted file mode 100644 index 8f4165f..0000000 --- a/sam/docs/brochure/v4/slides/brochure-dashboard-front.html +++ /dev/null @@ -1,260 +0,0 @@ - - - - - - - - -
- -
-

CEO DASHBOARD v4

-
- - -
-
-

EXECUTIVE DASHBOARD

-

대표님, 우리 회사
지금 어떤 상태인가요?

-

매출, 수주, 조직 실적, 승인 대기
더 이상 보고를 기다리지 마세요.

-
- -
- - - - - - - - - - - - - - - - - - 5 - - - - - - - - - - - -
-
- - -
- - -
-

대표님의 하루

-
- -
- - - - - 9AM - -
-

"어제 매출 얼마야?" → 팀장 보고 대기중...

-
-
- -
- - - - - 2PM - -
-

"수주 밀린 거 없어?" → Excel 취합중...

-
-
- -
- - - - - 5PM - -
-

"결재할 것 정리해줘" → 서류 찾는중...

-
-
-
-
- - -
- - - -

SAM 도입 후

-
- - -
- -
-
-
-
-

SAM CEO Dashboard ― 로그인 후 3초

-
- -
-
- - - - - -

5.2억

-

▲ 15.3%

-

월 매출

-
-
- - - - -

127건

-

▲ 8건

-

누적 수주

-
-
- - - - -

96%

-

목표 달성

-

납기 준수율

-
-
- - - - - -

5건

-

즉시 처리

-

승인 대기

-
-
- -
-
-

월별 매출 추이

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

영업1팀

-
-
-
-

영업2팀

-
-
-
-

생산팀

-
-
-
-

품질팀

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

SAM 대시보드가 드리는 약속

-

로그인 한 번이면 전사 매출, 수주, 승인 대기를 한눈에.
보고를 기다리는 시간을 제로로 만들어 드립니다.

-
-
-
- - -
-
- -

클라우드 기반

-
-
- -

PC + 모바일

-
-
- -

역할별 권한

-
-
- - -
-
-
-

(주)코드브릿지엑스

-

www.codebridge-x.com

-
-
-

뒷면에서 상세 기능을 확인하세요 ▶

-
-
-
- - \ No newline at end of file diff --git a/sam/docs/brochure/v5/convert-1page.cjs b/sam/docs/brochure/v5/convert-1page.cjs deleted file mode 100644 index 840ccc9..0000000 --- a/sam/docs/brochure/v5/convert-1page.cjs +++ /dev/null @@ -1,52 +0,0 @@ -const path = require('path'); -module.paths.unshift(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/node_modules')); - -const PptxGenJS = require('pptxgenjs'); -const html2pptx = require(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/html2pptx.js')); -const sharp = require('sharp'); - -async function generateGradientBg() { - const svgGradient = ` - - - - - - - - - `; - const buf = await sharp(Buffer.from(svgGradient)).png().toBuffer(); - return buf.toString('base64'); -} - -async function main() { - const pres = new PptxGenJS(); - - pres.defineLayout({ name: 'PORTRAIT_9x16', width: 5.625, height: 10 }); - pres.layout = 'PORTRAIT_9x16'; - - // Pre-generate gradient background PNG - console.log('Generating gradient background...'); - const bgBase64 = await generateGradientBg(); - - const htmlFile = path.join(__dirname, 'slides', 'brochure-dashboard-1page.html'); - console.log('Converting CEO Dashboard v5 (Premium Gradient) 1-page brochure...'); - - try { - await html2pptx(htmlFile, pres); - } catch (err) { - console.error(`Error: ${err.message}`); - } - - // Set gradient background on each slide - for (const slide of pres.slides) { - slide.background = { data: `image/png;base64,${bgBase64}` }; - } - - const outputPath = path.join(__dirname, 'sam-brochure-v5-dashboard-1page.pptx'); - await pres.writeFile({ fileName: outputPath }); - console.log(`\nPPTX created: ${outputPath}`); -} - -main().catch(console.error); diff --git a/sam/docs/brochure/v5/convert-2page.cjs b/sam/docs/brochure/v5/convert-2page.cjs deleted file mode 100644 index 7aa1fd0..0000000 --- a/sam/docs/brochure/v5/convert-2page.cjs +++ /dev/null @@ -1,56 +0,0 @@ -const path = require('path'); -module.paths.unshift(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/node_modules')); - -const PptxGenJS = require('pptxgenjs'); -const html2pptx = require(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/html2pptx.js')); -const sharp = require('sharp'); - -async function generateGradientBg() { - const svgGradient = ` - - - - - - - - - `; - const buf = await sharp(Buffer.from(svgGradient)).png().toBuffer(); - return buf.toString('base64'); -} - -async function main() { - const pres = new PptxGenJS(); - - pres.defineLayout({ name: 'PORTRAIT_9x16', width: 5.625, height: 10 }); - pres.layout = 'PORTRAIT_9x16'; - - // Pre-generate gradient background PNG - console.log('Generating gradient background...'); - const bgBase64 = await generateGradientBg(); - - const slidesDir = path.join(__dirname, 'slides'); - const slides = ['brochure-dashboard-front.html', 'brochure-dashboard-back.html']; - - for (const file of slides) { - const htmlFile = path.join(slidesDir, file); - console.log(`Converting ${file} ...`); - try { - await html2pptx(htmlFile, pres); - } catch (err) { - console.error(`Error on ${file}: ${err.message}`); - } - } - - // Set gradient background on each slide - for (const slide of pres.slides) { - slide.background = { data: `image/png;base64,${bgBase64}` }; - } - - const outputPath = path.join(__dirname, 'sam-brochure-v5-dashboard-2page.pptx'); - await pres.writeFile({ fileName: outputPath }); - console.log(`\nPPTX created: ${outputPath}`); -} - -main().catch(console.error); diff --git a/sam/docs/brochure/v5/sam-brochure-v5-dashboard-1page.pptx b/sam/docs/brochure/v5/sam-brochure-v5-dashboard-1page.pptx deleted file mode 100644 index 60194bf..0000000 Binary files a/sam/docs/brochure/v5/sam-brochure-v5-dashboard-1page.pptx and /dev/null differ diff --git a/sam/docs/brochure/v5/sam-brochure-v5-dashboard-2page.pptx b/sam/docs/brochure/v5/sam-brochure-v5-dashboard-2page.pptx deleted file mode 100644 index e53d81c..0000000 Binary files a/sam/docs/brochure/v5/sam-brochure-v5-dashboard-2page.pptx and /dev/null differ diff --git a/sam/docs/brochure/v5/slides/brochure-dashboard-1page.html b/sam/docs/brochure/v5/slides/brochure-dashboard-1page.html deleted file mode 100644 index 6e8d331..0000000 --- a/sam/docs/brochure/v5/slides/brochure-dashboard-1page.html +++ /dev/null @@ -1,319 +0,0 @@ - - - - - - - - -
- -
-
-

EXECUTIVE EDITION

-
-
- - -
-
-

CEO DASHBOARD

-

대표님의 시간은
보고를 기다리는 데
쓰여선 안 됩니다.

-

로그인 3초. 매출, 수주, 승인까지
모든 경영 현황이 한 화면에.

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

SAM 도입 후

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

SAM CEO Dashboard

-
- -
-
-

5.2억

-

▲ 15.3%

-

월 매출

-
-
-

127건

-

▲ 8건

-

누적 수주

-
-
-

96%

-

목표 달성

-

납기 준수율

-
-
-

5건

-

즉시 처리

-

승인 대기

-
-
- -
-
-

월별 매출 추이

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

영업1팀

-
-
-
-

영업2팀

-
-
-
-

생산팀

-
-
-
-
-
- - -
-

대표님이 얻는 것

-
-
- - - - - -

즉시 현황 파악

-

로그인 3초면 전사 확인

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

데이터로 판단

-

감이 아닌 KPI 비교

-
-
- - - - -

모바일 승인

-

이동중 즉시 결재

-
-
-
- - -
- - -
-

대시보드 핵심 기능

-
-
-
- - - - - -

실시간 매출/수주 KPI

-
-
- - - - - - - - -

조직 계층별 실적 트리

-
-
-
-
- - - - -

역할별 수당 현황

-
-
- - - - 5 - -

미승인 실시간 알림

-
-
-
-
- - - - -

기간별 트렌드 분석

-
-
- - - - - - - -

수익 시뮬레이터

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

BEFORE

-
-

매출? → 보고 대기 1~2일

-

수주? → Excel 취합 반나절

-

승인? → 서류 찾기 30분

-

실적? → 각 팀장 개별 보고

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

AFTER (SAM)

-
-

로그인 → 3초 전사 현황

-

클릭 → 실시간 수주 데이터

-

뱃지 → 즉시 승인 처리

-

트리 → 전 조직 한눈에

-
-
- - -
-
- -

클라우드

-
-
- -

PC + 모바일

-
-
- -

역할별 권한

-
-
- -

데이터 암호화

-
-
- - -
-
-
-

(주)코드브릿지엑스

-

www.codebridge-x.com

-
-
-

무료 데모 신청

-

contact@codebridge-x.com

-
-
-
- - \ No newline at end of file diff --git a/sam/docs/brochure/v5/slides/brochure-dashboard-back.html b/sam/docs/brochure/v5/slides/brochure-dashboard-back.html deleted file mode 100644 index aa9f629..0000000 --- a/sam/docs/brochure/v5/slides/brochure-dashboard-back.html +++ /dev/null @@ -1,311 +0,0 @@ - - - - - - - - -
- -
-

FEATURES & PRICING

-
- - -
-

대시보드 핵심 기능

-
- -
- - - - - -
-

실시간 KPI 카드

-
-

매출, 수주, 납기율, 승인 대기

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

조직 실적 트리

-
-

계층별 팀/개인 실적 펼쳐보기

-
- -
- - - - -
-

역할별 수당 현황

-
-

판매자/관리자/협업자 배분 확인

-
- -
- - - - ! - - -
-

승인 대기 알림

-
-

가입/지급 미처리 빨간 뱃지

-
- -
- - - - -
-

기간별 트렌드

-
-

당월/분기/연간 추이 차트

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

수익 시뮬레이터

-
-

가상 시나리오 수당/마진 계산

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

모바일 대응

-
-

스마트폰으로 KPI 확인/승인

-
-
-
- - -
- - -
-

역할별 맞춤 화면

-
-
- - - - - -

CEO

-

전사 KPI 총괄

-
-
- - - - - - -

관리자

-

팀 실적 관리

-
-
- - - - - - - - -

운영자

-

인력/승인 관리

-
-
- - - - - - - -

영업자

-

내 실적 조회

-
-
-
- - -
- - -
-

투자 비용

-
-
-
-
- - - - -

대시보드 포함 기본 패키지

-
-

2,000만원

-

+ 월 50만원 (유지보수)

-
-
-

CEO 대시보드 + 견적/수주 + 생산
인사/회계 무료 포함

-
-
-
-
-
- - - - - -

추가 옵션 (선택)

-
-
-
-

생산공정 관리

-

+500만원

-
-
-

품질관리(인정검사)

-

+2,000만원

-
-
-

AI 견적 자동 생성

-

월 10~20만원

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

도입 프로세스

-
-
- - - - - -

1~2주

-

현장 인터뷰

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

2~4주

-

맞춤 개발

-
- - - -
- - - - - -

1~2주

-

데이터 이관

-
- - - -
- - - - -

1~2주

-

교육/안정화

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

무료 데모를 신청하세요

-

대표님 전용 대시보드를 직접 체험

-
-
-
-

contact@codebridge-x.com

-

www.codebridge-x.com

-
-
-
- - -
-

(주)코드브릿지엑스 | SAM - Smart Automation Management

-
- - \ No newline at end of file diff --git a/sam/docs/brochure/v5/slides/brochure-dashboard-front.html b/sam/docs/brochure/v5/slides/brochure-dashboard-front.html deleted file mode 100644 index ba19d78..0000000 --- a/sam/docs/brochure/v5/slides/brochure-dashboard-front.html +++ /dev/null @@ -1,216 +0,0 @@ - - - - - - - - -
- -
-
-

EXECUTIVE EDITION

-
-
- - -
-

CEO DASHBOARD

-

대표님의 시간은
보고를 기다리는 데
쓰여선 안 됩니다.

-

로그인 3초. 매출, 수주, 승인 대기까지
모든 경영 현황이 한 화면에.

-
- - -
-
-
- - - - -

1~2일

-

매출 보고 대기

-
-
- - - - - - -

반나절

-

Excel 수주 취합

-
-
- - - - -

30분

-

결재 서류 찾기

-
-
-

매일 반복되는 비효율, SAM이 제로로 만듭니다.

-
- - -
-
-
-

SAM 도입 후

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

SAM CEO Dashboard

-
- -
-
- - - - - -

5.2억

-

▲ 15.3%

-

월 매출

-
-
- - - - -

127건

-

▲ 8건

-

누적 수주

-
-
- - - - -

96%

-

목표 달성

-

납기 준수율

-
-
- - - - - -

5건

-

즉시 처리

-

승인 대기

-
-
- -
-
-

월별 매출 추이

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

영업1팀

-
-
-
-

영업2팀

-
-
-
-

생산팀

-
-
-
-

품질팀

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

대표님께 드리는 약속

-

보고를 기다리는 시간을 제로로.
의사결정에만 집중하실 수 있도록.

-
-
-
- - -
-
- -

클라우드 기반

-
-
- -

PC + 모바일

-
-
- -

역할별 권한

-
-
- - -
-
-
-

(주)코드브릿지엑스

-

www.codebridge-x.com

-
-
-

뒷면에서 상세 기능을 확인하세요 ▶

-
-
-
- - \ No newline at end of file diff --git a/sam/docs/brochure/v6/convert-1page.cjs b/sam/docs/brochure/v6/convert-1page.cjs deleted file mode 100644 index 99a9664..0000000 --- a/sam/docs/brochure/v6/convert-1page.cjs +++ /dev/null @@ -1,27 +0,0 @@ -const path = require('path'); -module.paths.unshift(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/node_modules')); - -const PptxGenJS = require('pptxgenjs'); -const html2pptx = require(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/html2pptx.js')); - -async function main() { - const pres = new PptxGenJS(); - - pres.defineLayout({ name: 'PORTRAIT_9x16', width: 5.625, height: 10 }); - pres.layout = 'PORTRAIT_9x16'; - - const htmlFile = path.join(__dirname, 'slides', 'brochure-dashboard-1page.html'); - console.log('Converting CEO Dashboard v6 (Corporate Blue & White) 1-page brochure...'); - - try { - await html2pptx(htmlFile, pres); - } catch (err) { - console.error(`Error: ${err.message}`); - } - - const outputPath = path.join(__dirname, 'sam-brochure-v6-dashboard-1page.pptx'); - await pres.writeFile({ fileName: outputPath }); - console.log(`\nPPTX created: ${outputPath}`); -} - -main().catch(console.error); diff --git a/sam/docs/brochure/v6/convert-2page.cjs b/sam/docs/brochure/v6/convert-2page.cjs deleted file mode 100644 index 604c5be..0000000 --- a/sam/docs/brochure/v6/convert-2page.cjs +++ /dev/null @@ -1,31 +0,0 @@ -const path = require('path'); -module.paths.unshift(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/node_modules')); - -const PptxGenJS = require('pptxgenjs'); -const html2pptx = require(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/html2pptx.js')); - -async function main() { - const pres = new PptxGenJS(); - - pres.defineLayout({ name: 'PORTRAIT_9x16', width: 5.625, height: 10 }); - pres.layout = 'PORTRAIT_9x16'; - - const slidesDir = path.join(__dirname, 'slides'); - const slides = ['brochure-dashboard-front.html', 'brochure-dashboard-back.html']; - - for (const file of slides) { - const htmlFile = path.join(slidesDir, file); - console.log(`Converting ${file} ...`); - try { - await html2pptx(htmlFile, pres); - } catch (err) { - console.error(`Error on ${file}: ${err.message}`); - } - } - - const outputPath = path.join(__dirname, 'sam-brochure-v6-dashboard-2page.pptx'); - await pres.writeFile({ fileName: outputPath }); - console.log(`\nPPTX created: ${outputPath}`); -} - -main().catch(console.error); diff --git a/sam/docs/brochure/v6/sam-brochure-v6-dashboard-1page.pptx b/sam/docs/brochure/v6/sam-brochure-v6-dashboard-1page.pptx deleted file mode 100644 index a9fa7c0..0000000 Binary files a/sam/docs/brochure/v6/sam-brochure-v6-dashboard-1page.pptx and /dev/null differ diff --git a/sam/docs/brochure/v6/sam-brochure-v6-dashboard-2page.pptx b/sam/docs/brochure/v6/sam-brochure-v6-dashboard-2page.pptx deleted file mode 100644 index 8c54f02..0000000 Binary files a/sam/docs/brochure/v6/sam-brochure-v6-dashboard-2page.pptx and /dev/null differ diff --git a/sam/docs/brochure/v6/slides/brochure-dashboard-1page.html b/sam/docs/brochure/v6/slides/brochure-dashboard-1page.html deleted file mode 100644 index 20ee484..0000000 --- a/sam/docs/brochure/v6/slides/brochure-dashboard-1page.html +++ /dev/null @@ -1,374 +0,0 @@ - - - - - - - - -
- -
-
-

CEO DASHBOARD

-
-
- - -
- - -
-
-

EXECUTIVE DASHBOARD

-

대표님, 우리 회사
지금 어떤 상태인가요?

-

보고 대기 없이, 로그인 한 번이면

-

전사 현황이 한눈에 들어옵니다.

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

SAM CEO Dashboard

-
- -
-
- - - - - - -

5.2억

-

▲ 15.3%

-

월 매출

-
-
- - - - -

127건

-

▲ 8건

-

수주 잔량

-
-
- - - - 96 - -

96%

-

목표 달성

-

납기 준수율

-
-
- - - - - -

5건

-

즉시 처리

-

승인 대기

-
-
- -
-
-

월별 매출 추이

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

영업1팀 38%

-
-
-
-

영업2팀 25%

-
-
-
-

생산팀 22%

-
-
-
-

품질팀 15%

-
-
-
-
-
- - -
-
-

대표님이 얻는 것

-
-
-
- - - - - - -

즉시 현황 파악

-

로그인 3초면
전사 현황 확인

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

데이터로 판단

-

감이 아닌 숫자로
KPI/팀 성과 비교

-
-
- - - - - - -

모바일 승인

-

이동중에도 즉시
결재/승인 처리

-
-
-
- - -
- - -
-
-

대시보드 핵심 기능

-
-
-
-
- - - - - -

실시간 매출/수주 KPI

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

조직 계층별 실적 트리

-
-
-
-
- - - - -

역할별 수당 현황

-
-
- - - - 5 - - -

미승인 실시간 알림

-
-
-
-
- - - - -

기간별 트렌드 분석

-
-
- - - - - - - - -

수익 시뮬레이터

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

BEFORE

-
-

매출? → 보고 대기 1~2일

-

수주? → Excel 취합 반나절

-

승인? → 서류 찾기 30분

-

실적? → 각 팀장 개별 보고

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

AFTER (SAM)

-
-

로그인 → 3초 전사 현황

-

클릭 → 실시간 수주 데이터

-

뱃지 → 즉시 승인 처리

-

트리 → 전 조직 한눈에

-
-
- - -
-
- - - - -

실시간 업데이트

-
-
- - - - -

PC + 모바일

-
-
- - - - - -

역할별 권한

-
-
- - - - - -

데이터 암호화

-
-
- - - - - -

클라우드

-
-
- - -
-
-
-

(주)코드브릿지엑스

-

www.codebridge-x.com

-
-
-

무료 데모 신청

-

contact@codebridge-x.com

-
-
-
- -
- - \ No newline at end of file diff --git a/sam/docs/brochure/v6/slides/brochure-dashboard-back.html b/sam/docs/brochure/v6/slides/brochure-dashboard-back.html deleted file mode 100644 index 792d610..0000000 --- a/sam/docs/brochure/v6/slides/brochure-dashboard-back.html +++ /dev/null @@ -1,337 +0,0 @@ - - - - - - - - -
- -
-
-

FEATURES & PRICING

-
-
- - -
- - -
-
-

대시보드 핵심 기능

-
-
- -
- - - - - -
-

실시간 KPI 카드

-
-

매출, 수주, 납기율, 승인 대기

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

조직 실적 트리

-
-

계층별 팀/개인 실적 펼쳐보기

-
- -
- - - - -
-

역할별 수당 현황

-
-

판매자/관리자/협업자 배분 확인

-
- -
- - - - ! - - -
-

승인 대기 알림

-
-

가입/지급 미처리 빨간 뱃지

-
- -
- - - - -
-

기간별 트렌드

-
-

당월/분기/연간 추이 차트

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

수익 시뮬레이터

-
-

가상 시나리오 수당/마진 계산

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

모바일 대응

-
-

스마트폰으로 KPI 확인/승인

-
-
-
- - -
- - -
-
-

역할별 맞춤 화면

-
-
- -
- - - - - -

CEO

-

전사 KPI 총괄

-
- -
- - - - - - -

관리자

-

팀 실적 관리

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

운영자

-

인력/승인 관리

-
- -
- - - - - - - -

영업자

-

내 실적 조회

-
-
-
- - -
- - -
-
-

투자 비용

-
-
- -
-
-
- - - - -

대시보드 포함 기본 패키지

-
-

2,000만원

-

+ 월 50만원 (유지보수)

-
-
-

CEO 대시보드 + 견적/수주 + 생산

-

인사/회계 무료 포함

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

추가 옵션 (선택)

-
-
-
-

생산공정 관리

-

+500만원

-
-
-

품질관리(인정검사)

-

+2,000만원

-
-
-

AI 견적 자동 생성

-

월 10~20만원

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

도입 프로세스

-
-
-
- - - - - -

1~2주

-

현장 인터뷰

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

2~4주

-

맞춤 개발

-
- - - -
- - - - - -

1~2주

-

데이터 이관

-
- - - -
- - - - -

1~2주

-

교육/안정화

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

무료 데모를 신청하세요

-

대표님 전용 대시보드를 직접 체험

-
-
-
-

contact@codebridge-x.com

-

www.codebridge-x.com

-
-
-
- - -
-

(주)코드브릿지엑스 | SAM - Smart Automation Management

-
- -
- - \ No newline at end of file diff --git a/sam/docs/brochure/v6/slides/brochure-dashboard-front.html b/sam/docs/brochure/v6/slides/brochure-dashboard-front.html deleted file mode 100644 index d25994a..0000000 --- a/sam/docs/brochure/v6/slides/brochure-dashboard-front.html +++ /dev/null @@ -1,231 +0,0 @@ - - - - - - - - -
- -
-
-

CEO DASHBOARD

-
-
- - -
- - -
-
-

EXECUTIVE DASHBOARD

-

대표님, 우리 회사
지금 어떤 상태인가요?

-

매출, 수주, 조직 실적, 승인 대기

-

더 이상 보고를 기다리지 마세요.

-
- -
- - - - - - - - - - - - - 5 - - - - -
-
- - -
- - -
- -
-
-
-
-

SAM CEO Dashboard ― 로그인 후 3초

-
- -
-
- - - - - -

5.2억

-

▲ 15.3%

-

월 매출

-
-
- - - - -

127건

-

▲ 8건

-

누적 수주

-
-
- - - - -

96%

-

목표 달성

-

납기 준수율

-
-
- - - - - -

5건

-

즉시 처리

-

승인 대기

-
-
- -
-
-

월별 매출 추이

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

영업1팀

-
-
-
-

영업2팀

-
-
-
-

생산팀

-
-
-
-

품질팀

-
-
-
-
-
- - -
-
-

대표님이 얻는 것

-
-
- -
- - - - - - -

즉시 현황 파악

-

로그인 3초면
전사 현황 확인

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

데이터로 판단

-

감이 아닌 숫자로
KPI/팀 성과 비교

-
- -
- - - - - - -

모바일 승인

-

이동중에도 즉시
결재/승인 처리

-
-
-
- - -
-
- -

클라우드 기반

-
-
- -

PC + 모바일

-
-
- -

역할별 권한

-
-
- - -
-
-
-

(주)코드브릿지엑스

-

www.codebridge-x.com

-
-
-

뒷면에서 상세 기능을 확인하세요 ▶

-
-
-
- -
- - \ No newline at end of file diff --git a/sam/docs/brochure/v7/convert-1page.cjs b/sam/docs/brochure/v7/convert-1page.cjs deleted file mode 100644 index 723bfce..0000000 --- a/sam/docs/brochure/v7/convert-1page.cjs +++ /dev/null @@ -1,27 +0,0 @@ -const path = require('path'); -module.paths.unshift(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/node_modules')); - -const PptxGenJS = require('pptxgenjs'); -const html2pptx = require(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/html2pptx.js')); - -async function main() { - const pres = new PptxGenJS(); - - pres.defineLayout({ name: 'PORTRAIT_9x16', width: 5.625, height: 10 }); - pres.layout = 'PORTRAIT_9x16'; - - const htmlFile = path.join(__dirname, 'slides', 'brochure-dashboard-1page.html'); - console.log('Converting CEO Dashboard v7 (Warm Gray + Teal) 1-page brochure...'); - - try { - await html2pptx(htmlFile, pres); - } catch (err) { - console.error(`Error: ${err.message}`); - } - - const outputPath = path.join(__dirname, 'sam-brochure-v7-dashboard-1page.pptx'); - await pres.writeFile({ fileName: outputPath }); - console.log(`\nPPTX created: ${outputPath}`); -} - -main().catch(console.error); diff --git a/sam/docs/brochure/v7/convert-2page.cjs b/sam/docs/brochure/v7/convert-2page.cjs deleted file mode 100644 index bf9d100..0000000 --- a/sam/docs/brochure/v7/convert-2page.cjs +++ /dev/null @@ -1,31 +0,0 @@ -const path = require('path'); -module.paths.unshift(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/node_modules')); - -const PptxGenJS = require('pptxgenjs'); -const html2pptx = require(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/html2pptx.js')); - -async function main() { - const pres = new PptxGenJS(); - - pres.defineLayout({ name: 'PORTRAIT_9x16', width: 5.625, height: 10 }); - pres.layout = 'PORTRAIT_9x16'; - - const slidesDir = path.join(__dirname, 'slides'); - const slides = ['brochure-dashboard-front.html', 'brochure-dashboard-back.html']; - - for (const file of slides) { - const htmlFile = path.join(slidesDir, file); - console.log(`Converting ${file} ...`); - try { - await html2pptx(htmlFile, pres); - } catch (err) { - console.error(`Error on ${file}: ${err.message}`); - } - } - - const outputPath = path.join(__dirname, 'sam-brochure-v7-dashboard-2page.pptx'); - await pres.writeFile({ fileName: outputPath }); - console.log(`\nPPTX created: ${outputPath}`); -} - -main().catch(console.error); diff --git a/sam/docs/brochure/v7/sam-brochure-v7-dashboard-1page.pptx b/sam/docs/brochure/v7/sam-brochure-v7-dashboard-1page.pptx deleted file mode 100644 index 6f12fd7..0000000 Binary files a/sam/docs/brochure/v7/sam-brochure-v7-dashboard-1page.pptx and /dev/null differ diff --git a/sam/docs/brochure/v7/sam-brochure-v7-dashboard-2page.pptx b/sam/docs/brochure/v7/sam-brochure-v7-dashboard-2page.pptx deleted file mode 100644 index 20a6bd1..0000000 Binary files a/sam/docs/brochure/v7/sam-brochure-v7-dashboard-2page.pptx and /dev/null differ diff --git a/sam/docs/brochure/v7/slides/brochure-dashboard-1page.html b/sam/docs/brochure/v7/slides/brochure-dashboard-1page.html deleted file mode 100644 index 4cde3f3..0000000 --- a/sam/docs/brochure/v7/slides/brochure-dashboard-1page.html +++ /dev/null @@ -1,376 +0,0 @@ - - - - - - - - -
- -
-

CEO DASHBOARD v7

-
- - -
-
-

EXECUTIVE DASHBOARD

-

대표님, 우리 회사
지금 어떤 상태인가요?

-

보고 대기 없이, 로그인 한 번이면
전사 현황이 한눈에 들어옵니다.

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

SAM CEO Dashboard

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

5.2억

-

▲ 15.3%

-

월 매출

-
- -
- - - - -

127건

-

▲ 8건

-

수주 잔량

-
- -
- - - - 96 - -

96%

-

목표 달성

-

납기 준수율

-
- -
- - - - - -

5건

-

즉시 처리

-

승인 대기

-
-
- -
- -
-

월별 매출 추이

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

영업1팀 38%

-
-
-
-

영업2팀 25%

-
-
-
-

생산팀 22%

-
-
-
-

품질팀 15%

-
-
-
-
-
- - -
-

대표님이 얻는 것

-
-
- - - - - - -

즉시 현황 파악

-

로그인 3초면
전사 현황 확인

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

데이터로 판단

-

감이 아닌 숫자로
KPI/팀 성과 비교

-
-
- - - - - - -

모바일 승인

-

이동중에도 즉시
결재/승인 처리

-
-
-
- - -
- - -
-

대시보드 핵심 기능

-
-
-
- - - - - -

실시간 매출/수주 KPI

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

조직 계층별 실적 트리

-
-
-
-
- - - - -

역할별 수당 현황

-
-
- - - - 5 - - -

미승인 실시간 알림

-
-
-
-
- - - - -

기간별 트렌드 분석

-
-
- - - - - - - - -

수익 시뮬레이터

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

BEFORE

-
-

매출? 보고 대기 1~2일

-

수주? Excel 취합 반나절

-

승인? 서류 찾기 30분

-

실적? 각 팀장 개별 보고

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

AFTER (SAM)

-
-

로그인 3초 전사 현황

-

클릭 실시간 수주 데이터

-

뱃지 즉시 승인 처리

-

트리 전 조직 한눈에

-
-
- - -
-
- - - - -

실시간 업데이트

-
-
- - - - -

PC + 모바일

-
-
- - - - - -

역할별 권한

-
-
- - - - - -

데이터 암호화

-
-
- - - - - -

클라우드

-
-
- - -
-
-
-

(주)코드브릿지엑스

-

www.codebridge-x.com

-
-
-

무료 데모 신청

-

contact@codebridge-x.com

-
-
-
- - \ No newline at end of file diff --git a/sam/docs/brochure/v7/slides/brochure-dashboard-back.html b/sam/docs/brochure/v7/slides/brochure-dashboard-back.html deleted file mode 100644 index 7298655..0000000 --- a/sam/docs/brochure/v7/slides/brochure-dashboard-back.html +++ /dev/null @@ -1,373 +0,0 @@ - - - - - - - - -
- -
-

FEATURES & PRICING

-
- - -
-

대시보드 핵심 기능

-
- -
- - - - - -
-

실시간 KPI 카드

-
-

매출, 수주, 납기율, 승인 대기

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

조직 실적 트리

-
-

계층별 팀/개인 실적 펼쳐보기

-
- -
- - - - -
-

역할별 수당 현황

-
-

판매자/관리자/협업자 배분 확인

-
- -
- - - - ! - - -
-

승인 대기 알림

-
-

가입/지급 미처리 빨간 뱃지

-
- -
- - - - -
-

기간별 트렌드

-
-

당월/분기/연간 추이 차트

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

수익 시뮬레이터

-
-

가상 시나리오 수당/마진 계산

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

모바일 대응

-
-

스마트폰으로 KPI 확인/승인

-
-
-
- - -
- - -
-

역할별 맞춤 화면

-
- -
- - - - - -

CEO

-

전사 KPI 총괄

-
- -
- - - - - - -

관리자

-

팀 실적 관리

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

운영자

-

인력/승인 관리

-
- -
- - - - - - - -

영업자

-

내 실적 조회

-
-
-
- - -
- - -
-

대시보드 + SAM ERP/MES 통합

-
-
- - - - - - -

견적/수주

-
-
- - - - - - -

생산 MES

-
-
- - - - - -

품질/검사

-
-
- - - - - -

재고/자재

-
-
- - - - -

인사/회계

-
-
-

대시보드의 모든 데이터는 SAM ERP/MES 실시간 데이터 기반

-
- - -
- - -
-

투자 비용

-
- -
-
-
- - - - -

대시보드 포함 기본 패키지

-
-

2,000만원

-

+ 월 50만원 (유지보수)

-
-
-

CEO 대시보드 + 견적/수주 + 생산
인사/회계 무료 포함

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

추가 옵션 (선택)

-
-
-
-

생산공정 관리

-

+500만원

-
-
-

품질관리(인정검사)

-

+2,000만원

-
-
-

AI 견적 자동 생성

-

월 10~20만원

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

도입 프로세스

-
-
- - - - - -

1~2주

-

현장 인터뷰

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

2~4주

-

맞춤 개발

-
- - - -
- - - - - -

1~2주

-

데이터 이관

-
- - - -
- - - - -

1~2주

-

교육/안정화

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

무료 데모를 신청하세요

-

대표님 전용 대시보드를 직접 체험

-
-
-
-

contact@codebridge-x.com

-

www.codebridge-x.com

-
-
-
- - -
-

(주)코드브릿지엑스 | SAM - Smart Automation Management

-
- - \ No newline at end of file diff --git a/sam/docs/brochure/v7/slides/brochure-dashboard-front.html b/sam/docs/brochure/v7/slides/brochure-dashboard-front.html deleted file mode 100644 index 1a4ccdd..0000000 --- a/sam/docs/brochure/v7/slides/brochure-dashboard-front.html +++ /dev/null @@ -1,278 +0,0 @@ - - - - - - - - -
- -
-

CEO DASHBOARD v7

-
- - -
-
-

EXECUTIVE DASHBOARD

-

대표님, 우리 회사
지금 어떤 상태인가요?

-

매출, 수주, 조직 실적, 승인 대기
더 이상 보고를 기다리지 마세요.

-
- -
- - - - - - - - - - - - - - - - - - 5 - - - - - -
-
- - -
- - -
-

대표님의 하루

-
- -
- - - - - 9AM - -
-

"어제 매출 얼마야?" 팀장 보고 대기중...

-
-
- -
- - - - - 2PM - -
-

"수주 밀린 거 없어?" Excel 취합중...

-
-
- -
- - - - - 5PM - -
-

"결재할 것 정리해줘" 서류 찾는중...

-
-
-
-
- - -
- - - -

SAM 도입 후

-
- - -
- -
-
-
-
-

SAM CEO Dashboard --- 로그인 후 3초

-
- -
-
- - - - - -

5.2억

-

▲ 15.3%

-

월 매출

-
-
- - - - -

127건

-

▲ 8건

-

누적 수주

-
-
- - - - -

96%

-

목표 달성

-

납기 준수율

-
-
- - - - - -

5건

-

즉시 처리

-

승인 대기

-
-
- -
-
-

월별 매출 추이

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

영업1팀

-
-
-
-

영업2팀

-
-
-
-

생산팀

-
-
-
-

품질팀

-
-
-
-
-
- - -
-

대표님이 얻는 것

-
- -
- - - - - - -

즉시 현황 파악

-

로그인 3초면
전사 현황 확인

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

데이터로 판단

-

감이 아닌 숫자로
KPI/팀 성과 비교

-
- -
- - - - - - -

모바일 승인

-

이동중에도 즉시
결재/승인 처리

-
-
-
- - -
-
- -

클라우드 기반

-
-
- -

PC + 모바일

-
-
- -

역할별 권한

-
-
- - -
-
-
-

(주)코드브릿지엑스

-

www.codebridge-x.com

-
-
-

뒷면에서 상세 기능을 확인하세요 ▶

-
-
-
- - \ No newline at end of file diff --git a/sam/docs/brochure/v8/convert-1page.cjs b/sam/docs/brochure/v8/convert-1page.cjs deleted file mode 100644 index aa5af35..0000000 --- a/sam/docs/brochure/v8/convert-1page.cjs +++ /dev/null @@ -1,27 +0,0 @@ -const path = require('path'); -module.paths.unshift(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/node_modules')); - -const PptxGenJS = require('pptxgenjs'); -const html2pptx = require(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/html2pptx.js')); - -async function main() { - const pres = new PptxGenJS(); - - pres.defineLayout({ name: 'PORTRAIT_9x16', width: 5.625, height: 10 }); - pres.layout = 'PORTRAIT_9x16'; - - const htmlFile = path.join(__dirname, 'slides', 'brochure-dashboard-1page.html'); - console.log('Converting CEO Dashboard v8 (Two-Tone Split) 1-page brochure...'); - - try { - await html2pptx(htmlFile, pres); - } catch (err) { - console.error(`Error: ${err.message}`); - } - - const outputPath = path.join(__dirname, 'sam-brochure-v8-dashboard-1page.pptx'); - await pres.writeFile({ fileName: outputPath }); - console.log(`\nPPTX created: ${outputPath}`); -} - -main().catch(console.error); diff --git a/sam/docs/brochure/v8/convert-2page.cjs b/sam/docs/brochure/v8/convert-2page.cjs deleted file mode 100644 index 1b887e1..0000000 --- a/sam/docs/brochure/v8/convert-2page.cjs +++ /dev/null @@ -1,31 +0,0 @@ -const path = require('path'); -module.paths.unshift(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/node_modules')); - -const PptxGenJS = require('pptxgenjs'); -const html2pptx = require(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/html2pptx.js')); - -async function main() { - const pres = new PptxGenJS(); - - pres.defineLayout({ name: 'PORTRAIT_9x16', width: 5.625, height: 10 }); - pres.layout = 'PORTRAIT_9x16'; - - const slidesDir = path.join(__dirname, 'slides'); - const slides = ['brochure-dashboard-front.html', 'brochure-dashboard-back.html']; - - for (const file of slides) { - const htmlFile = path.join(slidesDir, file); - console.log(`Converting ${file} ...`); - try { - await html2pptx(htmlFile, pres); - } catch (err) { - console.error(`Error on ${file}: ${err.message}`); - } - } - - const outputPath = path.join(__dirname, 'sam-brochure-v8-dashboard-2page.pptx'); - await pres.writeFile({ fileName: outputPath }); - console.log(`\nPPTX created: ${outputPath}`); -} - -main().catch(console.error); diff --git a/sam/docs/brochure/v8/sam-brochure-v8-dashboard-1page.pptx b/sam/docs/brochure/v8/sam-brochure-v8-dashboard-1page.pptx deleted file mode 100644 index 4a2c33d..0000000 Binary files a/sam/docs/brochure/v8/sam-brochure-v8-dashboard-1page.pptx and /dev/null differ diff --git a/sam/docs/brochure/v8/sam-brochure-v8-dashboard-2page.pptx b/sam/docs/brochure/v8/sam-brochure-v8-dashboard-2page.pptx deleted file mode 100644 index ade5f05..0000000 Binary files a/sam/docs/brochure/v8/sam-brochure-v8-dashboard-2page.pptx and /dev/null differ diff --git a/sam/docs/brochure/v8/slides/brochure-dashboard-1page.html b/sam/docs/brochure/v8/slides/brochure-dashboard-1page.html deleted file mode 100644 index fbf62ea..0000000 --- a/sam/docs/brochure/v8/slides/brochure-dashboard-1page.html +++ /dev/null @@ -1,238 +0,0 @@ - - - - - - - - -
- -
- -
-
-

EXECUTIVE DASHBOARD

-
-
- - -
-

대표님, 우리 회사

-

지금 어떤 상태인가요?

-

보고 대기 없이, 로그인 한 번이면 전사 현황이 한눈에.

-
- - -
-
- - - - - -

5.2억

-

▲ 15.3%

-

월 매출

-
-
- - - - -

127건

-

▲ 8건

-

누적 수주

-
-
- - - - -

96%

-

목표 달성

-

납기 준수율

-
-
- - - - - -

5건

-

즉시 처리

-

승인 대기

-
-
-
- - -
- - -
-

대표님이 얻는 것

-
-
-

즉시 현황 파악

-

로그인 3초면

-

전사 현황 확인

-
-
-

데이터로 판단

-

감이 아닌 숫자로

-

KPI/팀 성과 비교

-
-
-

모바일 승인

-

이동중에도 즉시

-

결재/승인 처리

-
-
-
- - -
- - -
-

대시보드 핵심 기능

-
-
- - - - - -

실시간 KPI 카드

-

매출, 수주, 납기율, 승인

-
-
- - - - - - - - -

조직 실적 트리

-

계층별 팀/개인 실적

-
-
- - - - -

역할별 수당 현황

-

판매자/관리자/협업자

-
-
- - - - ! - -

승인 대기 알림

-

미처리 빨간 뱃지

-
-
- - - - -

기간별 트렌드

-

당월/분기/연간 추이

-
-
- - - - - - - -

수익 시뮬레이터

-

가상 시나리오 계산

-
-
- - - - - - - - -

모바일 대응

-

스마트폰 KPI/승인

-
-
-
- - -
- - -
-

투자 비용

-
-
-

기본 패키지

-

2,000만원

-

+ 월 50만원 (유지보수)

-
-
-

추가 옵션 (선택)

-
-

생산공정 관리

-

+500만원

-
-
-

품질관리(인정검사)

-

+2,000만원

-
-
-

AI 견적 자동 생성

-

월 10~20만원

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

무료 데모를 신청하세요

-

대표님 전용 대시보드를 직접 체험

-
-
-
-

contact@codebridge-x.com

-

www.codebridge-x.com

-
-
-
- - -
-

(주)코드브릿지엑스 | SAM - Smart Automation Management

-
-
- - \ No newline at end of file diff --git a/sam/docs/brochure/v8/slides/brochure-dashboard-back.html b/sam/docs/brochure/v8/slides/brochure-dashboard-back.html deleted file mode 100644 index 28747b2..0000000 --- a/sam/docs/brochure/v8/slides/brochure-dashboard-back.html +++ /dev/null @@ -1,320 +0,0 @@ - - - - - - - - -
- -
-
-

FEATURES & PRICING

-
-
- - -
-

대시보드 핵심 기능

-
- -
- - - - - -
-

실시간 KPI 카드

-
-

매출, 수주, 납기율, 승인 대기

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

조직 실적 트리

-
-

계층별 팀/개인 실적 펼쳐보기

-
- -
- - - - -
-

역할별 수당 현황

-
-

판매자/관리자/협업자 배분 확인

-
- -
- - - - ! - - -
-

승인 대기 알림

-
-

가입/지급 미처리 빨간 뱃지

-
- -
- - - - -
-

기간별 트렌드

-
-

당월/분기/연간 추이 차트

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

수익 시뮬레이터

-
-

가상 시나리오 수당/마진 계산

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

모바일 대응

-
-

스마트폰으로 KPI 확인/승인

-
-
-
- - -
- - -
-

역할별 맞춤 화면

-
- -
- - - - - -

CEO

-

전사 KPI 총괄

-
- -
- - - - - - -

관리자

-

팀 실적 관리

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

운영자

-

인력/승인 관리

-
- -
- - - - - - - -

영업자

-

내 실적 조회

-
-
-
- - -
- - -
-

투자 비용

-
- -
-
-
- - - - -

대시보드 포함 기본 패키지

-
-

2,000만원

-

+ 월 50만원 (유지보수)

-
-
-

CEO 대시보드 + 견적/수주 + 생산

-

인사/회계 무료 포함

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

추가 옵션 (선택)

-
-
-
-

생산공정 관리

-

+500만원

-
-
-

품질관리(인정검사)

-

+2,000만원

-
-
-

AI 견적 자동 생성

-

월 10~20만원

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

도입 프로세스

-
-
- - - - - -

1~2주

-

현장 인터뷰

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

2~4주

-

맞춤 개발

-
- - - -
- - - - - -

1~2주

-

데이터 이관

-
- - - -
- - - - -

1~2주

-

교육/안정화

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

무료 데모를 신청하세요

-

대표님 전용 대시보드를 직접 체험

-
-
-
-

contact@codebridge-x.com

-

www.codebridge-x.com

-
-
-
- - -
-

(주)코드브릿지엑스 | SAM - Smart Automation Management

-
- - \ No newline at end of file diff --git a/sam/docs/brochure/v8/slides/brochure-dashboard-front.html b/sam/docs/brochure/v8/slides/brochure-dashboard-front.html deleted file mode 100644 index 10ecdb0..0000000 --- a/sam/docs/brochure/v8/slides/brochure-dashboard-front.html +++ /dev/null @@ -1,281 +0,0 @@ - - - - - - - - -
- -
- -
-
-

EXECUTIVE DASHBOARD

-
-
- - -
-

대표님, 우리 회사

-

지금 어떤 상태인가요?

-

매출, 수주, 조직 실적, 승인 대기

-

더 이상 보고를 기다리지 마세요.

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

5.2억

-

▲ 15.3%

-

월 매출

-
- -
- - - - -

127건

-

▲ 8건

-

누적 수주

-
- -
- - - - -

96%

-

목표 달성

-

납기 준수율

-
- -
- - - - - -

5건

-

즉시 처리

-

승인 대기

-
-
-
- - -
- - -
-

대표님이 얻는 것

-
- -
- - - - - - -

즉시 현황 파악

-

로그인 3초면

-

전사 현황 확인

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

데이터로 판단

-

감이 아닌 숫자로

-

KPI/팀 성과 비교

-
- -
- - - - - - -

모바일 승인

-

이동중에도 즉시

-

결재/승인 처리

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

BEFORE

-
-

매출? → 보고 대기 1~2일

-

수주? → Excel 취합 반나절

-

승인? → 서류 찾기 30분

-

실적? → 각 팀장 개별 보고

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

AFTER (SAM)

-
-

로그인 3초 → 전사 현황

-

클릭 한 번 → 실시간 수주

-

뱃지 터치 → 즉시 승인

-

트리 펼침 → 전 조직 한눈에

-
-
- - -
- - -
-

대시보드 핵심 기능

-
-
-
- - - - - -

실시간 매출/수주 KPI

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

조직 계층별 실적 트리

-
-
-
-
- - - - -

역할별 수당 현황

-
-
- - - - 5 - - -

미승인 실시간 알림

-
-
-
-
- - - - -

기간별 트렌드 분석

-
-
- - - - - - - - -

수익 시뮬레이터

-
-
-
-
- - -
-
- -

클라우드 기반

-
-
- -

PC + 모바일

-
-
- -

역할별 권한

-
-
- -

데이터 암호화

-
-
- - -
-
-
-

(주)코드브릿지엑스

-

www.codebridge-x.com

-
-
-

뒷면에서 상세 기능을 확인하세요 ▶

-
-
-
-
- - \ No newline at end of file diff --git a/sam/docs/brochure/v9/convert-1page.cjs b/sam/docs/brochure/v9/convert-1page.cjs deleted file mode 100644 index 9846c6f..0000000 --- a/sam/docs/brochure/v9/convert-1page.cjs +++ /dev/null @@ -1,27 +0,0 @@ -const path = require('path'); -module.paths.unshift(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/node_modules')); - -const PptxGenJS = require('pptxgenjs'); -const html2pptx = require(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/html2pptx.js')); - -async function main() { - const pres = new PptxGenJS(); - - pres.defineLayout({ name: 'PORTRAIT_9x16', width: 5.625, height: 10 }); - pres.layout = 'PORTRAIT_9x16'; - - const htmlFile = path.join(__dirname, 'slides', 'brochure-dashboard-1page.html'); - console.log('Converting CEO Dashboard v9 (Minimal White + Indigo) 1-page brochure...'); - - try { - await html2pptx(htmlFile, pres); - } catch (err) { - console.error(`Error: ${err.message}`); - } - - const outputPath = path.join(__dirname, 'sam-brochure-v9-dashboard-1page.pptx'); - await pres.writeFile({ fileName: outputPath }); - console.log(`\nPPTX created: ${outputPath}`); -} - -main().catch(console.error); diff --git a/sam/docs/brochure/v9/convert-2page.cjs b/sam/docs/brochure/v9/convert-2page.cjs deleted file mode 100644 index a635175..0000000 --- a/sam/docs/brochure/v9/convert-2page.cjs +++ /dev/null @@ -1,31 +0,0 @@ -const path = require('path'); -module.paths.unshift(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/node_modules')); - -const PptxGenJS = require('pptxgenjs'); -const html2pptx = require(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/html2pptx.js')); - -async function main() { - const pres = new PptxGenJS(); - - pres.defineLayout({ name: 'PORTRAIT_9x16', width: 5.625, height: 10 }); - pres.layout = 'PORTRAIT_9x16'; - - const slidesDir = path.join(__dirname, 'slides'); - const slides = ['brochure-dashboard-front.html', 'brochure-dashboard-back.html']; - - for (const file of slides) { - const htmlFile = path.join(slidesDir, file); - console.log(`Converting ${file} ...`); - try { - await html2pptx(htmlFile, pres); - } catch (err) { - console.error(`Error on ${file}: ${err.message}`); - } - } - - const outputPath = path.join(__dirname, 'sam-brochure-v9-dashboard-2page.pptx'); - await pres.writeFile({ fileName: outputPath }); - console.log(`\nPPTX created: ${outputPath}`); -} - -main().catch(console.error); diff --git a/sam/docs/brochure/v9/sam-brochure-v9-dashboard-1page.pptx b/sam/docs/brochure/v9/sam-brochure-v9-dashboard-1page.pptx deleted file mode 100644 index 9a39ae4..0000000 Binary files a/sam/docs/brochure/v9/sam-brochure-v9-dashboard-1page.pptx and /dev/null differ diff --git a/sam/docs/brochure/v9/sam-brochure-v9-dashboard-2page.pptx b/sam/docs/brochure/v9/sam-brochure-v9-dashboard-2page.pptx deleted file mode 100644 index 3fd20cc..0000000 Binary files a/sam/docs/brochure/v9/sam-brochure-v9-dashboard-2page.pptx and /dev/null differ diff --git a/sam/docs/brochure/v9/slides/brochure-dashboard-1page.html b/sam/docs/brochure/v9/slides/brochure-dashboard-1page.html deleted file mode 100644 index d228d07..0000000 --- a/sam/docs/brochure/v9/slides/brochure-dashboard-1page.html +++ /dev/null @@ -1,266 +0,0 @@ - - - - - - - - -
- - -
- -
-

v9

-
- - -
-

EXECUTIVE DASHBOARD

-

대표님, 우리 회사

-

지금 어떤 상태인가요?

-

보고 대기 없이, 로그인 한 번이면 전사 현황이 한눈에.

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

SAM CEO Dashboard

-
- -
-
-

5.2억

-

+15.3%

-

월 매출

-
-
-

127건

-

+8건

-

누적 수주

-
-
-

96%

-

목표 달성

-

납기 준수율

-
-
-

5건

-

즉시 처리

-

승인 대기

-
-
- -
-
-

월별 매출 추이

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

영업1팀

-
-
-
-

영업2팀

-
-
-
-

생산팀

-
-
-
-

품질팀

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

즉시 현황 파악

-

3초면 전사 현황

-
-
- - - - - -

데이터로 판단

-

KPI/팀 성과 비교

-
-
- - - - -

모바일 승인

-

즉시 결재 처리

-
-
- - -
- - -
-

핵심 기능

-
-
-
-

실시간 KPI 카드

-
-
-
-

조직 실적 트리

-
-
-
-

역할별 수당 현황

-
-
-
-

승인 대기 알림

-
-
-
-

기간별 트렌드

-
-
-
-

수익 시뮬레이터

-
-
-
-

모바일 대응

-
-
-
- - -
- - -
-

역할별 맞춤 화면

-
-
-

CEO

-

전사 KPI

-
-
-

관리자

-

팀 실적

-
-
-

운영자

-

인력/승인

-
-
-

영업자

-

내 실적

-
-
-
- - -
- - -
-

투자 비용

-
-

2,000만원

-

+ 월 50만원 (유지보수)

-
-

CEO 대시보드 + 견적/수주 + 생산 + 인사/회계 포함

-
- - -
-

도입 프로세스

-
-
-

01

-

현장 인터뷰

-
- - - -
-

02

-

맞춤 개발

-
- - - -
-

03

-

데이터 이관

-
- - - -
-

04

-

교육/안정화

-
-
-
- - -
-
-
-

무료 데모를 신청하세요

-

대표님 전용 대시보드를 직접 체험

-
-
-

contact@codebridge-x.com

-

www.codebridge-x.com

-
-
-
-
-

(주)코드브릿지엑스

-
- - \ No newline at end of file diff --git a/sam/docs/brochure/v9/slides/brochure-dashboard-back.html b/sam/docs/brochure/v9/slides/brochure-dashboard-back.html deleted file mode 100644 index 46e438c..0000000 --- a/sam/docs/brochure/v9/slides/brochure-dashboard-back.html +++ /dev/null @@ -1,229 +0,0 @@ - - - - - - - - -
- - -
- -
-

FEATURES & PRICING

-
- - -
-

대시보드 핵심 기능

-
- -
-
-

실시간 KPI 카드

-

매출, 수주, 납기율, 승인 대기

-
- -
-
-

조직 실적 트리

-

계층별 팀/개인 실적 펼쳐보기

-
- -
-
-

역할별 수당 현황

-

판매자/관리자/협업자 배분 확인

-
- -
-
-

승인 대기 알림

-

가입/지급 미처리 빨간 뱃지

-
- -
-
-

기간별 트렌드

-

당월/분기/연간 추이 차트

-
- -
-
-

수익 시뮬레이터

-

가상 시나리오 수당/마진 계산

-
- -
-
-

모바일 대응

-

스마트폰으로 KPI 확인/승인

-
-
-
- - -
- - -
-

역할별 맞춤 화면

-
- -
- - - - - -

CEO

-

전사 KPI 총괄

-
- -
- - - - - - -

관리자

-

팀 실적 관리

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

운영자

-

인력/승인 관리

-
- -
- - - - - - - -

영업자

-

내 실적 조회

-
-
-
- - -
- - -
-

투자 비용

-
- -
-

대시보드 포함 기본 패키지

-

2,000만원

-

+ 월 50만원 (유지보수)

-
-

CEO 대시보드 + 견적/수주 + 생산

-

인사/회계 무료 포함

-
-
- -
-

추가 옵션 (선택)

-
-
-

생산공정 관리

-

+500만원

-
-
-

품질관리(인정검사)

-

+2,000만원

-
-
-

AI 견적 자동 생성

-

월 10~20만원

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

도입 프로세스

-
-
-

01

-

현장 인터뷰

-

1~2주

-
- - - -
-

02

-

맞춤 개발

-

2~4주

-
- - - -
-

03

-

데이터 이관

-

1~2주

-
- - - -
-

04

-

교육/안정화

-

1~2주

-
-
-
- - -
-
-
-

무료 데모를 신청하세요

-

대표님 전용 대시보드를 직접 체험

-
-
-

contact@codebridge-x.com

-

www.codebridge-x.com

-
-
-
- - -
-

(주)코드브릿지엑스

-
- - \ No newline at end of file diff --git a/sam/docs/brochure/v9/slides/brochure-dashboard-front.html b/sam/docs/brochure/v9/slides/brochure-dashboard-front.html deleted file mode 100644 index dc52623..0000000 --- a/sam/docs/brochure/v9/slides/brochure-dashboard-front.html +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - -
- - -
- -
-

v9

-
- - -
-

EXECUTIVE DASHBOARD

-

대표님, 우리 회사

-

지금 어떤 상태인가요?

-

매출, 수주, 조직 실적, 승인 대기

-

더 이상 보고를 기다리지 마세요.

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

SAM CEO Dashboard

-
- -
- -
- - - - - -

5.2억

-

+15.3%

-

월 매출

-
- -
- - - - -

127건

-

+8건

-

누적 수주

-
- -
- - - - -

96%

-

목표 달성

-

납기 준수율

-
- -
- - - - - -

5건

-

즉시 처리

-

승인 대기

-
-
- -
- -
-

월별 매출 추이

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

영업1팀

-
-
-
-

영업2팀

-
-
-
-

생산팀

-
-
-
-

품질팀

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

즉시 현황 파악

-

로그인 3초면

-

전사 현황 확인

-
- -
- - - - - -

데이터로 판단

-

감이 아닌 숫자로

-

KPI/팀 성과 비교

-
- -
- - - - -

모바일 승인

-

이동중에도 즉시

-

결재/승인 처리

-
-
- - -
-
-

(주)코드브릿지엑스

-

www.codebridge-x.com

-
-

뒷면에서 상세 기능을 확인하세요

-
- - \ No newline at end of file diff --git a/sam/docs/changes/20260303_gemini_model_upgrade.md b/sam/docs/changes/20260303_gemini_model_upgrade.md deleted file mode 100644 index e3806fc..0000000 --- a/sam/docs/changes/20260303_gemini_model_upgrade.md +++ /dev/null @@ -1,119 +0,0 @@ -# Gemini 모델 업그레이드: 2.0-flash → 2.5-flash - -**날짜:** 2026-03-03 -**작업자:** Claude Code - ---- - -## 변경 개요 - -Google이 2026년 6월 1일부로 Gemini 2.0 Flash 모델 서비스를 종료한다는 통보를 받아, SAM 시스템 전체의 Gemini 모델을 `gemini-2.0-flash` → `gemini-2.5-flash`로 마이그레이션했다. - ---- - -## 변경 사유 - -- Google의 공식 메일 통보: Gemini 2.0 Flash / 2.0 Flash-Lite → 2026-06-01 강제 종료 -- 마이그레이션 경로: `gemini-2.0-flash` → `gemini-2.5-flash` -- API 키, Base URL 변경 없음 (모델명만 변경) - ---- - -## 수정된 파일 - -### API 프로젝트 (`/home/aweso/sam/api`) - -| 파일 | 변경 내용 | -|------|----------| -| `.env` | `GEMINI_MODEL=gemini-2.0-flash` → `gemini-2.5-flash` | -| `config/services.php` | fallback 기본값 `gemini-2.0-flash` → `gemini-2.5-flash` | -| `app/Services/AiReportService.php` | fallback 기본값 변경 | - -### MNG 프로젝트 (`/home/aweso/sam/mng`) - -| 파일 | 변경 내용 | -|------|----------| -| `.env` | `GEMINI_MODEL=gemini-2.0-flash` → `gemini-2.5-flash` | -| `config/services.php` | fallback 기본값 변경 | -| `app/Models/System/AiConfig.php` | `DEFAULT_MODELS['gemini']` 상수 + `getActiveGemini()` fallback 변경 | -| `app/Services/NotionService.php` | fallback 기본값 변경 | -| `resources/views/system/ai-config/index.blade.php` | UI placeholder, 기본값, JS defaultModels 변경 | -| `resources/views/google-cloud/ai-guide/index.blade.php` | 서비스 현황 테이블 모델명 7곳 변경 | -| `resources/views/academy/env-management.blade.php` | 환경변수 예시 테이블 변경 | - -### 문서 (`/home/aweso/sam/docs`) - -| 파일 | 변경 내용 | -|------|----------| -| `guides/ai-config-settings.md` | 기본 모델명 업데이트, 최종 업데이트 날짜 변경 | -| `guides/ai-management.md` | **신규** — AI 관리 종합 가이드 (아키텍처, 버전 이력, 온보딩) | -| `guides/ai-model-update-workflow.md` | **신규** — 모델 업데이트 표준 절차 (7단계 워크플로우) | -| `changes/20260303_gemini_model_upgrade.md` | **신규** — 이 변경 이력 문서 | - -### 수정하지 않은 파일 (의도적) - -| 파일 | 이유 | -|------|------| -| `api/database/migrations/2026_01_27_*.php` | 이미 실행된 마이그레이션 — 변경 시 DB 무결성 문제 | -| `api/database/migrations/2026_02_07_*.php` | 동일 | -| `api/database/migrations/2026_02_09_*.php` | 동일 | -| `mng/views/google-cloud/cloud-api-pricing/index.blade.php` | `2.0 → 2.5` 마이그레이션 안내 UI — 이전 모델명이 의도적 잔존 | - ---- - -## 서버 .env 수정 필요 (배포 후) - -| 환경 | 파일 | 변수 | 담당 | -|------|------|------|------| -| 개발서버 | `/home/webservice/api/.env` | `GEMINI_MODEL=gemini-2.5-flash` | SSH 접속 수정 | -| 개발서버 | `/home/webservice/mng/.env` | `GEMINI_MODEL=gemini-2.5-flash` | SSH 접속 수정 | -| 운영서버 | `/home/webservice/api/.env` | `GEMINI_MODEL=gemini-2.5-flash` | 개발팀장 직접 | -| 운영서버 | `/home/webservice/mng/.env` | `GEMINI_MODEL=gemini-2.5-flash` | 개발팀장 직접 | - -수정 후 반드시 실행: -```bash -php artisan config:clear -``` - ---- - -## DB 단가 설정 필요 - -MNG `/system/ai-token-usage` → 단가 설정에서: -- 기존 `gemini-2.0-flash` 단가 → 비활성화 -- 신규 `gemini-2.5-flash` 단가 추가: - - `input_price_per_million`: 0.15 - - `output_price_per_million`: 0.60 - - `exchange_rate`: 현재 환율 - ---- - -## 테스트 체크리스트 - -- [x] 로컬 .env 수정 완료 -- [x] 코드 fallback 전체 변경 완료 -- [ ] 로컬 연결 테스트 (MNG `/system/ai-config`) -- [ ] 개발서버 .env 수정 + config:clear -- [ ] 개발서버 연결 테스트 -- [ ] 운영서버 .env 수정 + config:clear -- [ ] DB 단가 설정 (gemini-2.5-flash) -- [ ] 토큰 사용량 로그 확인 (새 모델명) - ---- - -## 롤백 절차 - -문제 발생 시 `.env`만 되돌리면 즉시 복구: -```bash -# 모든 환경의 .env에서 -GEMINI_MODEL=gemini-2.0-flash -php artisan config:clear -``` - ---- - -## 관련 문서 - -- [AI 관리 종합 가이드](../guides/ai-management.md) -- [모델 업데이트 워크플로우](../guides/ai-model-update-workflow.md) -- [AI 설정 기술문서](../guides/ai-config-settings.md) diff --git a/sam/docs/changes/20260304_eaccount_infinite_loop_fix.md b/sam/docs/changes/20260304_eaccount_infinite_loop_fix.md deleted file mode 100644 index e754f9f..0000000 --- a/sam/docs/changes/20260304_eaccount_infinite_loop_fix.md +++ /dev/null @@ -1,165 +0,0 @@ -# 계좌 입출금내역 부분 월 조회 시 무한루프 크래시 수정 - -**날짜:** 2026-03-04 -**작업자:** Claude Code - ---- - -## 변경 개요 - -계좌 입출금내역 페이지에서 **날짜를 수동 입력**하여 조회 시 500 에러가 발생하는 문제를 수정했다. -편의 버튼(이번달, 지난달 등)은 항상 전체 월(1일~말일)을 사용하여 문제가 없었으나, -수동으로 날짜를 입력하면 **부분 월**(예: 12/01~12/18)이 되어 무한루프가 발생했다. - ---- - -## 근본 원인 - -### `splitDateRangeMonthly()` 함수의 cursor 이동 버그 - -긴 기간 조회 시 바로빌 SOAP API의 한계로 인해 기간을 **월별 청크**로 분할하는 함수에서, -endDate가 **월 중간**일 때 cursor가 **같은 달 1일로 되돌아가** 무한루프가 발생했다. - -```php -// ❌ 버그 코드 — endDate가 월 중간이면 무한루프 -$cursor = $chunkEnd->copy()->addDay()->startOfMonth(); - -// 예시: endDate = 20251218 -// chunkEnd = 20251218 -// → addDay() = 20251219 -// → startOfMonth() = 20251201 ← 같은 달 1일로 되돌아감! -// → while($cursor <= $end) 조건 여전히 true → 무한 반복 -``` - -```php -// ✅ 수정 코드 — chunkStart 기준으로 다음 월로 이동 -$cursor = $chunkStart->copy()->addMonth()->startOfMonth(); - -// 예시: startDate = 20251201 -// chunkStart = 20251201 -// → addMonth() = 20260101 -// → startOfMonth() = 20260101 ← 다음 달로 정상 이동 -// → while($cursor <= $end) 조건 false → 루프 종료 -``` - -### 재현 조건 - -| 조건 | 결과 | -|------|------| -| 전체 월 (12/01~12/31) | 정상 — `addDay()` = 01/01 → `startOfMonth()` = 01/01 | -| 부분 월 (12/01~12/18) | **무한루프** — `addDay()` = 12/19 → `startOfMonth()` = 12/01 | -| 다중 월 (12/01~02/18) | **무한루프** — 마지막 월이 부분 월이면 동일 증상 | - -### 증상 - -- PHP 프로세스가 메모리 한도(256M/512M)에 도달하여 **Fatal Error로 크래시** -- Laravel 로그에 에러 기록 없음 (try-catch 밖에서 프로세스가 종료) -- 프론트엔드에 `서버 응답 오류 (500):` (빈 응답 본문) - ---- - -## 수정된 파일 - -| 파일 | 변경 내용 | -|------|----------| -| `app/Http/Controllers/Barobill/EaccountController.php` | `splitDateRangeMonthly()` cursor 이동 로직 수정 | - ---- - -## 검증 결과 - -tinker에서 수정 전후 비교 테스트: - -``` -=== 수정 전 (버그): 20251201~20251218 === -→ 같은 청크 무한 반복 (10회 제한으로 강제 중단) - -=== 수정 후: 20251201~20251218 === -→ [{start: 20251201, end: 20251218}] ← 1개 청크, 정상 - -=== 수정 후: 20251201~20260218 (다중 월) === -→ [{20251201~20251231}, {20260101~20260131}, {20260201~20260218}] ← 3개 청크, 정상 - -=== 수정 후: 20251215~20251231 === -→ [{start: 20251215, end: 20251231}] ← 1개 청크, 정상 -``` - ---- - -## 동일 패턴 코드베이스 점검 결과 - -`sam/mng` 전체를 검색하여 유사 패턴을 점검했다: - -| 파일 | 함수 | 패턴 | 위험도 | -|------|------|------|--------| -| `EaccountController.php` | `splitDateRangeMonthly()` | 월별 청크 분할 | ✅ 수정 완료 | -| `DashboardStatService.php` | `generateDateRange()` | `addDay()` 단순 증가 | 안전 | -| `InspectionCycle.php` | `getHolidayDates()` | `addDay()` 단순 증가 | 안전 | -| `CorporateCardController.php` | `getNextBusinessDay()` | `addDay()` 단순 증가 | 안전 | -| `PartitionManagementService.php` | `addPartitions()` | `for` 루프 (고정 횟수) | 안전 | - -> **결론**: `EaccountController` 외에 동일 버그 패턴 없음. -> 다른 코드들은 모두 `addDay()` 단순 증가 패턴을 사용하여 무한루프 위험 없음. - ---- - -## 교훈 및 방지 규칙 - -### R1. 날짜 cursor 이동 시 `chunkEnd` 기반 이동 금지 - -```php -// ❌ 위험: chunkEnd가 월 중간이면 startOfMonth()가 같은 달로 되돌림 -$cursor = $chunkEnd->copy()->addDay()->startOfMonth(); - -// ✅ 안전: chunkStart 기준으로 항상 다음 월로 이동 -$cursor = $chunkStart->copy()->addMonth()->startOfMonth(); -``` - -### R2. 날짜 루프에 안전장치(max iterations) 추가 권장 - -```php -$maxIterations = 120; // 10년 = 120개월 -$iterations = 0; - -while ($cursor->lte($end) && $iterations < $maxIterations) { - // ... 청크 처리 ... - $iterations++; -} - -if ($iterations >= $maxIterations) { - Log::error('날짜 분할 루프 안전장치 작동', compact('startDate', 'endDate')); -} -``` - -### R3. 부분 월 테스트 필수 - -날짜 범위를 분할하는 코드 작성/수정 시 반드시 다음 케이스를 테스트: - -- [ ] 전체 월 (01일~말일) -- [ ] 부분 월 — 시작 (01일~중간) -- [ ] 부분 월 — 끝 (중간~말일) -- [ ] 다중 월 (마지막 월이 부분 월) -- [ ] 같은 날 (시작일 = 종료일) - ---- - -## 부수 개선 사항 - -이 문제 조사 과정에서 추가로 발견/수정된 항목: - -| 항목 | 내용 | -|------|------| -| WSDL 캐싱 | `WSDL_CACHE_NONE` → `WSDL_CACHE_BOTH` (4개 바로빌 컨트롤러 전체) | -| 소켓 타임아웃 | `default_socket_timeout` 60→120초 연장 | -| Shutdown handler | PHP Fatal Error 감지 시 Laravel 로그에 기록 | -| SOAP 호출 로깅 | 호출 시작/완료 시간 + 소요시간(ms) 기록 | - ---- - -## 관련 문서 - -- `app/Http/Controllers/Barobill/EaccountController.php` — 바로빌 계좌 입출금내역 - ---- - -**최종 업데이트**: 2026-03-04 diff --git a/sam/docs/contracts/CHANGELOG.md b/sam/docs/contracts/CHANGELOG.md deleted file mode 100644 index cfd3346..0000000 --- a/sam/docs/contracts/CHANGELOG.md +++ /dev/null @@ -1,42 +0,0 @@ -# 계약서 개정이력 - -> **작성일**: 2026-02-22 -> **관리 대상**: 전자계약 DOCX 4종 - ---- - -## v4.1 (2026-02-22) - -**작성자**: 개발팀 -**대상**: 고객사 서비스 이용계약서 - -- 제4조에 사용량 기반 추가 과금 조항(4.5) 추가 - - 파일 저장 공간: 기본 100GB 초과 시 100GB당 100,000원/월 - - AI 토큰: 월 100만 토큰 기본, 초과 시 1,000토큰 단위 실비 과금 -- 제4조에 바로빌 부가 서비스 요금 조항(4.6) 추가 - - 계좌조회, 카드내역, 세금계산서 발행 요금 명시 - - 홈택스 매입/매출 조회는 회사 부담 명시 - ---- - -## v4.0 (2026-02-22) - -**작성자**: 개발팀 - -- 계약서 버전 관리 시스템 도입 -- DOCX → Markdown 미러링 체계 구축 -- 4개 전자계약 문서에 개정이력 테이블 삽입 -- 동기화 검증 스크립트 구축 - -### 대상 문서 - -| 파일 | 문서명 | -|------|--------| -| `01_고객_서비스이용계약서_v4_0_전자서명용.docx` | 고객사 서비스 이용계약서 | -| `비밀유지서약서.docx` | 비밀유지서약서 (NDA) | -| `영업파트너 위촉계약서.docx` | 영업파트너 위촉계약서 | -| `영업파트너 위촉계약서(단체용).docx` | 영업파트너 위촉계약서 (단체용) | - ---- - -**최종 업데이트**: 2026-02-22 (v4.1) diff --git a/sam/docs/contracts/docx/01_고객_서비스이용계약서_v4_0_전자서명용.docx b/sam/docs/contracts/docx/01_고객_서비스이용계약서_v4_0_전자서명용.docx deleted file mode 100644 index de1e3ed..0000000 Binary files a/sam/docs/contracts/docx/01_고객_서비스이용계약서_v4_0_전자서명용.docx and /dev/null differ diff --git a/sam/docs/contracts/docx/비밀유지서약서.docx b/sam/docs/contracts/docx/비밀유지서약서.docx deleted file mode 100755 index 635b42c..0000000 Binary files a/sam/docs/contracts/docx/비밀유지서약서.docx and /dev/null differ diff --git a/sam/docs/contracts/docx/영업파트너 위촉계약서(단체용).docx b/sam/docs/contracts/docx/영업파트너 위촉계약서(단체용).docx deleted file mode 100755 index 1332c74..0000000 Binary files a/sam/docs/contracts/docx/영업파트너 위촉계약서(단체용).docx and /dev/null differ diff --git a/sam/docs/contracts/docx/영업파트너 위촉계약서.docx b/sam/docs/contracts/docx/영업파트너 위촉계약서.docx deleted file mode 100755 index 9e849b5..0000000 Binary files a/sam/docs/contracts/docx/영업파트너 위촉계약서.docx and /dev/null differ diff --git a/sam/docs/contracts/markdown/01-service-agreement.md b/sam/docs/contracts/markdown/01-service-agreement.md deleted file mode 100644 index 51c694c..0000000 --- a/sam/docs/contracts/markdown/01-service-agreement.md +++ /dev/null @@ -1,458 +0,0 @@ ---- -title: "고객사 서비스 이용계약서" -version: "v4.2" -date: "2026-02-24" -docx_file: "01_고객_서비스이용계약서_v4_0_전자서명용.docx" ---- - -# 고객사 서비스 이용계약서 - -Customer Service Agreement - -계약번호: -계약일: - -본 계약은 주식회사 코드브릿지엑스(이하 “회사”)와 간에 SAM 서비스 제공과 관련하여 다음과 같이 계약을 체결합니다. - -## 제1조 (계약의 목적) - -본 계약은 회사가 고객에게 SAM(Smart MES/ERP Solution) 서비스를 제공함에 있어 필요한 사항을 규정하고, 양측의 권리와 의무를 명확히 함을 목적으로 합니다. - -## 제2조 (용어의 정의) - -- **서비스**: 회사가 제공하는 SAM 클라우드 기반 MES/ERP 솔루션 -- **SaaS**: Software as a Service (서비스형 소프트웨어) -- **서비스 게시**: 개발 완료 후 고객이 서비스에 접근 가능하도록 제공하는 것 -- **액세스 제공**: 고객에게 서비스 사용 권한을 부여하는 것 -- **검수 기간**: 서비스 게시 전 고객이 완성도를 확인하는 기간 (최대 1개월) -- **하자**: 계약서에 명시된 기능의 오류, 미구현, 성능 미달 등 -- **하자담보 책임**: 서비스 게시 후 1년간 하자를 무상으로 수정하는 의무 - -## 제3조 (서비스 내용) - -### 3.1 서비스 범위 - -회사는 다음의 서비스를 제공합니다: -- **맞춤형 개발**: - - 고객 요구사항에 맞춘 SAM 시스템 개발 - - 개발 범위: [별첨 기획서 참조] - - 개발 기간: 계약일로부터 [ 3 ]개월 -- **클라우드 제공** (SaaS): - - 연중무휴 24시간 접근 가능 - - 자동 백업 및 보안 -- **기술 지원**: - - 고객센터 운영 (평일 09:00~18:00) - - 이메일 지원 (24시간) - - 긴급 장애 대응 -- **하자담보 책임** (1년): - - 서비스 게시일로부터 1년간 무상 수정 - - 버그, 미구현 기능, 성능 개선 등 - -### 3.2 제공 방식 - -- 회사는 서비스를 **SaaS 방식**으로 제공합니다. -- 고객은 서비스에 대한 **사용 권한**만을 부여받으며, 소유권은 회사에 귀속됩니다. - - 소스코드는 제공되지 않습니다. - -## 제4조 (비용 및 납부) - -### 4.1 개발비 - -| 구분 | 금액 (부가세 별도) | 지급 시기 | 비고 | -| --- | --- | --- | --- | -| 1차 개발비 | 총 개발비의 50% | 계약 체결 시 | 착수금 | -| 2차 개발비 | 총 개발비의 50% | 서비스 게시일로부터 3일 이내 | 잔금 | -| 총 개발비 | [ ]원 | | | - -### 4.2 월 구독료 - -| 구분 | 금액 (부가세 별도) | 지급 시기 | 비고 | -| --- | --- | --- | --- | -| 월 구독료 | 원 ~ | 매월 말일 | 후불제, 사용량 기준 청구 | - -> ⚠️ 중요: - 월 구독료는 원이며, 영업 협상 및 개발 범위에 따라 증액될 수 있습니다. - -- 계약 시 확정된 구독료: [ ]원/월 - -### 4.3 납부 방법 - -- **개발비**: - - 계좌이체 (세금계산서 발행) - - 입금 계좌: 기업은행 170-175519-04-011  (주)코드브릿지엑스 -- **구독료**: - - CMS 자동이체 (권장) - - 또는 세금계산서 발행 후 계좌이체 - -### 4.4 잔금 지급 기한 [법률 검토 반영] - -- **지급 기한**: 서비스 게시일로부터 **3일 이내** -- **사전 준비**: 회사는 영업 단계부터 납품 일정을 공유하여 고객이 미리 준비할 수 있도록 합니다. -- **미납 시 조치**: 제13조 참조 - -### 4.5 사용량 기반 추가 과금 - -기본 제공 한도 초과 시 다음과 같이 실비 과금됩니다. - -| 항목 | 기본 제공 | 추가 과금 기준 | -| --- | --- | --- | -| 파일 저장 공간 | 100GB | 100GB당 100,000원/월 (부가세 별도) | -| AI 토큰 | 월 100만 토큰 | 1,000토큰 단위 실비 과금 | - -- **파일 저장 공간: **기본 100GB를 초과하는 경우 100GB 단위로 월 100,000원(부가세 별도)이 추가 과금됩니다. -- **AI 토큰: **월 100만 토큰 기본 제공되며, 초과 사용 시 1,000토큰 단위로 실비 과금됩니다. - - 미사용 잔여 토큰은 이월되지 않습니다. (매월 1일 갱신) - - 기본 제공량 80%, 100% 소진 시 자동 알림이 발송됩니다. - -### 4.6 바로빌 부가 서비스 요금 - -고객이 선택적으로 이용하는 바로빌 연동 서비스의 요금은 다음과 같습니다. - -| 서비스 | 과금 방식 | 기본 제공 | 추가 과금 | -| --- | --- | --- | --- | -| 계좌조회 | 월정액 10,000원 | 1계좌 | 추가 1계좌당 10,000원 | -| 카드내역 | 월정액 10,000원 | 5장 | 추가 1장당 5,000원 | -| 세금계산서 발행 | 건별 | 100건 | 추가 50건당 5,000원 | - -- **바로빌 서비스 요금은 고객이 부담하며, 월 구독료와 별도로 청구됩니다.** - - 홈택스 매입/매출 조회 서비스(월 30,000원)는 회사가 부담합니다. - - 상기 금액은 부가세 별도입니다. - -## 제5조 (마일스톤 및 진행 일정) - -### 5.1 개발 단계 (5단계 통일) - -| 단계 | 주요 활동 | 진행률 | 기간 | 납부 | -| --- | --- | --- | --- | --- | -| M1 | 요구사항 분석 및 기획 | 20% | [ 2 ]주 | 1차 개발비 (착수금 50%) | -| M2 | 설계 및 개발 착수 | 50% | [ 2 ]주 | - | -| M3 | 개발 진행 (50% 완료) | 60% | [ 2 ]주 | - | -| M4 | 개발 완료 및 테스트 | 80% | [ 2 ]주 | - | -| M5 | 검수 및 서비스 게시 | 100% | 최대 2주 | 2차 개발비 (잔금 50%) | - -> ⚠️ 중요: - 5단계 마일스톤으로 통일 관리 - M5 검수 완료 후 서비스 게시 - 서비스 게시일로부터 3일 이내 잔금 납부 - -### 5.2 일정 조정 - - - 개발 일정은 고객의 협조에 따라 변동될 수 있습니다. - - 고객 귀책 사유로 인한 지연은 회사의 책임이 아닙니다. - - 불가항력으로 인한 지연 시 양측 협의하여 일정을 조정합니다. - -## 제6조 (서비스 게시 및 검수) - -### 6.1 서비스 게시 - -- 회사는 개발 완료 후 고객에게 **서비스 게시**를 통지합니다. -- **서비스 게시일**은 고객이 서비스에 접근 가능한 날짜를 의미합니다. - - 서비스 게시일부터 구독료가 발생합니다. - -### 6.2 검수 기간 - -- 고객은 개발 완료 후 **최대 2주간 검수 기간**을 가집니다. -- 검수 기간은 서비스 게시 **전**에 이루어집니다. - - 검수 기간 중 발견된 하자는 회사가 무상으로 수정합니다. - -### 6.3 검수 완료 - - - 고객이 서면으로 검수 완료를 통지하거나, - - 검수 기간 2주 종료 시점에 특별한 이의가 없으면 자동 승인으로 간주합니다. - - 검수 완료 후 서비스 게시일이 확정되고, 하자담보 책임 정책이 적용됩니다. - -## 제7조 (하자담보 책임) - -### 7.1 책임 기간 - -서비스 게시일로부터 1년 (소프트웨어산업진흥법 제16조, 민법 제667조) - -### 7.2 하자담보 범위 (무상 처리) - -| 항목 | 내용 | 예시 | -| --- | --- | --- | -| 버그 수정 | 소프트웨어 오류 | 계산 오류, 기능 미작동 | -| 미구현 기능 | 계약서에 명시된 기능 누락 | 약속된 기능 미구현 | -| 성능 개선 | 명시된 성능 기준 미달 | 속도 저하, 응답 지연 | -| UI/UX 수정 | 사용성 문제 | 버튼 미작동, 화면 깨짐 | -| 데이터 오류 | 데이터 손실 또는 오류 | 데이터 삭제, 중복 생성 | -| 보안 패치 | 보안 취약점 수정 | 해킹 방지, 암호화 | - -### 7.3 제외 사항 (별도 비용) - -| 항목 | 내용 | 예시 | -| --- | --- | --- | -| 신규 기능 개발 | 계약서에 없던 새 기능 | 새로운 모듈, 기능 확장 | -| 구조 변경 | 시스템 아키텍처 변경 | DB 구조, 프레임워크 교체 | -| 추가 모듈 | 새로운 모듈 개발 | 회계 모듈, 재고 모듈 | -| 기획 변경 | 초기 기획과 다른 요구사항 | 화면 구성, 프로세스 변경 | -| 교육/컨설팅 | 사용자 교육, 업무 컨설팅 | 직원 교육, 프로세스 개선 | - -### 7.4 하자 처리 절차 - -| 단계 | 내용 | 기간 | -| --- | --- | --- | -| 1. 하자 신고 | 고객이 이메일로 하자 신고 | - | -| 2. 하자 확인 | 회사가 하자 여부 판정 | 3영업일 | -| 3. 수정 작업 | 하자 인정 시 무상 수정 | 7영업일 | -| 4. 검수 완료 | 고객이 수정 사항 확인 | - | - -> ⚠️ 긴급 하자 (서비스 중단)는 24시간 이내 조치합니다. - -### 7.5 책임 면제 사유 - -다음의 경우 하자담보 책임이 면제됩니다: -- **고객 귀책 사유**: - - 고객의 임의 수정 또는 변경 - - 승인되지 않은 제3자 개입 - - 사용 환경 미준수 -- **불가항력**: - - 천재지변 (지진, 태풍 등) - - 전쟁, 테러, 전염병 - - 정부 규제 또는 법령 변경 -- **기간 만료**: - - 서비스 게시일로부터 1년 경과 - -## 제8조 (계약 해제 및 환불) - -### 8.1 환불 정책 개요 - -고객의 임의 해제 권리와 회사의 투입 비용 보전의 균형을 고려하여 수립되었습니다. - -### 8.2 단계별 환불 - -### Phase 1: 상담(인터뷰) 시작 전 - -- **환불율**: 100% (전액 환불) -- **조건**: 계약 후 상담(인터뷰) 배정 전 -- **위약금**: 없음 -- **임의 해제 가능** - -### Phase 2: 상담(인터뷰) 시작 후, 개발 착수 전 - -| 진행 상황 | 환불율 | 공제 내역 | -| --- | --- | --- | -| M1: 기획안 작성 중 (50% 미만) | 80% | 상담매니저 및 기획/개발자 투입 비용 20% 공제 | -| M2: 기획안 완료 (50% 이상) | 50% | 상담매니저 및 기획/개발자 투입 비용 50% 공제 | - -### Phase 3: 개발 진행 중 (5단계 마일스톤 기준) - -| 마일스톤 | 진행률 | 청구 금액(개발비 대비) | 비고 | -| --- | --- | --- | --- | -| M3: 개발 진행 중 (50%) | 70% | 70% | 30% 환불 | -| M4: 개발 완료 및 테스트 | 90% | 90% | 10% 환불 | -| M5: 서비스 개시 완료 | 100% | 100% | 환불 불가 | - -> ⚠️ 중요: 5단계 마일스톤으로 통일 관리 - -### Phase 4: 서비스 게시 후 - -- **환불율**: 0% (환불 불가) -- **개발비**: 전액 확정, 환불 불가 -- **구독료**: 매월 말일 후불제이므로 사용한 만큼만 청구 (환불 개념 없음) -- **대신 제공**: 하자담보 책임 (1년) + 유지보수 (구독 기간 전체) - -### 8.3 환불 불가 사유 - -- **고객 귀책 사유**: - - 협조 지연으로 인한 개발 지연 - - 요구사항 변경으로 인한 추가 개발 - - 승인 거부 또는 회피 -- **약관 위반**: - - 허위 정보 제공 - - 부정 사용 또는 재판매 - - 회사 명예 훼손 - -### 8.4 할인 계약 해지 시 추가 조건 - -본 계약이 정상가 대비 할인 조건으로 체결된 경우, 다음 조건이 추가 적용된다. - -- 발주자 귀책 해지 시 정상가(할인 전 금액) 기준으로 정산한다. - -## 제9조 (구독 및 해지) - -### 9.1 구독 시작 - -- **시작일**: 서비스 게시일 (검수 완료 후) -- **결제일**: 매월 말일 -- **청구 방식**: 후불제 (해당 월 사용량 기준) -- **일할 계산**: (사용 일수 / 해당 월 일수) × 구독료 - -> ⚠️ 중요: - 계약 시 확정된 구독료 금액은 [ ]원/월입니다. - -- 매월 말일에 해당 월 사용일수만큼만 후불 청구됩니다. - -### 9.2 구독 해지 - - - 고객은 언제든지 구독을 해지할 수 있습니다. (위약금 없음) - - 해지 신청 후 30일간 데이터 백업 기간 제공 - - 해지일로부터 30일 후 모든 데이터 완전 삭제 - -## 제10조 (유지보수 정책) - -### 10.1 유지보수 개요 - -- **적용 대상**: 구독료를 정상 납부하는 고객 -- **적용 기간**: 구독 기간 전체 (하자담보 책임 1년 이후에도 구독 중이면 계속 제공) -- **비용**: 월 구독료(500,000원)에 포함 - -### 10.2 하자담보 책임과의 차이 - -| 구분 | 하자담보 책임 (제7조) | 유지보수 (제9조의2) | -| --- | --- | --- | -| 기간 | 서비스 게시일로부터 1년 | 구독 기간 전체 | -| 근거 | 법적 의무 (소프트웨어산업진흥법) | 계약 조건 | -| 비용 | 무상 | 구독료에 포함 | -| 범위 | 하자(버그, 미구현 등) | 하자 + 일반 유지보수 | - -### 10.3 유지보수 범위 (구독료에 포함) - -> ✅ 무상 제공: - 모든 버그 수정 및 오류 처리 - 보안 패치 및 업데이트 - 성능 최적화 - 긴급 장애 대응 (24시간 이내) - 데이터 백업 및 복구 - 기술 지원 (고객센터, 이메일) - 플랫폼 업데이트 (프레임워크, 브라우저 호환성) - -> ❌ 별도 비용: - 신규 기능 개발 - 커스터마이징 및 추가 개발 - 기획 변경 (화면 구성, 프로세스 변경) - 외부 시스템 연동 - 추가 교육 및 컨설팅 - -### 10.4 서비스 레벨 (SLA) - -| 심각도 | 상황 | 응답 시간 | 해결 목표 | -| --- | --- | --- | --- | -| 긴급 (P0) | 서비스 완전 중단 | 1시간 | 24시간 | -| 높음 (P1) | 주요 기능 장애 | 4시간 | 3영업일 | -| 보통 (P2) | 일반 버그 | 1영업일 | 7영업일 | -| 낮음 (P3) | 문의/안내 | 1영업일 | 3영업일 | - -### 10.5 정기 유지보수 - -- **월간**: 보안 패치, 백업 점검 (매월 첫째 주 일요일 새벽) -- **분기**: 성능 최적화 (분기 말 일요일 새벽) -- **반기**: 시스템 점검 (6월/12월 일요일 새벽) - -> ⚠️ 모든 정기 점검은 최소 7일 전 사전 공지됩니다. - -### 10.6 유지보수 신청 - -- **고객센터**: 02-6347-0005 (평일 09:00~18:00 ) -- **이메일**: support@codebridge-x.com (24시간) -- **시스템 내**: SAM 시스템 내 고객지원 메뉴 - -### 10.7 유지보수 종료 - -다음의 경우 유지보수 서비스가 종료됩니다: 1. 구독 해지 시 2. 구독료 3개월 연속 미납 시 3. 중대한 약관 위반 시 - -## 제11조 (고객의 의무) - -고객은 다음 사항을 준수해야 합니다: -- **정확한 정보 제공**: 허위 정보 제공 금지 -- **협조 의무**: 개발에 필요한 자료 및 정보 제공 -- **부정 사용 금지**: 서비스의 재판매, 재배포 금지 -- **지적재산권 존중**: 무단 복제, 역설계 금지 - -## 제12조 (회사의 의무) - -회사는 다음 사항을 준수합니다: -- **서비스 제공**: 계약서에 명시된 서비스 제공 -- **하자담보 책임**: 1년간 하자 무상 수정 -- **개인정보 보호**: 개인정보보호법 준수 -- **기술 지원**: 고객센터 운영 및 기술 지원 - -## 제13조 (미입금 시 법적 조치) - -### 13.1 개발비 미입금 절차 - -| 단계 | 시점 | 조치 내용 | -| --- | --- | --- | -| 1차 독촉 | 기한 경과 후 3일 | 이메일 및 SMS 발송 | -| 내용증명 | 기한 경과 후 7일 | 우편 발송, 7일 내 입금 요청 | -| 추심등 | 기한 경과 후 14일 | 신용정보사 연체 등록, 법률대리인 위임 | -| 법적 조치 | 기한 경과 후 30일 | 지급명령 신청 또는 소송 제기 | - -### 13.2 구독료 미입금 절차 - -| 단계 | 시점 | 조치 내용 | -| --- | --- | --- | -| 1차 실패 | 익일 | 재출금 | -| 2차 실패 | 기한 경과 후 3일 | 재출금 | -| 3차 실패 | 미수금 처리 | 서비스 접근 제한, 1차 독촉 | -| 내용증명 | 기한 경과 후 7일 | 우편 발송, 7일 내 입금 요청 | -| 서비스 중단 | 기한 경과 후 14일 | 로그인 불가, 데이터 격리 | -| 강제 해지 | 기한 경과 후 30일 | 계약 해지, 법적 조치 검토 | - -## 제14조 (개인정보 보호) - - - 회사는 「개인정보 보호법」을 준수합니다. - - 고객의 개인정보는 서비스 제공 목적으로만 사용됩니다. - - 제3자에게 제공하지 않습니다. (법령 제외) - - 계약 종료 시 개인정보는 즉시 삭제됩니다. (법정 보관 의무 제외) - -## 제15조 (지적재산권) - -- **소유권**: 서비스에 대한 모든 지적재산권은 회사에 귀속됩니다. -- **사용 권한**: 고객은 서비스 사용 권한만을 부여받습니다. -- **금지 사항**: 복제, 배포, 역설계, 재판매 금지 - -## 제16조 (손해배상) - - - 회사 또는 고객이 본 계약을 위반하여 상대방에게 손해를 입힌 경우 배상 책임이 있습니다. - - 다만, 불가항력으로 인한 손해는 배상 책임에서 제외됩니다. - -## 제17조 (불가항력) - -다음의 사유로 서비스 제공이 불가능한 경우 회사는 책임을 지지 않습니다: - - 천재지변 (지진, 태풍, 홍수 등) - - 전쟁, 테러, 전염병 - - 정부 규제 또는 법령 변경 - - 제3자의 불법 행위 (해킹 등) - -## 제18조 (분쟁 해결) - - - 본 계약과 관련한 분쟁은 상호 협의하여 해결합니다. -- 협의가 이루어지지 않을 경우, **서울중앙지방법원**을 관할 법원으로 합니다. - -## 제19조 (계약의 효력) - - - 본 계약은 계약일로부터 효력이 발생합니다. - - 본 계약은 구독 해지 시까지 유효합니다. - -## 제20조 (기타) - - - 본 계약서는 2부 작성하여 회사와 고객이 각 1부씩 보관합니다. - - 본 계약의 해석 및 적용은 대한민국 법률을 준거법으로 합니다. - -## 계약 당사자 - -### [회사] - -상호: 주식회사 코드브릿지엑스 -대표자: 이의찬 -사업자등록번호: 664-86-03713 -주소: 서울특별시 강서구 양천로 583, 우림블루나인 B동 1602호 -이메일: contact@codebridge-x.com -전화: 02-6347-0005 -서명: -날짜: - -### [고객] - -상호: -대표자: -사업자등록번호: -주소: -이메일: -전화: -서명: -날짜: - -## 별첨 - -### 별첨 1: 기획서 - -[별도 첨부] - -### 별첨 2: 개발 일정표 - -[별도 첨부] - -### 별첨 3: 기능 명세서 - -[별도 첨부] - -주식회사 코드브릿지엑스 -이메일: contact@codebridge-x.com -전화: 02-6347-0005 -주소: 서울특별시 강서구 양천로 583, 우림블루나인 B동 1602호 - diff --git a/sam/docs/contracts/markdown/02-nda.md b/sam/docs/contracts/markdown/02-nda.md deleted file mode 100644 index cb6ff9c..0000000 --- a/sam/docs/contracts/markdown/02-nda.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: "비밀유지서약서 (NDA)" -version: "v4.0" -date: "2026-02-22" -docx_file: "비밀유지서약서.docx" ---- - -# 비밀유지서약서 (NDA) - -- **작성일**: - -- **서약인 정보** -- **구분**: - -- **인적 사항:** -상호(성명): _______________ -대표자(본인): _______________ -사업자등록번호(주민등록번호): ____________________ -주소: ______________________________________________________________________ -연락처: _______________ -이메일: _______________ - -## 제1조 (목적) - - - 본 서약서는 주식회사 코드브릿지(이하 “회사”)와의 업무 관계에서 알게 된 기밀 정보를 - - 보호하기 위해 작성되었습니다. - -## 제2조 (기밀 정보의 정의) - - - 다음 각 호의 정보는 회사의 기밀 정보로 간주됩니다: - -### 2.1 고객 정보 - - - 고객사 명단 (법인명, 대표자명, 연락처) - - 고객사 담당자 정보 (성명, 부서, 연락처, 이메일) - - 계약 내역 (가입비, 할인율, 구독료, 특약 사항) - - 고객사의 사업 정보 (매출, 직원 수, 거래처 등) - - 고객사가 회사에 요구한 개발 내역 및 기획 문서 - -### 2.2 영업 정보 - - - 가격 정책 (정가, 할인 정책, 최소 가입비) - - 수수료 정책 (비율, 지급 기준, 상계 방식) - - 영업 전략 및 마케팅 계획 - - 잠재 고객 리스트 - - 계약 체결 노하우 및 제안서 템플릿 - -### 2.3 기술 정보 - - - SAM 시스템의 소스코드 - - 데이터베이스 구조 및 설계 문서 - - 개발 프로세스 및 방법론 - - 서버 인프라 구성 및 보안 정책 - - API 키, 접속 정보, 관리자 권한 - -### 2.4 경영 정보 - - - 회사의 재무 정보 (매출, 이익, 원가) - - 조직도 및 인사 정보 - - 사업 계획 및 전략 - - 투자 유치 및 M&A 관련 정보 - -### 2.5 기타 - -- 회사가 **“기밀(Confidential)”** 또는 **“대외비”**로 표시한 모든 문서 및 정보 - -## 제3조 (기밀 유지 의무) - -### 3.1 기본 의무 - - - 본인은 업무 수행 중 알게 된 모든 기밀 정보를: -- **외부에 누설하지 않습니다** -- **업무 목적 외에 사용하지 않습니다** -- **무단으로 복사, 복제, 전송하지 않습니다** -- **제3자에게 제공하거나 공개하지 않습니다** - -### 3.2 정보 관리 - - - 기밀 문서는 안전한 장소에 보관 - - 이메일, 메신저 등 전송 시 암호화 - - 업무 종료 시 모든 기밀 자료 반환 또는 파기 - - 개인 디바이스에 기밀 정보 저장 금지 - -### 3.3 제3자 접근 차단 - - - 가족, 친구 등 타인이 기밀 정보에 접근하지 못하도록 조치 - - 공공장소(카페, 도서관 등)에서 기밀 정보 취급 금지 - - 비밀번호 및 접속 정보 타인 공유 금지 - -## 제4조 (예외 사항) - - - 다음의 정보는 기밀 정보에서 제외됩니다: - - 본인이 알기 전에 이미 공개된 정보 - - 본인의 귀책사유 없이 공개된 정보 - - 제3자로부터 적법하게 취득한 정보 - - 본인이 독자적으로 개발한 정보 - - 법원, 정부기관의 법적 요구에 따라 공개해야 하는 정보 (단, 회사에 사전 통지 필수) - -## 제5조 (의무 기간) - -### 5.1 기간 - - - 본 서약서의 기밀 유지 의무는: -- **계약 체결일로부터 효력 발생** -- **계약 종료 후 2년간 유지** - -### 5.2 영구 보호 - -- 단, 다음 정보는 **영구적으로** 보호됩니다: - - 고객사 개인정보 - - 회사의 영업 비밀 (부정경쟁방지법상 영업 비밀) - - 기술 정보 (특허, 저작권 대상) - -## 제6조 (위반 시 책임) - -### 6.1 민사 책임 - - - 본인이 본 서약을 위반하여 회사 또는 고객에게 손해를 입힌 경우: -- **실손해**** 배상**: 실제 발생한 손해 전액 -- **징벌적 손해배상**: 실손해의 최대 3배 (악의적 유출 시) -- **법률 비용**: 소송 비용, 변호사 비용 등 - -### 6.2 형사 책임 - - - 다음의 경우 형사 고발 대상이 됩니다: -- **부정경쟁방지법** 위반 (영업 비밀 침해) -- **개인정보보호법** 위반 (고객 정보 유출) -- **정보통신망법** 위반 (기술 정보 침해) -- **형법** 위반 (업무상 배임) -- **※ 형사 처벌: 5년 이하 징역 또는 5천만원 이하 벌금** - -### 6.3 계약 해지 - - - 회사는 본 서약 위반 시 즉시 계약을 해지할 수 있으며, 이미 지급한 수수료 또는 - - 대금을 환수할 수 있습니다. - -## 제7조 (자료 반환) - -### 7.1 반환 대상 - - - 계약 종료 또는 요청 시 다음을 즉시 반환해야 합니다: - - 회사로부터 제공받은 모든 문서 (종이, 파일) - - 고객사 계약서 및 개인정보 - - 가격표, 제안서, 템플릿 등 영업 자료 - - USB, 하드디스크 등 저장 매체 - -### 7.2 파기 확인 - -- 반환 불가능한 파일(이메일, 클라우드 등)은 즉시 삭제하고, **삭제 확인서**를 회사에 - - 제출해야 합니다. - -## 제8조 (경업 금지) - -### 8.1 경업 금지 기간 - -- 계약 종료 후 **6개월간** 다음 행위를 금지합니다: - - 회사의 고객에게 경쟁 제품 판매 - - 회사의 기밀 정보를 이용한 유사 사업 - - 회사 직원 또는 영업파트너를 스카우트 - -### 8.2 예외 - - - 단순히 경쟁사 제품을 판매하는 것은 허용되나, 회사의 기밀 정보를 활용해서는 - - 안 됩니다. - -## 제9조 (분쟁 해결) - -### 9.1 관할 법원 - - - 본 서약과 관련된 분쟁은 회사 본사 소재지 관할 법원으로 합니다. - -### 9.2 준거법 - - - 본 서약은 대한민국 법률에 따라 해석됩니다. - -- **서약 확인** - - 본인은 위 내용을 충분히 이해하였으며, 이를 성실히 준수할 것을 서약합니다. -- **서약일**: ___________________ -- **서약인** -상호(성명): _______________ -대표자(본인): _______________ -주민등록번호(또는 사업자등록번호): _______________ -- **서명 또는 인**: _______________ - -- **수령인 (주식회사 ****코드브릿지엑스****)** - - 대표이사: 이의찬 -- **확인****일**: ___________________ -- **서명 또는 인**: _______________ - -- **참고: 관련 법률** -- **부정경쟁방지법 제2조 (영업비밀)** - - “영업비밀”이란 공공연히 알려져 있지 아니하고 독립된 경제적 가치를 가지는 것으로서, - - 비밀로 관리된 생산방법, 판매방법, 그 밖에 영업활동에 유용한 기술상 또는 경영상의 - - 정보를 말한다. -- **부정경쟁방지법 제18조 (벌칙)** -- 영업비밀을 외국에서 사용하거나 외국에서 사용되게 할 목적으로 취득·사용 또는 제3자에게 누설한 자는 **15년 이하의 징역** 또는 **15억원 이하의 벌금**에 처한다. - -- **※ 본 서약서는 2부를 작성하여 회사와 서약인이 각 1부씩 보관합니다.** -- **※ 서약 위반 시 민·형사상 책임을 질 수 있습니다.** \ No newline at end of file diff --git a/sam/docs/contracts/markdown/03-partner-agreement.md b/sam/docs/contracts/markdown/03-partner-agreement.md deleted file mode 100644 index 81e6af5..0000000 --- a/sam/docs/contracts/markdown/03-partner-agreement.md +++ /dev/null @@ -1,276 +0,0 @@ ---- -title: "영업파트너 위촉계약서" -version: "v4.0" -date: "2026-02-22" -docx_file: "영업파트너 위촉계약서.docx" ---- - -# < 영업파트너 위촉계약서 > - -# Sales Partner Engagement Agreement - - - 본 계약은 주식회사 코드브릿지엑스(이하 “회사”)와 (이하 “파트너)간에 SAM 서비스 영업 활동과 관련하여 다음과 같이 위촉계약을 체결합니다. - -## 제1조 (계약의 목적) - - - 본 계약은 회사와 파트너 간의 영업파트너 위촉 관계를 규정하고, 상호 권리와 의무를 - - 명확히 함을 목적으로 합니다. - -## 제2조 (용어의 정의) - -- **판매자**: 고객을 발굴하고 계약 체결을 주도하는 영업파트너 -- **관리자**: 판매자를 관리하고 지원하는 상급 영업파트너 -- **개발비**: 고객이 SAM 서비스 개발을 위해 지급하는 비용 -- **수수료**: 파트너가 영업 활동의 대가로 받는 보상 -- **서비스 게시**: 개발 완료 후 고객이 서비스에 접근 가능하도록 제공하는 것 - -## 제3조 (파트너의 역할 및 업무) - -### 3.1 판매자의 역할 - - - 잠재 고객 발굴 및 초기 접촉 - - SAM 서비스 소개 및 제안 - - 고객과의 계약 체결 지원 - - 계약 후 고객 관리 및 사후 지원 - -### 3.2 관리자의 역할 - - - 판매자 모집 및 관리 - - 판매자 교육 및 지원 - - 영업 전략 수립 및 실행 - - 회사와 판매자 간 소통 중재 - -### 3.3 공통 의무 - - - 회사의 브랜드 이미지 유지 - - 정확한 정보 제공 - - 윤리적 영업 활동 준수 - - 비밀 유지 의무 - -## 제4조 (수수료 정책) - -### 4.1 수수료 비율 - -| 역할 | 수수료 비율 | 산정 기준 | -| --- | --- | --- | -| 판매자 | 개발비의 20% | 1차,2차 입금액 기준 | -| 관리자 | 개발비의 5% | 1차,2차 입금액 기준 | - -### 4.2 수수료 산정 예시 - -- **총 개발비 80,000,000원 계약 시** - -| 단계 | 고객 입금 | 판매자 수수료 (20%) | 관리자 수수료 (5%) | -| --- | --- | --- | --- | -| 1차 착수금 (50%) | 40,000,000원 | 8,000,000원 | 2,000,000원 | -| 2차 잔금 (50%) | 40,000,000원 | 8,000,000원 | 2,000,000원 | -| 총계 | 80,000,000원 | 16,000,000원 | 4,000,000원 | - -- **⚠️ 중요**: 개발비만 수수료 산정 대상이며, 구독료는 수수료 대상이 아닙니다. - -### 4.3 지급 시기 - -- **지급일**: 고객 입금일 **익월 10일** -- **지급 방식**: 계좌 이체 -- **세금**: 3.3% 원천징수 (사업소득) - -### 4.4 수수료 지급 조건 - - - 고객이 개발비를 실제로 입금한 경우에만 지급 - - 계약 해지 또는 환불 시 수수료 미지급 또는 환수 - - 파트너가 계약 위반 시 수수료 지급 보류 - -## 제5조 (수수료 정책 변경) - -### 5.1 사전 고지 의무 - -- 회사는 수수료 정책을 변경할 경우 **최소 1개월 전** 서면 또는 이메일로 파트너에게 고지합니다. - - 수수료 정책을 완전히 폐지하는 경우에도 동일하게 1개월 전 고지합니다. - - 고지 기간 중 체결된 계약은 기존 수수료 정책을 적용합니다. - -### 5.2 변경 효력 - -- 변경된 수수료 정책은 고지일로부터 **1개월 후** 새로 체결되는 계약부터 적용됩니다. - - 고지 기간 만료 전에 체결된 계약은 기존 정책을 따릅니다. - - 진행 중인 계약은 최초 약정 조건을 유지합니다. - -### 5.3 변경 예시 - -#### 예시 1: 수수료율 변경 - - - 고지일: 2026년 2월 1일 - - 변경 내용: 판매자 수수료 20% → 18% - - 적용일: 2026년 3월 1일 이후 체결 계약부터 - -#### 예시 2: 수수료 정책 폐지 - - - 고지일: 2026년 2월 1일 - - 변경 내용: 수수료 정책 완전 폐지 - - 적용일: 2026년 3월 1일 이후 체결 계약부터 - -## 제6조 (계약 기간) - -- 본 계약은 계약일로부터 **1년간** 유효합니다. -- 양측이 계약 만료 **30일 전**까지 서면으로 해지 의사를 통지하지 않으면 자동으로 **1년 연장**됩니다. - - 자동 연장은 동일한 조건으로 반복됩니다. - -## 제7조 (계약 해지) - -### 7.1 일반 해지 (양방향) - -- **통지 기간**: 양측은 **30일 전** 서면 통지로 계약을 해지할 수 있습니다. -- **통지 방법**: 이메일 또는 등기우편 -- **효력 발생**: 통지일로부터 30일 후 -- **미지급 수수료**: 해지일 이전에 발생한 수수료는 정산하여 지급 -- **예시**: - - 통지일: 2026년 2월 1일 - - 해지일: 2026년 3월 1일 - - 2월 중 발생한 수수료는 3월 10일 정상 지급 - -### 7.2 즉시 해지 사유 - -- 회사는 다음의 경우 **즉시 계약을 해지**할 수 있습니다: -- **(1) 품위 유지 결격사유 발생 [신설]** - - 음주운전으로 적발된 경우 - - 형사 범죄로 기소 또는 구속된 경우 - - 사회적 물의를 일으킨 경우 - - 기타 파트너로서의 품위를 훼손한 경우 -- **(2) 계약 위반** - - 허위 정보 제공 또는 사기 행위 - - 회사 명예 훼손 또는 영업 방해 - - 비밀 유지 의무 위반 - - 중대한 업무 태만 -- **(3) 부정 행위** - - 고객으로부터 금품 수수 - - 계약서 위조 또는 변조 - - 회사 자산 횡령 또는 유용 - -### 7.3 즉시 해지 시 조치 - - - 미지급 수수료는 지급하지 않습니다. - - 이미 지급한 수수료는 환수하지 않습니다. (단, 사기 행위는 예외) - - 진행 중인 계약은 회사가 직접 관리합니다. - -## 제8조 (비밀 유지) - -### 8.1 비밀 정보 - - - 다음 정보는 비밀로 유지되어야 합니다: - - 회사의 영업 전략 및 계획 - - 고객 정보 (회사명, 담당자, 연락처 등) - - 수수료 정책 및 계약 조건 - - 기술 정보 및 노하우 - - 회사 내부 자료 - -### 8.2 비밀 유지 의무 - - - 파트너는 업무 중 알게 된 비밀 정보를 외부에 누설하지 않습니다. -- 비밀 유지 의무는 계약 종료 후에도 **3년간** 유효합니다. - - 위반 시 손해배상 책임이 있습니다. - -## 제9조 (지적재산권) - - - SAM 서비스에 대한 모든 지적재산권은 회사에 귀속됩니다. - - 파트너는 회사의 사전 서면 동의 없이 회사의 상표, 로고, 브랜드를 무단으로 사용할 수 없습니다. - - 영업 활동에 필요한 자료는 회사가 제공합니다. - -## 제10조 (세금 및 원천징수) - -### 10.1 사업소득 - -- 파트너 수수료는 **사업소득**으로 간주됩니다. - -### 10.2 원천징수 - -| 항목 | 비율 | 비고 | -| --- | --- | --- | -| 소득세 | 3.0% | | -| 지방소득세 | 0.3% | 소득세의 10% | -| 합계 | 3.3% | | - -### 10.3 지급명세서 - -- 회사는 매월 수수료를 지급한 후에 파트너에게 **지급명세서**를 발급합니다. - -## 제11조 (손해배상) - -### 11.1 파트너의 귀책 사유 - - - 파트너가 다음의 행위로 회사에 손해를 입힌 경우 배상 책임이 있습니다: - - 허위 정보 제공으로 계약 취소 - - 고객과의 분쟁으로 회사 명예 훼손 - - 비밀 유지 의무 위반 - - 부정 행위 - -### 11.2 회사의 귀책 사유 - - - 회사가 정당한 사유 없이 수수료를 지급하지 않을 경우, 연체 이자를 더하여 지급합니다. - -## 제12조 (분쟁 해결) - - - 본 계약과 관련한 분쟁은 상호 협의하여 해결합니다. -- 협의가 이루어지지 않을 경우, **서울중앙지방법원**을 관할 법원으로 합니다. - -## 제13조 (기타 사항) - -### 13.1 계약서 교부 - - - 본 계약서는 2부 작성하여 회사와 파트너가 각 1부씩 보관합니다. - -### 13.2 통지 - - - 모든 통지는 다음의 연락처로 발송됩니다: -- **회사**: -- 이메일: admin@codebridge-x.com -- 전화: 02-6347-0005 -- **파트너**: -- 이메일: -- 전화: - -### 13.3 준거법 - - - 본 계약은 대한민국 법률에 따라 해석되고 적용됩니다. - -- **계약 당사자** -- **[회사]** -- **상호**: 주식회사 코드브릿지엑스 -- **대표자**: 이의찬 (인) -- **사업자등록번호**: 664-86-03713 -- **주소**: 서울특별시 강서구 양천로 583, 우림블루나인 B동 1602호 -- **이메일**: admin@codebridge-x.com -- **전화**: 02-6347-0005 -- **날짜**: - -- **[파트너]** -- **상호/성명**: -- **대표자/본인**: (서명) -- **사업자등록번호**: -- **주소**: -- **이메일**: -- **전화**: -- **날짜**: - -- **별첨** - -#### 별첨 1: 수수료 정산표 - -| 계약번호 | 고객사 | 입금일 | 입금액 | 수수료율 | 수수료 | 지급일 | -| --- | --- | --- | --- | --- | --- | --- | -| | | | | | | | - -#### 별첨 2: 영업 활동 보고서 - -| 날짜 | 활동내용 | 고객사 | 진행 상황 | -| --- | --- | --- | --- | -| | | | | - - - 첨부 서류 - - 사업자등록증 사본 (사업자인 경우) - - 주민등록등본 사본 (개인인 경우) - - 통장 사본 (수수료 입금용) - - 비밀유지서약서 - -- **주식회사 코드브릿지엑스** -- 이메일: admin@codebridge-x.com -- 전화: 02-6347-0005 -- 주소: 서울특별시 강서구 양천로 583, 우림블루나인 B동 1602호 diff --git a/sam/docs/contracts/markdown/04-partner-agreement-group.md b/sam/docs/contracts/markdown/04-partner-agreement-group.md deleted file mode 100644 index b3251c4..0000000 --- a/sam/docs/contracts/markdown/04-partner-agreement-group.md +++ /dev/null @@ -1,267 +0,0 @@ ---- -title: "영업파트너 위촉계약서 (단체용)" -version: "v4.0" -date: "2026-02-22" -docx_file: "영업파트너 위촉계약서(단체용).docx" ---- - -# < 영업파트너 위촉계약서 > - -# Sales Partner Engagement Agreement - - - 본 계약은 주식회사 코드브릿지엑스(이하 “회사”)와 (이하 “파트너)간에 SAM 서비스 영업 활동과 관련하여 다음과 같이 위촉계약을 체결합니다. - -## 제1조 (계약의 목적) - - - 본 계약은 회사와 파트너 간의 영업파트너 위촉 관계를 규정하고, 상호 권리와 의무를 - - 명확히 함을 목적으로 합니다. - -## 제2조 (용어의 정의) - -- **판매자**: 고객을 발굴하고 계약 체결을 주도하는 영업파트너 -- **개발비**: 고객이 SAM 서비스 개발을 위해 지급하는 비용 -- **수수료**: 파트너가 영업 활동의 대가로 받는 보상 -- **서비스 게시**: 개발 완료 후 고객이 서비스에 접근 가능하도록 제공하는 것 - -## 제3조 (파트너의 역할 및 업무) - -### 3.1 판매자의 역할 - - - 잠재 고객 발굴 및 초기 접촉 - - SAM 서비스 소개 및 제안 - - 고객과의 계약 체결 지원 - - 계약 후 고객 관리 및 사후 지원 - -### 3.2 공통 의무 - - - 회사의 브랜드 이미지 유지 - - 정확한 정보 제공 - - 윤리적 영업 활동 준수 - - 비밀 유지 의무 - -## 제4조 (수수료 정책) - -### 4.1 수수료 비율 - -| 역할 | 수수료 비율 | 산정 기준 | -| --- | --- | --- | -| 판매자 | 개발비의 30% | 1차,2차 입금액 기준 | - -### 4.2 수수료 산정 예시 - -- **총 개발비 80,000,000원 계약 시** - -| 단계 | 고객 입금 | 판매자 수수료 (30%) | -| --- | --- | --- | -| 1차 착수금 (50%) | 40,000,000원 | 12,000,000원 | -| 2차 잔금 (50%) | 40,000,000원 | 12,000,000원 | -| 총계 | 80,000,000원 | 24,000,000원 | - -- **⚠️ 중요**: 개발비만 수수료 산정 대상이며, 구독료는 수수료 대상이 아닙니다. - -### 4.3 지급 시기 - -- **지급일**: 고객 입금일 **익월 10일** -- **지급 방식**: 계좌 이체 -- **세금**: 사업소득일 경우 3.3% 원천징수 - -### 4.4 수수료 지급 조건 - - - 고객이 개발비를 실제로 입금한 경우에만 지급 - - 계약 해지 또는 환불 시 수수료 미지급 또는 환수 - - 파트너가 계약 위반 시 수수료 지급 보류 - -## 제5조 (수수료 정책 변경) - -### 5.1 사전 고지 의무 - -- 회사는 수수료 정책을 변경할 경우 **최소 1개월 전** 서면 또는 이메일로 파트너에게 고지합니다. - - 수수료 정책을 완전히 폐지하는 경우에도 동일하게 1개월 전 고지합니다. - - 고지 기간 중 체결된 계약은 기존 수수료 정책을 적용합니다. - -### 5.2 변경 효력 - -- 변경된 수수료 정책은 고지일로부터 **1개월 후** 새로 체결되는 계약부터 적용됩니다. - - 고지 기간 만료 전에 체결된 계약은 기존 정책을 따릅니다. - - 진행 중인 계약은 최초 약정 조건을 유지합니다. - -### 5.3 변경 예시 - -#### 예시 1: 수수료율 변경 - - - 고지일: 2026년 2월 1일 - - 변경 내용: 판매자 수수료 20% → 18% - - 적용일: 2026년 3월 1일 이후 체결 계약부터 - -#### 예시 2: 수수료 정책 폐지 - - - 고지일: 2026년 2월 1일 - - 변경 내용: 수수료 정책 완전 폐지 - - 적용일: 2026년 3월 1일 이후 체결 계약부터 - -## 제6조 (계약 기간) - -- 본 계약은 계약일로부터 **1년간** 유효합니다. -- 양측이 계약 만료 **30일 전**까지 서면으로 해지 의사를 통지하지 않으면 자동으로 **1년 연장**됩니다. - - 자동 연장은 동일한 조건으로 반복됩니다. - -## 제7조 (계약 해지) - -### 7.1 일반 해지 (양방향) - -- **통지 기간**: 양측은 **30일 전** 서면 통지로 계약을 해지할 수 있습니다. -- **통지 방법**: 이메일 또는 등기우편 -- **효력 발생**: 통지일로부터 30일 후 -- **미지급 수수료**: 해지일 이전에 발생한 수수료는 정산하여 지급 -- **예시**: - - 통지일: 2026년 2월 1일 - - 해지일: 2026년 3월 1일 - - 2월 중 발생한 수수료는 3월 10일 정상 지급 - -### 7.2 즉시 해지 사유 - -- 회사는 다음의 경우 **즉시 계약을 해지**할 수 있습니다: -- **(1) 품위 유지 결격사유 발생 [신설]** - - 음주운전으로 적발된 경우 - - 형사 범죄로 기소 또는 구속된 경우 - - 사회적 물의를 일으킨 경우 - - 기타 파트너로서의 품위를 훼손한 경우 -- **(2) 계약 위반** - - 허위 정보 제공 또는 사기 행위 - - 회사 명예 훼손 또는 영업 방해 - - 비밀 유지 의무 위반 - - 중대한 업무 태만 -- **(3) 부정 행위** - - 고객으로부터 금품 수수 - - 계약서 위조 또는 변조 - - 회사 자산 횡령 또는 유용 - -### 7.3 즉시 해지 시 조치 - - - 미지급 수수료는 지급하지 않습니다. - - 이미 지급한 수수료는 환수하지 않습니다. (단, 사기 행위는 예외) - - 진행 중인 계약은 회사가 직접 관리합니다. - -## 제8조 (비밀 유지) - -### 8.1 비밀 정보 - - - 다음 정보는 비밀로 유지되어야 합니다: - - 회사의 영업 전략 및 계획 - - 고객 정보 (회사명, 담당자, 연락처 등) - - 수수료 정책 및 계약 조건 - - 기술 정보 및 노하우 - - 회사 내부 자료 - -### 8.2 비밀 유지 의무 - - - 파트너는 업무 중 알게 된 비밀 정보를 외부에 누설하지 않습니다. -- 비밀 유지 의무는 계약 종료 후에도 **3년간** 유효합니다. - - 위반 시 손해배상 책임이 있습니다. - -## 제9조 (지적재산권) - - - SAM 서비스에 대한 모든 지적재산권은 회사에 귀속됩니다. - - 파트너는 회사의 사전 서면 동의 없이 회사의 상표, 로고, 브랜드를 무단으로 사용할 수 없습니다. - - 영업 활동에 필요한 자료는 회사가 제공합니다. - -## 제10조 (세금 및 원천징수) - -### 10.1 사업소득 - -- 파트너 수수료는 **사업소득**으로 간주됩니다. - -### 10.2 원천징수 - -| 항목 | 비율 | 비고 | -| --- | --- | --- | -| 소득세 | 3.0% | | -| 지방소득세 | 0.3% | 소득세의 10% | -| 합계 | 3.3% | | - -### 10.3 지급명세서 - -- 회사는 매월 수수료를 지급한 후에 파트너에게 **지급명세서**를 발급합니다. - -## 제11조 (손해배상) - -### 11.1 파트너의 귀책 사유 - - - 파트너가 다음의 행위로 회사에 손해를 입힌 경우 배상 책임이 있습니다: - - 허위 정보 제공으로 계약 취소 - - 고객과의 분쟁으로 회사 명예 훼손 - - 비밀 유지 의무 위반 - - 부정 행위 - -### 11.2 회사의 귀책 사유 - - - 회사가 정당한 사유 없이 수수료를 지급하지 않을 경우, 연체 이자를 더하여 지급합니다. - -## 제12조 (분쟁 해결) - - - 본 계약과 관련한 분쟁은 상호 협의하여 해결합니다. -- 협의가 이루어지지 않을 경우, **서울중앙지방법원**을 관할 법원으로 합니다. - -## 제13조 (기타 사항) - -### 13.1 계약서 교부 - - - 본 계약서는 2부 작성하여 회사와 파트너가 각 1부씩 보관합니다. - -### 13.2 통지 - - - 모든 통지는 다음의 연락처로 발송됩니다: -- **회사**: -- 이메일: admin@codebridge-x.com -- 전화: 02-6347-0005 -- **파트너**: -- 이메일: -- 전화: - -### 13.3 준거법 - - - 본 계약은 대한민국 법률에 따라 해석되고 적용됩니다. - -- **계약 당사자** -- **[회사]** -- **상호**: 주식회사 코드브릿지엑스 -- **대표자**: 이의찬 (인) -- **사업자등록번호**: 664-86-03713 -- **주소**: 서울특별시 강서구 양천로 583, 우림블루나인 B동 1602호 -- **이메일**: admin@codebridge-x.com -- **전화**: 02-6347-0005 -- **날짜**: - -- **[파트너]** -- **상호/성명**: -- **대표자/본인**: (서명) -- **사업자등록번호**: -- **주소**: -- **이메일**: -- **전화**: -- **날짜**: - -- **별첨** - -#### 별첨 1: 수수료 정산표 - -| 계약번호 | 고객사 | 입금일 | 입금액 | 수수료율 | 수수료 | 지급일 | -| --- | --- | --- | --- | --- | --- | --- | -| | | | | | | | - -#### 별첨 2: 영업 활동 보고서 - -| 날짜 | 활동내용 | 고객사 | 진행 상황 | -| --- | --- | --- | --- | -| | | | | - - - 첨부 서류 - - 사업자등록증 사본 (사업자인 경우) - - 주민등록등본 사본 (개인인 경우) - - 통장 사본 (수수료 입금용) - - 비밀유지서약서 - -- **주식회사 코드브릿지엑스** -- 이메일: admin@codebridge-x.com -- 전화: 02-6347-0005 -- 주소: 서울특별시 강서구 양천로 583, 우림블루나인 B동 1602호 diff --git a/sam/docs/contracts/revisions.json b/sam/docs/contracts/revisions.json deleted file mode 100644 index 1bcd843..0000000 --- a/sam/docs/contracts/revisions.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "documents": { - "01-service-agreement": { - "title": "고객사 서비스 이용계약서", - "docx_file": "01_고객_서비스이용계약서_v4_0_전자서명용.docx", - "revisions": [ - { - "version": "v4.0", - "date": "2026-02-22", - "author": "개발팀", - "description": "버전 관리 시스템 도입, 개정이력 추적 시작" - }, - { - "version": "v4.1", - "date": "2026-02-22", - "author": "개발팀", - "description": "제4조에 사용량 기반 추가 과금(4.5) 및 바로빌 부가 서비스 요금(4.6) 조항 추가" - } - ] - }, - "02-nda": { - "title": "비밀유지서약서 (NDA)", - "docx_file": "비밀유지서약서.docx", - "revisions": [ - { - "version": "v4.0", - "date": "2026-02-22", - "author": "개발팀", - "description": "버전 관리 시스템 도입, 개정이력 추적 시작" - } - ] - }, - "03-partner-agreement": { - "title": "영업파트너 위촉계약서", - "docx_file": "영업파트너 위촉계약서.docx", - "revisions": [ - { - "version": "v4.0", - "date": "2026-02-22", - "author": "개발팀", - "description": "버전 관리 시스템 도입, 개정이력 추적 시작" - } - ] - }, - "04-partner-agreement-group": { - "title": "영업파트너 위촉계약서 (단체용)", - "docx_file": "영업파트너 위촉계약서(단체용).docx", - "revisions": [ - { - "version": "v4.0", - "date": "2026-02-22", - "author": "개발팀", - "description": "버전 관리 시스템 도입, 개정이력 추적 시작" - } - ] - } - } -} diff --git a/sam/docs/contracts/scripts/extract_to_markdown.py b/sam/docs/contracts/scripts/extract_to_markdown.py deleted file mode 100644 index ea44889..0000000 --- a/sam/docs/contracts/scripts/extract_to_markdown.py +++ /dev/null @@ -1,334 +0,0 @@ -#!/usr/bin/env python3 -""" -DOCX → Markdown 추출 스크립트 - -4개 전자계약 DOCX 파일을 Markdown으로 변환한다. -- 서비스이용계약서: Heading 스타일 기반 매핑 -- 나머지 3개: Bold 런 + 패턴 매칭으로 구조 유추 -""" - -import re -import sys -from datetime import date -from pathlib import Path - -from docx import Document - -# 경로 설정 -BASE_DIR = Path(__file__).resolve().parent.parent -DOCX_DIR = BASE_DIR / "docx" -MD_DIR = BASE_DIR / "markdown" - -# DOCX → Markdown 매핑 -FILE_MAP = { - "01_고객_서비스이용계약서_v4_0_전자서명용.docx": { - "output": "01-service-agreement.md", - "title": "고객사 서비스 이용계약서", - "type": "styled", - }, - "비밀유지서약서.docx": { - "output": "02-nda.md", - "title": "비밀유지서약서 (NDA)", - "type": "pattern", - }, - "영업파트너 위촉계약서.docx": { - "output": "03-partner-agreement.md", - "title": "영업파트너 위촉계약서", - "type": "pattern", - }, - "영업파트너 위촉계약서(단체용).docx": { - "output": "04-partner-agreement-group.md", - "title": "영업파트너 위촉계약서 (단체용)", - "type": "pattern", - }, -} - - -def table_to_markdown(table): - """DOCX 테이블을 Markdown 테이블로 변환""" - rows = [] - for row in table.rows: - cells = [cell.text.strip().replace("\n", " ") for cell in row.cells] - rows.append(cells) - - if not rows: - return "" - - lines = [] - # 헤더 - lines.append("| " + " | ".join(rows[0]) + " |") - lines.append("| " + " | ".join(["---"] * len(rows[0])) + " |") - # 본문 - for row in rows[1:]: - # 셀 개수 맞추기 - while len(row) < len(rows[0]): - row.append("") - lines.append("| " + " | ".join(row[: len(rows[0])]) + " |") - - return "\n".join(lines) - - -def get_paragraph_heading_level_styled(para): - """스타일 기반 문서의 헤딩 레벨 판별 (서비스이용계약서)""" - style = para.style.name if para.style else "" - - if style == "Heading 1": - return 1 - elif style == "Heading 2": - return 2 - elif style == "Heading 3": - return 3 - - return 0 - - -def get_paragraph_heading_level_pattern(para): - """패턴 매칭 기반 문서의 헤딩 레벨 판별 (비밀유지서약서, 영업파트너 위촉계약서)""" - text = para.text.strip() - has_bold = any(r.bold for r in para.runs if r.bold) - - if not text or not has_bold: - return 0 - - # "제X조" 패턴 → ## (h2) - if re.match(r"^ 0: - lines.append("") - lines.append(f"{'#' * level} {text}") - lines.append("") - elif style == "Compact": - # Bold 런이 있으면 강조 리스트 - has_bold = any(r.bold for r in para.runs if r.bold) - if has_bold: - # Bold 부분과 일반 부분 분리 - parts = [] - for run in para.runs: - if run.bold: - parts.append(f"**{run.text}**") - else: - parts.append(run.text) - combined = "".join(parts) - lines.append(f"- {combined}") - else: - # 들여쓰기된 하위 항목 - lines.append(f" - {text}") - elif style in ("Body Text", "First Paragraph"): - # 본문 텍스트 - if text.startswith("⚠️") or text.startswith("✅") or text.startswith("❌"): - lines.append("") - lines.append(f"> {text}") - lines.append("") - else: - lines.append(text) - else: - lines.append(text) - - elif tag == "tbl": - if table_idx <= len(doc.tables): - current_table_idx = sum( - 1 - for c in list(body)[: list(body).index(child)] - if (c.tag.split("}")[-1] if "}" in c.tag else c.tag) == "tbl" - ) - if current_table_idx < len(doc.tables): - lines.append("") - lines.append(table_to_markdown(doc.tables[current_table_idx])) - lines.append("") - - return "\n".join(lines) - - -def extract_pattern_doc(doc, file_info): - """패턴 매칭 기반 문서 추출 (비밀유지서약서, 영업파트너 위촉계약서)""" - lines = [] - - body = doc.element.body - para_idx = 0 - - for child in body: - tag = child.tag.split("}")[-1] if "}" in child.tag else child.tag - - if tag == "p": - para = doc.paragraphs[para_idx] - para_idx += 1 - text = para.text.strip() - - if not text: - lines.append("") - continue - - level = get_paragraph_heading_level_pattern(para) - has_bold = any(r.bold for r in para.runs if r.bold) - - if level > 0: - lines.append("") - # 제목에서 < > 제거 - clean_text = re.sub(r"^<\s*|\s*>$", "", text).strip() - lines.append(f"{'#' * level} {clean_text}") - lines.append("") - elif has_bold: - # Bold 텍스트는 강조 처리 - parts = [] - for run in para.runs: - if run.bold: - parts.append(f"**{run.text}**") - else: - parts.append(run.text) - combined = "".join(parts) - - # (1), (2) 같은 번호 패턴 - if re.match(r"^\*\*\(\d+\)", combined): - lines.append(f"- {combined}") - # "예시 N:", "Phase N:" 같은 패턴 - elif re.match(r"^\*\*(예시|Phase|별첨)\s", combined): - lines.append("") - lines.append(f"#### {text}") - lines.append("") - else: - lines.append(f"- {combined}") - else: - # 일반 텍스트 - # 빈칸 양식 (___) 유지 - if "___" in text: - lines.append(text) - elif re.match(r"^(이메일|전화|주소|상호|대표|사업자|주민|연락처|날짜):", text): - lines.append(f"- {text}") - else: - lines.append(f" - {text}") - - elif tag == "tbl": - current_table_idx = sum( - 1 - for c in list(body)[: list(body).index(child)] - if (c.tag.split("}")[-1] if "}" in c.tag else c.tag) == "tbl" - ) - if current_table_idx < len(doc.tables): - lines.append("") - lines.append(table_to_markdown(doc.tables[current_table_idx])) - lines.append("") - - return "\n".join(lines) - - -def add_frontmatter(content, file_info, docx_name): - """YAML 프론트매터 추가""" - frontmatter = f"""--- -title: "{file_info['title']}" -version: "v4.0" -date: "{date.today().isoformat()}" -docx_file: "{docx_name}" ---- -""" - return frontmatter + "\n" + content - - -def extract_file(docx_name, file_info): - """단일 DOCX 파일 추출""" - docx_path = DOCX_DIR / docx_name - if not docx_path.exists(): - print(f" [SKIP] {docx_name} - 파일 없음") - return False - - doc = Document(str(docx_path)) - - if file_info["type"] == "styled": - content = extract_styled_doc(doc, file_info) - else: - content = extract_pattern_doc(doc, file_info) - - # 프론트매터 추가 - content = add_frontmatter(content, file_info, docx_name) - - # 연속 빈 줄 정리 (3줄 이상 → 2줄로) - content = re.sub(r"\n{3,}", "\n\n", content) - - # 파일 저장 - output_path = MD_DIR / file_info["output"] - output_path.write_text(content, encoding="utf-8") - print(f" [OK] {docx_name} → {file_info['output']}") - return True - - -def main(): - print("DOCX → Markdown 추출 시작") - print(f" DOCX 디렉토리: {DOCX_DIR}") - print(f" 출력 디렉토리: {MD_DIR}") - print() - - MD_DIR.mkdir(parents=True, exist_ok=True) - - success = 0 - for docx_name, file_info in FILE_MAP.items(): - if extract_file(docx_name, file_info): - success += 1 - - print(f"\n완료: {success}/{len(FILE_MAP)} 파일 변환됨") - return 0 if success == len(FILE_MAP) else 1 - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/sam/docs/contracts/scripts/sync_check.py b/sam/docs/contracts/scripts/sync_check.py deleted file mode 100644 index 09d55d9..0000000 --- a/sam/docs/contracts/scripts/sync_check.py +++ /dev/null @@ -1,263 +0,0 @@ -#!/usr/bin/env python3 -""" -DOCX ↔ Markdown 동기화 검증 스크립트 - -DOCX에서 텍스트를 추출하고 Markdown 파일의 텍스트와 비교하여 -불일치 항목을 리포트한다. -""" - -import difflib -import re -import sys -from pathlib import Path - -from docx import Document - -BASE_DIR = Path(__file__).resolve().parent.parent -DOCX_DIR = BASE_DIR / "docx" -MD_DIR = BASE_DIR / "markdown" - -# DOCX → Markdown 파일 매핑 -FILE_MAP = { - "01_고객_서비스이용계약서_v4_0_전자서명용.docx": "01-service-agreement.md", - "비밀유지서약서.docx": "02-nda.md", - "영업파트너 위촉계약서.docx": "03-partner-agreement.md", - "영업파트너 위촉계약서(단체용).docx": "04-partner-agreement-group.md", -} - - -def extract_text_from_docx(docx_path): - """DOCX에서 순수 텍스트만 추출 (개정이력 테이블 제외, 인터리빙 방식)""" - doc = Document(str(docx_path)) - lines = [] - - from docx.oxml.ns import qn as _qn - - body = doc.element.body - para_idx = 0 - table_idx = 0 - skip_revision = False - - for child in body: - tag = child.tag.split("}")[-1] if "}" in child.tag else child.tag - - if tag == "p": - if para_idx < len(doc.paragraphs): - text = doc.paragraphs[para_idx].text.strip() - para_idx += 1 - - if "개정이력" in text: - skip_revision = True - continue - if text: - skip_revision = False - lines.append(text) - - elif tag == "tbl": - if table_idx < len(doc.tables): - table = doc.tables[table_idx] - table_idx += 1 - - # 개정이력 테이블 건너뛰기 - if len(table.rows) > 0: - first_row_text = [cell.text.strip() for cell in table.rows[0].cells] - if "버전" in first_row_text and "날짜" in first_row_text: - skip_revision = False - continue - - if skip_revision: - skip_revision = False - continue - - for row in table.rows: - cells = [cell.text.strip() for cell in row.cells] - # 빈 셀만 있는 행 건너뛰기 - if not any(cells): - continue - row_text = " | ".join(cells) - if row_text.strip(): - lines.append(row_text) - - return lines - - -def extract_text_from_markdown(md_path): - """Markdown에서 순수 텍스트만 추출 (프론트매터, 마크업 제거)""" - content = md_path.read_text(encoding="utf-8") - lines = [] - - in_frontmatter = False - in_table = False - - for line in content.split("\n"): - stripped = line.strip() - - # YAML 프론트매터 건너뛰기 - if stripped == "---": - in_frontmatter = not in_frontmatter - continue - if in_frontmatter: - continue - - # 빈 줄 건너뛰기 - if not stripped: - in_table = False - continue - - # Markdown 마크업 제거 - text = stripped - - # 헤딩 마크업 제거 - text = re.sub(r"^#{1,6}\s+", "", text) - - # 리스트 마크업 제거 - text = re.sub(r"^\s*[-*+]\s+", "", text) - - # Bold/Italic 마크업 제거 - text = re.sub(r"\*\*(.+?)\*\*", r"\1", text) - text = re.sub(r"\*(.+?)\*", r"\1", text) - - # 블록인용 제거 - text = re.sub(r"^>\s*", "", text) - - # 테이블 구분선 건너뛰기 - if re.match(r"^\|[\s\-|]+\|$", text): - continue - - # 테이블 행 - if text.startswith("|") and text.endswith("|"): - # 파이프 제거하고 셀 텍스트 추출 - cells = [c.strip() for c in text.strip("|").split("|")] - text = " | ".join(cells) - - text = text.strip() - if text: - lines.append(text) - - return lines - - -def normalize_text(text): - """비교를 위한 텍스트 정규화""" - # 공백 정규화 - text = re.sub(r"\s+", " ", text).strip() - # 특수문자 정규화 - text = text.replace("\u00a0", " ") # non-breaking space - text = text.replace("\u3000", " ") # ideographic space - # 언더스코어 빈칸 정규화 - text = re.sub(r"_{3,}", "___", text) - # Bold 마크업(**) 제거 (DOCX 텍스트에 리터럴 ** 포함되는 경우) - text = re.sub(r"\*\*(.+?)\*\*", r"\1", text) - # 선행 리스트 마커 제거 (DOCX 텍스트가 "- "로 시작하는 경우) - text = re.sub(r"^-\s+", "", text) - return text - - -def compare_documents(docx_name, md_name): - """두 문서의 텍스트를 비교""" - docx_path = DOCX_DIR / docx_name - md_path = MD_DIR / md_name - - if not docx_path.exists(): - return {"status": "error", "message": f"DOCX 파일 없음: {docx_name}"} - if not md_path.exists(): - return {"status": "error", "message": f"Markdown 파일 없음: {md_name}"} - - docx_lines = [normalize_text(l) for l in extract_text_from_docx(docx_path) if l.strip()] - md_lines = [normalize_text(l) for l in extract_text_from_markdown(md_path) if l.strip()] - - # difflib로 비교 - matcher = difflib.SequenceMatcher(None, docx_lines, md_lines) - ratio = matcher.ratio() - - # 차이점 추출 - diffs = [] - for tag, i1, i2, j1, j2 in matcher.get_opcodes(): - if tag == "equal": - continue - elif tag == "replace": - for idx in range(max(i2 - i1, j2 - j1)): - docx_text = docx_lines[i1 + idx] if i1 + idx < i2 else "(없음)" - md_text = md_lines[j1 + idx] if j1 + idx < j2 else "(없음)" - diffs.append({ - "type": "변경", - "docx": docx_text[:80], - "markdown": md_text[:80], - }) - elif tag == "delete": - for idx in range(i1, i2): - diffs.append({ - "type": "DOCX에만 존재", - "docx": docx_lines[idx][:80], - "markdown": "-", - }) - elif tag == "insert": - for idx in range(j1, j2): - diffs.append({ - "type": "Markdown에만 존재", - "docx": "-", - "markdown": md_lines[idx][:80], - }) - - return { - "status": "ok", - "similarity": round(ratio * 100, 1), - "docx_lines": len(docx_lines), - "md_lines": len(md_lines), - "diff_count": len(diffs), - "diffs": diffs[:20], # 상위 20개만 - } - - -def main(): - print("=" * 70) - print("DOCX ↔ Markdown 동기화 검증") - print("=" * 70) - - all_ok = True - - for docx_name, md_name in FILE_MAP.items(): - print(f"\n{'─' * 50}") - print(f"문서: {docx_name}") - print(f" ↔ {md_name}") - print(f"{'─' * 50}") - - result = compare_documents(docx_name, md_name) - - if result["status"] == "error": - print(f" [ERROR] {result['message']}") - all_ok = False - continue - - similarity = result["similarity"] - status_icon = "OK" if similarity >= 80 else "WARN" if similarity >= 60 else "FAIL" - - print(f" 유사도: {similarity}% [{status_icon}]") - print(f" DOCX 라인: {result['docx_lines']}") - print(f" Markdown 라인: {result['md_lines']}") - print(f" 차이점: {result['diff_count']}개") - - if result["diffs"]: - print(f"\n 주요 차이점 (상위 {min(len(result['diffs']), 10)}개):") - for i, diff in enumerate(result["diffs"][:10]): - print(f" [{diff['type']}]") - if diff["docx"] != "-": - print(f" DOCX: {diff['docx']}") - if diff["markdown"] != "-": - print(f" MD: {diff['markdown']}") - - if similarity < 80: - all_ok = False - - print(f"\n{'=' * 70}") - if all_ok: - print("결과: 모든 문서 동기화 상태 양호") - else: - print("결과: 일부 문서에서 불일치 발견 - 확인 필요") - print(f"{'=' * 70}") - - return 0 if all_ok else 1 - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/sam/docs/data/interview-master-questions.sql b/sam/docs/data/interview-master-questions.sql deleted file mode 100644 index 58b4899..0000000 --- a/sam/docs/data/interview-master-questions.sql +++ /dev/null @@ -1,279 +0,0 @@ --- ============================================================ --- 인터뷰 질문 마스터 데이터 SQL --- 8개 도메인 × 16개 템플릿 × 80개 질문 --- --- 실행 방법: --- 로컬: docker exec -i sam-mysql-1 mysql -u root -p samdb < docs/data/interview-master-questions.sql --- 개발서버: mysql -u -p samdb < interview-master-questions.sql --- phpMyAdmin: SQL 탭에서 전체 복사 후 실행 --- --- 주의: 한 번만 실행할 것. 중복 실행 시 데이터가 중복됨. --- ============================================================ - -SET NAMES utf8mb4; -SET @tenant_id = 1; -SET @user_id = 1; -SET @now = NOW(); - --- ============================================================ --- 대분류: 제조업-방화셔터 (parent_id=null, 루트 카테고리) --- ============================================================ -INSERT INTO interview_categories (tenant_id, interview_project_id, parent_id, name, description, domain, sort_order, is_active, created_by, updated_by, created_at, updated_at) -VALUES (@tenant_id, NULL, NULL, '제조업-방화셔터', '방화셔터 제조업 인터뷰', NULL, 1, 1, @user_id, @user_id, @now, @now); -SET @root_manufacturing = LAST_INSERT_ID(); - --- ============================================================ --- Domain 1: 제품 분류 체계 (product_classification) --- ============================================================ -INSERT INTO interview_categories (tenant_id, interview_project_id, parent_id, name, description, domain, sort_order, is_active, created_by, updated_by, created_at, updated_at) -VALUES (@tenant_id, NULL, @root_manufacturing, '제품 분류 체계', '제품 카테고리, 모델 코드, 분류 기준 파악', 'product_classification', 3, 1, @user_id, @user_id, @now, @now); -SET @cat_1 = LAST_INSERT_ID(); - --- 템플릿 1.1: 제품 카테고리 구조 -INSERT INTO interview_templates (tenant_id, interview_category_id, name, sort_order, is_active, created_by, updated_by, created_at, updated_at) -VALUES (@tenant_id, @cat_1, '제품 카테고리 구조', 1, 1, @user_id, @user_id, @now, @now); -SET @tpl_1_1 = LAST_INSERT_ID(); - -INSERT INTO interview_questions (tenant_id, interview_template_id, question_text, question_type, options, ai_hint, expected_format, depends_on, domain, is_required, sort_order, is_active, created_by, updated_by, created_at, updated_at) VALUES -(@tenant_id, @tpl_1_1, '귀사의 주요 제품군을 모두 나열해주세요', 'text', NULL, '쉼표 구분으로 제품군 나열', NULL, NULL, 'product_classification', 1, 1, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_1_1, '각 제품군의 하위 모델명과 코드 체계를 알려주세요', 'table_input', '{"columns":["모델코드","모델명","비고"]}', '코드-이름 매핑 테이블', NULL, NULL, 'product_classification', 0, 2, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_1_1, '제품을 분류하는 기준은 무엇인가요? (소재, 용도, 크기 등)', 'multi_select', '{"choices":["소재별","용도별","크기별","설치방식별","인증여부별"]}', NULL, NULL, NULL, 'product_classification', 0, 3, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_1_1, '인증(인정) 제품과 비인증 제품의 구분이 있나요?', 'select', '{"choices":["있음","없음"]}', NULL, NULL, NULL, 'product_classification', 0, 4, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_1_1, '인증 제품의 경우 구성이 고정되나요?', 'checkbox', NULL, NULL, NULL, '{"question_index":3,"value":"있음"}', 'product_classification', 0, 5, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_1_1, '카테고리별 제품 수는 대략 몇 개인가요?', 'number', NULL, NULL, '개', NULL, 'product_classification', 0, 6, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_1_1, '제품 코드 명명 규칙을 설명해주세요 (예: KSS01의 의미)', 'text', NULL, '코드 체계의 각 자릿수 의미', NULL, NULL, 'product_classification', 0, 7, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_1_1, '기존 시스템(ERP/엑셀)에서 사용하는 제품 분류 방식을 캡처하여 업로드해주세요', 'file_upload', NULL, NULL, NULL, NULL, 'product_classification', 0, 8, 1, @user_id, @user_id, @now, @now); - --- 템플릿 1.2: 설치 유형별 분류 -INSERT INTO interview_templates (tenant_id, interview_category_id, name, sort_order, is_active, created_by, updated_by, created_at, updated_at) -VALUES (@tenant_id, @cat_1, '설치 유형별 분류', 2, 1, @user_id, @user_id, @now, @now); -SET @tpl_1_2 = LAST_INSERT_ID(); - -INSERT INTO interview_questions (tenant_id, interview_template_id, question_text, question_type, options, ai_hint, expected_format, depends_on, domain, is_required, sort_order, is_active, created_by, updated_by, created_at, updated_at) VALUES -(@tenant_id, @tpl_1_2, '설치 유형(벽면형, 측면형, 혼합형 등)에 따라 견적이 달라지나요?', 'select', '{"choices":["예, 크게 달라짐","약간 달라짐","달라지지 않음"]}', NULL, NULL, NULL, 'product_classification', 0, 1, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_1_2, '각 설치 유형별로 어떤 부품이 달라지나요?', 'table_input', '{"columns":["설치유형","추가부품","제외부품","비고"]}', NULL, NULL, NULL, 'product_classification', 0, 2, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_1_2, '설치 유형에 따른 추가 비용 항목이 있나요?', 'text', NULL, NULL, NULL, NULL, 'product_classification', 0, 3, 1, @user_id, @user_id, @now, @now); - --- ============================================================ --- Domain 2: BOM 구조 (bom_structure) --- ============================================================ -INSERT INTO interview_categories (tenant_id, interview_project_id, parent_id, name, description, domain, sort_order, is_active, created_by, updated_by, created_at, updated_at) -VALUES (@tenant_id, NULL, @root_manufacturing, 'BOM 구조', '완제품-부품 관계, 부품 카테고리, BOM 레벨', 'bom_structure', 4, 1, @user_id, @user_id, @now, @now); -SET @cat_2 = LAST_INSERT_ID(); - --- 템플릿 2.1: 완제품-부품 관계 -INSERT INTO interview_templates (tenant_id, interview_category_id, name, sort_order, is_active, created_by, updated_by, created_at, updated_at) -VALUES (@tenant_id, @cat_2, '완제품-부품 관계', 1, 1, @user_id, @user_id, @now, @now); -SET @tpl_2_1 = LAST_INSERT_ID(); - -INSERT INTO interview_questions (tenant_id, interview_template_id, question_text, question_type, options, ai_hint, expected_format, depends_on, domain, is_required, sort_order, is_active, created_by, updated_by, created_at, updated_at) VALUES -(@tenant_id, @tpl_2_1, '대표 제품 1개의 완제품→부품 구성을 트리로 그려주세요', 'bom_tree', NULL, '최상위 제품부터 하위 부품까지 트리 구조', NULL, NULL, 'bom_structure', 1, 1, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_2_1, '모든 제품에 공통으로 들어가는 부품은 무엇인가요?', 'multi_select', '{"choices":["가이드레일","케이스","모터","제어기","브라켓","볼트/너트"]}', '직접 입력 가능', NULL, NULL, 'bom_structure', 0, 2, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_2_1, '제품별로 선택적(옵션)인 부품은 무엇인가요?', 'table_input', '{"columns":["제품명","옵션부품","적용조건"]}', NULL, NULL, NULL, 'bom_structure', 0, 3, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_2_1, 'BOM이 현재 엑셀로 관리되고 있나요? 파일을 업로드해주세요', 'file_upload', NULL, NULL, NULL, NULL, 'bom_structure', 0, 4, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_2_1, '하위 부품의 단계(레벨)는 최대 몇 단계인가요?', 'number', NULL, NULL, '단계', NULL, 'bom_structure', 0, 5, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_2_1, '부품 수량이 고정인 것과 계산이 필요한 것을 구분해주세요', 'table_input', '{"columns":["부품명","고정/계산","고정수량 또는 계산식"]}', NULL, NULL, NULL, 'bom_structure', 0, 6, 1, @user_id, @user_id, @now, @now); - --- 템플릿 2.2: 부품 카테고리 -INSERT INTO interview_templates (tenant_id, interview_category_id, name, sort_order, is_active, created_by, updated_by, created_at, updated_at) -VALUES (@tenant_id, @cat_2, '부품 카테고리', 2, 1, @user_id, @user_id, @now, @now); -SET @tpl_2_2 = LAST_INSERT_ID(); - -INSERT INTO interview_questions (tenant_id, interview_template_id, question_text, question_type, options, ai_hint, expected_format, depends_on, domain, is_required, sort_order, is_active, created_by, updated_by, created_at, updated_at) VALUES -(@tenant_id, @tpl_2_2, '부품을 카테고리로 분류하면 어떻게 나눠지나요? (본체, 절곡품, 전동부, 부자재 등)', 'text', NULL, '부품 분류 체계', NULL, NULL, 'bom_structure', 0, 1, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_2_2, '각 카테고리에 속하는 부품 목록을 정리해주세요', 'table_input', '{"columns":["카테고리","부품명","규격"]}', NULL, NULL, NULL, 'bom_structure', 0, 2, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_2_2, '외주 구매 부품과 자체 제작 부품의 구분이 있나요?', 'select', '{"choices":["있음","없음"]}', NULL, NULL, NULL, 'bom_structure', 0, 3, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_2_2, '부자재(볼트, 너트, 패킹 등)는 별도 관리하나요?', 'checkbox', NULL, NULL, NULL, NULL, 'bom_structure', 0, 4, 1, @user_id, @user_id, @now, @now); - --- ============================================================ --- Domain 3: 치수/변수 계산 (dimension_formula) --- ============================================================ -INSERT INTO interview_categories (tenant_id, interview_project_id, parent_id, name, description, domain, sort_order, is_active, created_by, updated_by, created_at, updated_at) -VALUES (@tenant_id, NULL, @root_manufacturing, '치수/변수 계산', '오픈 사이즈→제작 사이즈 변환, 파생 변수 계산', 'dimension_formula', 5, 1, @user_id, @user_id, @now, @now); -SET @cat_3 = LAST_INSERT_ID(); - --- 템플릿 3.1: 오픈 사이즈 → 제작 사이즈 -INSERT INTO interview_templates (tenant_id, interview_category_id, name, sort_order, is_active, created_by, updated_by, created_at, updated_at) -VALUES (@tenant_id, @cat_3, '오픈 사이즈 → 제작 사이즈', 1, 1, @user_id, @user_id, @now, @now); -SET @tpl_3_1 = LAST_INSERT_ID(); - -INSERT INTO interview_questions (tenant_id, interview_template_id, question_text, question_type, options, ai_hint, expected_format, depends_on, domain, is_required, sort_order, is_active, created_by, updated_by, created_at, updated_at) VALUES -(@tenant_id, @tpl_3_1, '고객이 입력하는 기본 치수 항목은 무엇인가요? (폭, 높이, 깊이 등)', 'multi_select', '{"choices":["폭(W)","높이(H)","깊이(D)","두께(T)","지름(Ø)"]}', NULL, NULL, NULL, 'dimension_formula', 1, 1, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_3_1, '오픈 사이즈에서 제작 사이즈로 변환할 때 더하는 마진값은?', 'formula_input', NULL, '예: W1 = W0 + 120, H1 = H0 + 50', 'mm', NULL, 'dimension_formula', 0, 2, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_3_1, '제품 카테고리별로 마진값이 다른가요?', 'table_input', '{"columns":["제품카테고리","W 마진(mm)","H 마진(mm)","비고"]}', NULL, NULL, NULL, 'dimension_formula', 0, 3, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_3_1, '면적(㎡) 계산 공식을 알려주세요', 'formula_input', NULL, '예: area = W1 * H1 / 1000000', '㎡', NULL, 'dimension_formula', 0, 4, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_3_1, '중량(kg) 계산 공식을 알려주세요', 'formula_input', NULL, '예: weight = area * 단위중량(kg/㎡)', 'kg', NULL, 'dimension_formula', 0, 5, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_3_1, '기타 파생 변수가 있나요? (예: 분할 개수, 절곡 길이 등)', 'table_input', '{"columns":["변수명","계산식","단위","비고"]}', NULL, NULL, NULL, 'dimension_formula', 0, 6, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_3_1, '치수 계산에 사용하는 엑셀 수식을 캡처해주세요', 'file_upload', NULL, NULL, NULL, NULL, 'dimension_formula', 0, 7, 1, @user_id, @user_id, @now, @now); - --- 템플릿 3.2: 변수 의존 관계 -INSERT INTO interview_templates (tenant_id, interview_category_id, name, sort_order, is_active, created_by, updated_by, created_at, updated_at) -VALUES (@tenant_id, @cat_3, '변수 의존 관계', 2, 1, @user_id, @user_id, @now, @now); -SET @tpl_3_2 = LAST_INSERT_ID(); - -INSERT INTO interview_questions (tenant_id, interview_template_id, question_text, question_type, options, ai_hint, expected_format, depends_on, domain, is_required, sort_order, is_active, created_by, updated_by, created_at, updated_at) VALUES -(@tenant_id, @tpl_3_2, '변수 간 의존 관계를 설명해주세요 (A는 B와 C로 계산)', 'text', NULL, '계산 순서와 변수 의존성', NULL, NULL, 'dimension_formula', 0, 1, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_3_2, '계산 순서가 중요한 변수가 있나요?', 'text', NULL, NULL, NULL, NULL, 'dimension_formula', 0, 2, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_3_2, '단위는 mm, m, kg 중 어떤 것을 기본으로 사용하나요?', 'select', '{"choices":["mm","m","cm","혼용"]}', NULL, NULL, NULL, 'dimension_formula', 0, 3, 1, @user_id, @user_id, @now, @now); - --- ============================================================ --- Domain 4: 부품 구성 상세 (component_config) --- ============================================================ -INSERT INTO interview_categories (tenant_id, interview_project_id, parent_id, name, description, domain, sort_order, is_active, created_by, updated_by, created_at, updated_at) -VALUES (@tenant_id, NULL, @root_manufacturing, '부품 구성 상세', '주요 부품별 규격, 선택 기준, 특수 구성', 'component_config', 6, 1, @user_id, @user_id, @now, @now); -SET @cat_4 = LAST_INSERT_ID(); - --- 템플릿 4.1: 주요 부품별 상세 -INSERT INTO interview_templates (tenant_id, interview_category_id, name, sort_order, is_active, created_by, updated_by, created_at, updated_at) -VALUES (@tenant_id, @cat_4, '주요 부품별 상세', 1, 1, @user_id, @user_id, @now, @now); -SET @tpl_4_1 = LAST_INSERT_ID(); - -INSERT INTO interview_questions (tenant_id, interview_template_id, question_text, question_type, options, ai_hint, expected_format, depends_on, domain, is_required, sort_order, is_active, created_by, updated_by, created_at, updated_at) VALUES -(@tenant_id, @tpl_4_1, '가이드레일의 표준 길이 규격은? (예: 1219, 2438, 3305mm)', 'table_input', '{"columns":["규격코드","길이(mm)","비고"]}', NULL, NULL, NULL, 'component_config', 0, 1, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_4_1, '가이드레일 길이 조합 규칙은? (어떤 길이를 몇 개 사용?)', 'text', NULL, '높이에 따른 가이드레일 조합 로직', NULL, NULL, 'component_config', 0, 2, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_4_1, '케이스(하우징) 크기별 규격과 부속품 차이를 설명해주세요', 'table_input', '{"columns":["케이스규격","적용조건","부속품"]}', NULL, NULL, NULL, 'component_config', 0, 3, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_4_1, '모터 용량 종류와 선택 기준은? (무게별? 면적별?)', 'table_input', '{"columns":["모터용량","적용범위(최소)","적용범위(최대)","단위"]}', '무게/면적 범위별 모터 매핑', NULL, NULL, 'component_config', 0, 4, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_4_1, '모터 전압 옵션은? (380V, 220V 등)', 'multi_select', '{"choices":["380V","220V","110V","DC 24V"]}', NULL, NULL, NULL, 'component_config', 0, 5, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_4_1, '제어기 종류와 선택 기준은? (노출형/매립형 등)', 'table_input', '{"columns":["제어기유형","적용조건","비고"]}', NULL, NULL, NULL, 'component_config', 0, 6, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_4_1, '절곡품(판재 가공) 목록과 각각의 치수 결정 방식은?', 'table_input', '{"columns":["절곡품명","치수결정방식","재질","두께(mm)"]}', NULL, NULL, NULL, 'component_config', 0, 7, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_4_1, '부자재(볼트, 너트, 패킹 등) 목록과 수량 결정 방식은?', 'table_input', '{"columns":["부자재명","규격","수량결정방식","기본수량"]}', NULL, NULL, NULL, 'component_config', 0, 8, 1, @user_id, @user_id, @now, @now); - --- 템플릿 4.2: 특수 구성 -INSERT INTO interview_templates (tenant_id, interview_category_id, name, sort_order, is_active, created_by, updated_by, created_at, updated_at) -VALUES (@tenant_id, @cat_4, '특수 구성', 2, 1, @user_id, @user_id, @now, @now); -SET @tpl_4_2 = LAST_INSERT_ID(); - -INSERT INTO interview_questions (tenant_id, interview_template_id, question_text, question_type, options, ai_hint, expected_format, depends_on, domain, is_required, sort_order, is_active, created_by, updated_by, created_at, updated_at) VALUES -(@tenant_id, @tpl_4_2, '연기차단재 등 특수 부품이 있나요? 적용 조건은?', 'text', NULL, NULL, NULL, NULL, 'component_config', 0, 1, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_4_2, '보강재(샤프트, 파이프, 앵글 등) 사용 조건은?', 'table_input', '{"columns":["보강재명","규격","적용조건","수량"]}', NULL, NULL, NULL, 'component_config', 0, 2, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_4_2, '고객 요청에 따라 추가/제외되는 옵션 부품은?', 'table_input', '{"columns":["옵션부품","추가/제외","추가비용","비고"]}', NULL, NULL, NULL, 'component_config', 0, 3, 1, @user_id, @user_id, @now, @now); - --- ============================================================ --- Domain 5: 단가 체계 (pricing_structure) --- ============================================================ -INSERT INTO interview_categories (tenant_id, interview_project_id, parent_id, name, description, domain, sort_order, is_active, created_by, updated_by, created_at, updated_at) -VALUES (@tenant_id, NULL, @root_manufacturing, '단가 체계', '단가 관리 방식, 계산 방식, 마진/LOSS율', 'pricing_structure', 7, 1, @user_id, @user_id, @now, @now); -SET @cat_5 = LAST_INSERT_ID(); - --- 템플릿 5.1: 단가 관리 방식 -INSERT INTO interview_templates (tenant_id, interview_category_id, name, sort_order, is_active, created_by, updated_by, created_at, updated_at) -VALUES (@tenant_id, @cat_5, '단가 관리 방식', 1, 1, @user_id, @user_id, @now, @now); -SET @tpl_5_1 = LAST_INSERT_ID(); - -INSERT INTO interview_questions (tenant_id, interview_template_id, question_text, question_type, options, ai_hint, expected_format, depends_on, domain, is_required, sort_order, is_active, created_by, updated_by, created_at, updated_at) VALUES -(@tenant_id, @tpl_5_1, '부품별 단가를 어디서 관리하나요? (엑셀, ERP, 구두 등)', 'select', '{"choices":["엑셀","ERP 시스템","구두/경험","기타"]}', NULL, NULL, NULL, 'pricing_structure', 0, 1, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_5_1, '단가표 파일을 업로드해주세요', 'file_upload', NULL, NULL, NULL, NULL, 'pricing_structure', 0, 2, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_5_1, '단가 변경 주기는? (월/분기/연 등)', 'select', '{"choices":["수시","월 단위","분기 단위","반기 단위","연 단위"]}', NULL, NULL, NULL, 'pricing_structure', 0, 3, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_5_1, '단가에 포함되는 항목은? (재료비만? 가공비 포함?)', 'multi_select', '{"choices":["재료비","가공비","운송비","설치비","마진"]}', NULL, NULL, NULL, 'pricing_structure', 0, 4, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_5_1, '고객별/거래처별 차등 단가가 있나요?', 'select', '{"choices":["있음 (등급별)","있음 (거래처별)","없음 (일괄 동일)"]}', NULL, NULL, NULL, 'pricing_structure', 0, 5, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_5_1, 'LOSS율(손실률)을 적용하나요? 적용 방식은?', 'formula_input', NULL, '예: 실제수량 = 계산수량 × (1 + LOSS율)', '%', NULL, 'pricing_structure', 0, 6, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_5_1, '마진율 설정 방식은? (일괄? 품목별?)', 'select', '{"choices":["일괄 마진율","품목별 마진율","카테고리별 마진율","고객별 마진율"]}', NULL, NULL, NULL, 'pricing_structure', 0, 7, 1, @user_id, @user_id, @now, @now); - --- 템플릿 5.2: 단가 계산 방식 -INSERT INTO interview_templates (tenant_id, interview_category_id, name, sort_order, is_active, created_by, updated_by, created_at, updated_at) -VALUES (@tenant_id, @cat_5, '단가 계산 방식', 2, 1, @user_id, @user_id, @now, @now); -SET @tpl_5_2 = LAST_INSERT_ID(); - -INSERT INTO interview_questions (tenant_id, interview_template_id, question_text, question_type, options, ai_hint, expected_format, depends_on, domain, is_required, sort_order, is_active, created_by, updated_by, created_at, updated_at) VALUES -(@tenant_id, @tpl_5_2, '면적 기반 단가 품목은? (원/㎡)', 'table_input', '{"columns":["품목명","단가(원/㎡)","비고"]}', NULL, '원/㎡', NULL, 'pricing_structure', 0, 1, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_5_2, '중량 기반 단가 품목은? (원/kg)', 'table_input', '{"columns":["품목명","단가(원/kg)","비고"]}', NULL, '원/kg', NULL, 'pricing_structure', 0, 2, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_5_2, '수량 기반 단가 품목은? (원/EA)', 'table_input', '{"columns":["품목명","단가(원/EA)","비고"]}', NULL, '원/EA', NULL, 'pricing_structure', 0, 3, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_5_2, '길이 기반 단가 품목은? (원/m)', 'table_input', '{"columns":["품목명","단가(원/m)","비고"]}', NULL, '원/m', NULL, 'pricing_structure', 0, 4, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_5_2, '기타 특수 단가 계산 방식이 있나요?', 'text', NULL, NULL, NULL, NULL, 'pricing_structure', 0, 5, 1, @user_id, @user_id, @now, @now); - --- ============================================================ --- Domain 6: 수량 수식 (quantity_formula) --- ============================================================ -INSERT INTO interview_categories (tenant_id, interview_project_id, parent_id, name, description, domain, sort_order, is_active, created_by, updated_by, created_at, updated_at) -VALUES (@tenant_id, NULL, @root_manufacturing, '수량 수식', '부품별 수량 결정 규칙, 계산식, 검증', 'quantity_formula', 8, 1, @user_id, @user_id, @now, @now); -SET @cat_6 = LAST_INSERT_ID(); - --- 템플릿 6.1: 수량 결정 규칙 -INSERT INTO interview_templates (tenant_id, interview_category_id, name, sort_order, is_active, created_by, updated_by, created_at, updated_at) -VALUES (@tenant_id, @cat_6, '수량 결정 규칙', 1, 1, @user_id, @user_id, @now, @now); -SET @tpl_6_1 = LAST_INSERT_ID(); - -INSERT INTO interview_questions (tenant_id, interview_template_id, question_text, question_type, options, ai_hint, expected_format, depends_on, domain, is_required, sort_order, is_active, created_by, updated_by, created_at, updated_at) VALUES -(@tenant_id, @tpl_6_1, '고정 수량 부품 목록 (항상 1개, 2개 등)', 'table_input', '{"columns":["부품명","고정수량","비고"]}', NULL, NULL, NULL, 'quantity_formula', 0, 1, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_6_1, '치수 기반 수량 계산 부품과 수식', 'formula_input', NULL, '예: 슬랫수량 = CEIL(H1 / 슬랫피치)', NULL, NULL, 'quantity_formula', 0, 2, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_6_1, '면적 기반 수량 계산 부품과 수식', 'formula_input', NULL, '예: 스크린수량 = area / 기준면적', NULL, NULL, 'quantity_formula', 0, 3, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_6_1, '중량 기반 수량 계산 부품과 수식', 'formula_input', NULL, NULL, NULL, NULL, 'quantity_formula', 0, 4, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_6_1, '올림/내림/반올림 규칙이 있는 계산은?', 'table_input', '{"columns":["계산항목","올림/내림/반올림","소수점자릿수"]}', NULL, NULL, NULL, 'quantity_formula', 0, 5, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_6_1, '여유 수량(LOSS) 적용 품목과 비율은?', 'table_input', '{"columns":["품목명","LOSS율(%)","비고"]}', NULL, NULL, NULL, 'quantity_formula', 0, 6, 1, @user_id, @user_id, @now, @now); - --- 템플릿 6.2: 수식 검증 -INSERT INTO interview_templates (tenant_id, interview_category_id, name, sort_order, is_active, created_by, updated_by, created_at, updated_at) -VALUES (@tenant_id, @cat_6, '수식 검증', 2, 1, @user_id, @user_id, @now, @now); -SET @tpl_6_2 = LAST_INSERT_ID(); - -INSERT INTO interview_questions (tenant_id, interview_template_id, question_text, question_type, options, ai_hint, expected_format, depends_on, domain, is_required, sort_order, is_active, created_by, updated_by, created_at, updated_at) VALUES -(@tenant_id, @tpl_6_2, '실제 견적서에서 수량 계산 예시를 보여주세요 (W=3000, H=2500일 때)', 'table_input', '{"columns":["부품명","수식","계산결과","단위"]}', NULL, NULL, NULL, 'quantity_formula', 1, 1, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_6_2, '수식에 사용하는 함수가 있나요? (SUM, CEIL, ROUND 등)', 'multi_select', '{"choices":["CEIL (올림)","FLOOR (내림)","ROUND (반올림)","MAX","MIN","IF 조건문","SUM"]}', NULL, NULL, NULL, 'quantity_formula', 0, 2, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_6_2, '조건에 따라 수식이 달라지는 경우가 있나요?', 'text', NULL, '예: 폭이 3000 초과이면 분할 계산', NULL, NULL, 'quantity_formula', 0, 3, 1, @user_id, @user_id, @now, @now); - --- ============================================================ --- Domain 7: 조건부 로직 (conditional_logic) --- ============================================================ -INSERT INTO interview_categories (tenant_id, interview_project_id, parent_id, name, description, domain, sort_order, is_active, created_by, updated_by, created_at, updated_at) -VALUES (@tenant_id, NULL, @root_manufacturing, '조건부 로직', '범위/매핑 기반 부품 자동 선택 규칙', 'conditional_logic', 9, 1, @user_id, @user_id, @now, @now); -SET @cat_7 = LAST_INSERT_ID(); - --- 템플릿 7.1: 범위 기반 선택 -INSERT INTO interview_templates (tenant_id, interview_category_id, name, sort_order, is_active, created_by, updated_by, created_at, updated_at) -VALUES (@tenant_id, @cat_7, '범위 기반 선택', 1, 1, @user_id, @user_id, @now, @now); -SET @tpl_7_1 = LAST_INSERT_ID(); - -INSERT INTO interview_questions (tenant_id, interview_template_id, question_text, question_type, options, ai_hint, expected_format, depends_on, domain, is_required, sort_order, is_active, created_by, updated_by, created_at, updated_at) VALUES -(@tenant_id, @tpl_7_1, '무게 범위별 모터 용량 선택표를 작성해주세요', 'price_table', '{"columns":["범위 시작(kg)","범위 끝(kg)","모터용량","비고"]}', NULL, NULL, NULL, 'conditional_logic', 1, 1, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_7_1, '크기 범위별 부품 자동 선택 규칙이 있나요?', 'table_input', '{"columns":["조건(변수)","범위","선택부품","비고"]}', NULL, NULL, NULL, 'conditional_logic', 0, 2, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_7_1, '브라켓 크기 결정 기준은?', 'table_input', '{"columns":["조건","범위","브라켓 규격"]}', NULL, NULL, NULL, 'conditional_logic', 0, 3, 1, @user_id, @user_id, @now, @now); - --- 템플릿 7.2: 매핑 기반 선택 -INSERT INTO interview_templates (tenant_id, interview_category_id, name, sort_order, is_active, created_by, updated_by, created_at, updated_at) -VALUES (@tenant_id, @cat_7, '매핑 기반 선택', 2, 1, @user_id, @user_id, @now, @now); -SET @tpl_7_2 = LAST_INSERT_ID(); - -INSERT INTO interview_questions (tenant_id, interview_template_id, question_text, question_type, options, ai_hint, expected_format, depends_on, domain, is_required, sort_order, is_active, created_by, updated_by, created_at, updated_at) VALUES -(@tenant_id, @tpl_7_2, '제품 모델 → 기본 부품 세트 매핑표', 'table_input', '{"columns":["제품모델","기본부품1","기본부품2","기본부품3"]}', NULL, NULL, NULL, 'conditional_logic', 0, 1, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_7_2, '설치 유형 → 추가 부품 매핑표', 'table_input', '{"columns":["설치유형","추가부품","수량","비고"]}', NULL, NULL, NULL, 'conditional_logic', 0, 2, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_7_2, '제어기 유형 → 부속품 매핑표', 'table_input', '{"columns":["제어기유형","부속품1","부속품2","부속품3"]}', NULL, NULL, NULL, 'conditional_logic', 0, 3, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_7_2, '기타 조건부 자동 선택 규칙', 'text', NULL, '위 항목에 해당하지 않는 조건-결과 매핑', NULL, NULL, 'conditional_logic', 0, 4, 1, @user_id, @user_id, @now, @now); - --- ============================================================ --- Domain 8: 견적서 양식 (quote_format) --- ============================================================ -INSERT INTO interview_categories (tenant_id, interview_project_id, parent_id, name, description, domain, sort_order, is_active, created_by, updated_by, created_at, updated_at) -VALUES (@tenant_id, NULL, @root_manufacturing, '견적서 양식', '출력 양식, 항목 그룹, 소계/합계 구조', 'quote_format', 10, 1, @user_id, @user_id, @now, @now); -SET @cat_8 = LAST_INSERT_ID(); - --- 템플릿 8.1: 출력 양식 -INSERT INTO interview_templates (tenant_id, interview_category_id, name, sort_order, is_active, created_by, updated_by, created_at, updated_at) -VALUES (@tenant_id, @cat_8, '출력 양식', 1, 1, @user_id, @user_id, @now, @now); -SET @tpl_8_1 = LAST_INSERT_ID(); - -INSERT INTO interview_questions (tenant_id, interview_template_id, question_text, question_type, options, ai_hint, expected_format, depends_on, domain, is_required, sort_order, is_active, created_by, updated_by, created_at, updated_at) VALUES -(@tenant_id, @tpl_8_1, '현재 사용 중인 견적서 양식을 업로드해주세요', 'file_upload', NULL, NULL, NULL, NULL, 'quote_format', 1, 1, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_8_1, '견적서에 표시되는 항목 그룹은? (재료비, 노무비, 설치비 등)', 'multi_select', '{"choices":["재료비","노무비","경비","설치비","운반비","이윤","부가세"]}', NULL, NULL, NULL, 'quote_format', 0, 2, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_8_1, '소계/합계 계산 구조를 설명해주세요', 'text', NULL, '항목 그룹별 소계와 최종 합계의 관계', NULL, NULL, 'quote_format', 0, 3, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_8_1, '할인 적용 방식은? (일괄? 항목별?)', 'select', '{"choices":["일괄 할인","항목별 할인","할인 없음","협의 할인"]}', NULL, NULL, NULL, 'quote_format', 0, 4, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_8_1, '부가세 표시 방식은? (별도? 포함?)', 'select', '{"choices":["별도 표시","포함 표시","선택 가능"]}', NULL, NULL, NULL, 'quote_format', 0, 5, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_8_1, '견적서에 표시하지 않는 내부 관리 항목은?', 'text', NULL, NULL, NULL, NULL, 'quote_format', 0, 6, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_8_1, '견적 번호 체계를 알려주세요', 'text', NULL, '예: Q-2026-001 형식', NULL, NULL, 'quote_format', 0, 7, 1, @user_id, @user_id, @now, @now); - --- 템플릿 8.2: 특수 요구사항 -INSERT INTO interview_templates (tenant_id, interview_category_id, name, sort_order, is_active, created_by, updated_by, created_at, updated_at) -VALUES (@tenant_id, @cat_8, '특수 요구사항', 2, 1, @user_id, @user_id, @now, @now); -SET @tpl_8_2 = LAST_INSERT_ID(); - -INSERT INTO interview_questions (tenant_id, interview_template_id, question_text, question_type, options, ai_hint, expected_format, depends_on, domain, is_required, sort_order, is_active, created_by, updated_by, created_at, updated_at) VALUES -(@tenant_id, @tpl_8_2, '산출내역서(세부 내역)를 별도로 제공하나요?', 'checkbox', NULL, NULL, NULL, NULL, 'quote_format', 0, 1, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_8_2, '위치별(층/부호) 개별 산출이 필요한가요?', 'checkbox', NULL, NULL, NULL, NULL, 'quote_format', 0, 2, 1, @user_id, @user_id, @now, @now), -(@tenant_id, @tpl_8_2, '일괄 산출(여러 위치 합산)을 사용하나요?', 'checkbox', NULL, NULL, NULL, NULL, 'quote_format', 0, 3, 1, @user_id, @user_id, @now, @now); - --- ============================================================ --- 완료 확인 --- ============================================================ -SELECT - (SELECT COUNT(*) FROM interview_categories WHERE interview_project_id IS NULL AND domain IS NOT NULL) AS master_categories, - (SELECT COUNT(*) FROM interview_templates t JOIN interview_categories c ON t.interview_category_id = c.id WHERE c.interview_project_id IS NULL AND c.domain IS NOT NULL) AS master_templates, - (SELECT COUNT(*) FROM interview_questions q JOIN interview_templates t ON q.interview_template_id = t.id JOIN interview_categories c ON t.interview_category_id = c.id WHERE c.interview_project_id IS NULL AND c.domain IS NOT NULL) AS master_questions; diff --git a/sam/docs/features/academy/fire-shutter-image-prompts.md b/sam/docs/features/academy/fire-shutter-image-prompts.md deleted file mode 100644 index 1614eda..0000000 --- a/sam/docs/features/academy/fire-shutter-image-prompts.md +++ /dev/null @@ -1,369 +0,0 @@ -# 방화셔터 백과사전 이미지 생성 프롬프트 - -> **작성일**: 2026-02-22 -> **상태**: 확정 -> **용도**: Google Gemini (Nano Banana Pro) 이미지 생성용 - ---- - -## 1. 개요 - -### 1.1 목적 - -MNG 아카데미 > 방화셔터 백과사전 페이지에 삽입할 기술 일러스트레이션을 AI 이미지 생성 도구(Google Gemini)로 제작하기 위한 프롬프트 모음이다. - -### 1.2 사용 방법 - -1. Google Gemini (Nano Banana Pro 모델)에서 프롬프트를 입력한다 -2. 생성된 이미지를 `mng/public/images/academy/fire-shutter/` 경로에 저장한다 -3. Blade 뷰에서 `` 태그로 참조한다 - -### 1.3 주의사항 - -- **화면 내 모든 라벨은 영어**로 작성되어 있다 (한글 텍스트는 AI 이미지 생성 시 깨짐 현상 발생) -- 전체 구성도, 설치 장면 등 넓은 이미지는 **16:9** 비율 권장 -- 단면도, 부품 상세 등은 **1:1** 또는 **4:3** 비율 권장 -- 생성 실패 시 프롬프트 앞에 `Detailed technical engineering illustration, clean white background, ` 를 추가한다 - ---- - -## 2. 프롬프트 목록 - -### 2.1 방화셔터 전체 구성도 (Full Component Diagram) - -``` -Technical illustration of a fire shutter (automatic fire-rated rolling shutter) installed in a building opening, cutaway side view showing all components with English labels. - -Show these parts clearly labeled: -- Top: "CEILING SLAB" with "HEAD BOX / CASE" mounted below -- Inside head box: "SHAFT" with coiled steel slats, "BALANCE SPRING", "GEAR BOX", "MOTOR", "ELECTROMAGNETIC BRAKE", "BRACKET" on both sides -- Both sides: vertical "GUIDE RAIL" mounted on fireproof walls with "ANCHOR BOLTS" -- Center: multiple horizontal "STEEL SLATS" hanging down in interlocking pattern -- Bottom: "BOTTOM BAR" touching the floor with rubber seal -- Nearby wall: "MANUAL CONTROL BOX" with UP/STOP/DOWN buttons -- Ceiling: "SMOKE DETECTOR" and "HEAT DETECTOR" -- Wall-mounted: "FIRE SHUTTER CONTROLLER" - -Style: Clean technical cutaway diagram, white background, professional engineering illustration, labeled with arrows pointing to each component. Color-coded: structural parts in gray/silver, electrical parts in blue, safety parts in red. Isometric or 3/4 perspective view. -``` - ---- - -### 2.2 슬랫 인터록킹 구조 (Slat Interlocking) - -``` -Technical cross-section illustration showing how fire shutter steel slats interlock with each other. - -Show 3-4 slats connected in interlocking pattern: -- Each slat is a C-shaped or S-shaped profile made from 1.6mm EGI steel -- The curved edges of adjacent slats hook into each other, allowing flexibility while maintaining a continuous curtain surface -- One slat highlighted with dimension labels: "THICKNESS 1.6mm", "PITCH 75-100mm" -- Show the slight curved profile that allows the slat to wrap around the shaft when rolled up -- Arrow labeled "ROLLING DIRECTION" - -Label each part: "SLAT", "INTERLOCKING JOINT", "EGI STEEL 1.6mm" - -Style: Clean engineering cross-section diagram, white background, metallic silver color for steel. Include dimension lines. Zoomed-in detail view with magnified interlocking joint area in a callout circle. -``` - ---- - -### 2.3 가이드레일 단면도 (Guide Rail Cross-Section) - -``` -Technical cross-section illustration of a fire shutter guide rail mounted on a fireproof wall, viewed from top-down. - -Show the C-channel shaped guide rail: -- C-channel profile, steel thickness 2.3mm+ -- Inside the channel: slat edge sitting in the groove -- Smoke seal material strips on both sides of the channel, pressing against the slat -- Anchor bolts securing the guide rail to the concrete wall -- Wall shown as hatched concrete pattern - -Labels with arrows: -- "GUIDE RAIL BODY (C-CHANNEL)" -- "SLAT EDGE" -- "SMOKE SEAL PACKING" -- "ANCHOR BOLT" -- "FIREPROOF WALL" -- "STEEL 2.3mm+" - -Style: Clean technical cross-section, white background, steel parts in metallic gray, seal material in orange/red, wall in light brown hatched pattern. Include dimension annotations. -``` - ---- - -### 2.4 샤프트 어셈블리 (Shaft Assembly) - -``` -Technical illustration showing the inside of a fire shutter head box, exploded or cutaway view. - -Show these components assembled on or around the shaft: -- Central pipe labeled "SHAFT" with slats attached, partially wound -- Left side: "BRACKET" steel plate bolted to wall, with "BEARING" supporting shaft end -- Right side: "GEAR BOX" and "MOTOR" mounted on bracket -- "ELECTROMAGNETIC BRAKE" attached to motor assembly -- "BALANCE SPRING" torsion spring visible inside the shaft -- "AUTO CLOSER" device mounted near the brake -- "LIMIT SWITCH" small switches with actuator arms -- "HEAD BOX CASE" shown as transparent or partially removed to reveal internals -- Wiring connections going down labeled "TO CONTROLLER" - -Style: Exploded technical diagram or cutaway 3D illustration, white background, professional engineering style. Color-coded: mechanical parts in silver/gray, motor in dark blue, brake in red, spring in green. All labels in English with leader lines. -``` - ---- - -### 2.5 감속기+모터+브레이크 (Gear Box + Motor + Brake Assembly) - -``` -Technical illustration of a fire shutter drive unit assembly, showing three main components connected together. - -Show them assembled in sequence with labels: -1. "MOTOR (220V)" - cylindrical body with power cables -2. "ELECTROMAGNETIC BRAKE" - disc-type brake between motor and gearbox, showing brake disc, coil, and spring -3. "WORM GEAR BOX" - rectangular housing with cutaway revealing the worm gear and worm wheel inside - -Assembly order shown with arrows: MOTOR → BRAKE → GEAR BOX → "OUTPUT TO SHAFT" -Include rotation direction arrows - -Small inset callout showing worm gear mechanism detail labeled: "WORM", "WORM WHEEL", "SELF-LOCKING" - -Style: Technical exploded/assembly diagram, white background, metallic rendering, engineering illustration style. -``` - ---- - -### 2.6 연동제어기 시스템 (Controller System) - -``` -Technical schematic diagram showing the fire shutter interlock control system wiring and signal flow. - -Layout (block diagram style): -- Top center: "FIRE ALARM PANEL" - rectangular box -- Left: "SMOKE DETECTOR (PHOTOELECTRIC)" - circular device on ceiling -- Right: "HEAT DETECTOR (FIXED TEMP.)" - circular device on ceiling -- Center: "FIRE SHUTTER CONTROLLER" - panel with LED indicators labeled "POWER", "PARTIAL CLOSE", "FULL CLOSE" -- Below controller: "AUTO CLOSER" connected to shutter mechanism -- Bottom left: "MANUAL CONTROL BOX" with "UP / STOP / DOWN" buttons -- Bottom: "FIRE SHUTTER" shown schematically - -Signal flow arrows with labels: -- Smoke detector → Controller: "STAGE 1: PARTIAL CLOSE (1m gap)" -- Heat detector → Controller: "STAGE 2: FULL CLOSE (floor sealed)" -- Controller → Auto closer: "CLOSE COMMAND" -- Controller → Speaker icon: "ALARM OUTPUT" -- Controller ↔ Fire alarm panel: "STATUS SIGNAL" - -Style: Clean schematic/block diagram, white background, professional electrical diagram style. Color coding: red for fire signals, blue for power, green for status. All labels in English. -``` - ---- - -### 2.7 2단계 폐쇄 시퀀스 (2-Stage Closure Sequence) - -``` -Technical illustration showing the two-stage closing sequence of an automatic fire shutter, presented as 3 side-by-side panels: - -Panel 1 - Title: "NORMAL (OPEN)": -- Fire shutter fully open, rolled up inside head box -- People walking through the opening freely -- Smoke and heat detectors on ceiling shown in standby (green LED) -- Caption: "Shutter open, passage clear" - -Panel 2 - Title: "STAGE 1: PARTIAL CLOSE": -- Smoke detector activated (red LED, smoke wisps shown) -- Shutter descended leaving about 1 meter gap from floor -- A person crouching to pass under the gap -- Alarm buzzer icon showing sound waves -- Caption: "Smoke detected → Partial close, 1m gap for evacuation" - -Panel 3 - Title: "STAGE 2: FULL CLOSE": -- Heat detector activated (red LED, flames shown) -- Shutter fully closed to floor, bottom bar sealed against floor -- Fire and smoke on one side, clean air on other side -- Caption: "Heat detected → Full close, fire/smoke blocked" - -Arrow at bottom labeled "TIME SEQUENCE →" - -Style: Clean technical illustration with slight architectural rendering, sequential format left to right, white background. People as simple silhouettes. Fire/smoke rendered subtly. -``` - ---- - -### 2.8 롤포밍 공정 (Roll Forming Process) - -``` -Technical illustration showing the roll forming manufacturing process for fire shutter steel slats, production line viewed from the side. - -Show the line from left to right with labels: -1. "UNCOILER" - Steel coil (EGI 1.6mm) being unrolled -2. "LEVELER" - Flattening rollers correcting coil curvature -3. "ROLL FORMING STATION" - 6-8 pairs of forming rollers progressively shaping the flat strip into C/S-shaped slat profile -4. "CUTTING STATION" - Flying shear cutting the formed strip to length -5. "FINISHED SLATS" - Slats stacked neatly on output table - -Detail callout at top showing progressive cross-section shape changes: "FLAT → STAGE 1 → STAGE 2 → STAGE 3 → FINAL PROFILE" - -Arrow at bottom: "MATERIAL FLOW →" -Label on coil: "EGI STEEL COIL 1.6mm" - -Style: Technical factory/manufacturing illustration, clean white background, machinery in industrial gray/green, steel in silver. Side view. Directional arrows showing material flow. -``` - ---- - -### 2.9 현장 설치 (Field Installation) - -``` -Technical illustration showing fire shutter installation at a construction site, depicting key installation steps in a single scene. - -Scene showing a large building opening (about 5m wide, 4m tall) with: -- Two workers on scaffolding installing the head box assembly at the top -- Brackets already bolted to both side walls near the ceiling -- Guide rails mounted vertically on walls with anchor bolts -- Shaft with wound slat curtain being lifted up to place on brackets -- Manual control box being mounted on adjacent wall -- Wiring conduits visible running from controller to head box -- Construction tools: level tool, drill, anchor bolts, wrenches - -Labels with arrows pointing to activities: -- "BRACKET MOUNTING" -- "GUIDE RAIL ANCHORING" -- "SHAFT PLACEMENT" -- "ELECTRICAL WIRING" -- "LEVEL CHECK" -- "ANCHOR BOLT FIXING" - -Style: Technical construction illustration, slightly warm tone, realistic building interior with exposed concrete. Workers wearing safety helmets and vests. Clean architectural illustration style. All text in English. -``` - ---- - -### 2.10 유지보수 점검 (Maintenance Inspection) - -``` -Technical illustration showing fire shutter maintenance inspection scene. - -Show a maintenance technician inspecting a fire shutter: -- Technician with safety vest and hard hat, holding a tablet -- Fire shutter partially lowered (halfway) for testing -- Close-up callout bubbles showing key inspection points: - 1. "SLAT CONDITION" - checking for deformation, rust - 2. "SMOKE SEAL CHECK" - checking guide rail seal condition - 3. "BOTTOM BAR PACKING" - checking floor seal - 4. "MOTOR / BRAKE CHECK" - head box open, listening for sounds - 5. "MANUAL BOX TEST" - pressing UP/STOP/DOWN buttons - 6. "CONTROLLER STATUS" - checking LED indicators - -Checklist overlay in corner: -☑ MOTOR OPEN/CLOSE TEST -☑ DETECTOR INTERLOCK TEST -☑ ALARM SOUND CHECK -☑ MANUAL OPERATION CHECK -☑ BOTTOM BAR SEAL CHECK - -Style: Clean technical illustration, bright well-lit building interior, professional maintenance scene. Color callout bubbles with icons. All text in English. -``` - ---- - -### 2.11 강판형 vs 스크린형 (Steel Plate vs Screen Type) - -``` -Technical side-by-side comparison illustration of two types of fire shutters in similar building openings: - -Left side - Title "STEEL PLATE TYPE": -- Steel slat fire shutter in partially closed position -- Opaque metallic surface of interlocking steel slats visible -- Heavier, industrial appearance with thick guide rails -- Bottom bar with rubber seal -- Callout: "EGI STEEL 1.6mm / HEAVY / OPAQUE / HIGH SEALING" - -Right side - Title "SCREEN / FABRIC TYPE": -- Fabric fire shutter in partially closed position -- Semi-transparent woven silica fiber screen, you can faintly see light through it -- Lighter, sleeker with thin guide rails (11mm) -- Fabric gathered at top -- Callout: "SILICA FIBER / LIGHTWEIGHT / SEMI-TRANSPARENT / RAIL 11mm" - -Center dividing line with "VS" label -Bottom comparison bar: "WEIGHT: Heavy vs Light | VISIBILITY: Opaque vs See-through | RAIL WIDTH: Wide vs 11mm" - -Style: Clean technical comparison, white background, same scale, professional product comparison layout. All text in English. -``` - ---- - -### 2.12 주요 고장 유형 (Major Fault Types) - -``` -Technical illustration showing 6 common fire shutter failure types in a 2x3 grid layout, each in its own panel with a red problem highlight: - -Panel 1 - "SLAT DERAILMENT": -- A slat edge coming out of the guide rail groove, curtain jammed -- Red circle on problem area - -Panel 2 - "MOTOR BURNOUT": -- Motor with smoke marks, burnt wiring -- Overheat warning symbol - -Panel 3 - "BRAKE PAD WEAR": -- Electromagnetic brake with worn disc pad -- Side comparison: "NEW" thick pad vs "WORN" thin pad - -Panel 4 - "CONTROLLER MALFUNCTION": -- Controller panel with error LED, disconnected wires -- Broken signal path indicator - -Panel 5 - "CLOSER SPEED FAULT": -- Shutter dropping fast, speedometer showing "0.15 m/s LIMIT EXCEEDED" -- Governor mechanism detail - -Panel 6 - "SMOKE SEAL FAILURE": -- Smoke wisps leaking through guide rail gaps -- Comparison: "NEW SEAL" vs "DEGRADED SEAL" - -Style: Technical diagnostic illustration, white background, bordered panels. Problem areas in red/orange highlight. Clean maintenance manual style. All titles and labels in English. -``` - ---- - -## 3. 이미지 파일 관리 - -### 3.1 저장 경로 - -``` -mng/public/images/academy/fire-shutter/ -├── 01-full-component-diagram.png -├── 02-slat-interlocking.png -├── 03-guide-rail-cross-section.png -├── 04-shaft-assembly.png -├── 05-gearbox-motor-brake.png -├── 06-controller-system.png -├── 07-two-stage-closure.png -├── 08-roll-forming-process.png -├── 09-field-installation.png -├── 10-maintenance-inspection.png -├── 11-steel-vs-screen-type.png -└── 12-major-fault-types.png -``` - -### 3.2 Blade 참조 예시 - -```html -방화셔터 전체 구성도 -``` - ---- - -## 관련 문서 - -- `mng/resources/views/academy/fire-shutter.blade.php` - 방화셔터 백과사전 Blade 뷰 -- `mng/app/Http/Controllers/AcademyController.php` - 아카데미 컨트롤러 - ---- - -**최종 업데이트**: 2026-02-22 diff --git a/sam/docs/features/approvals/README.md b/sam/docs/features/approvals/README.md deleted file mode 100644 index a43521c..0000000 --- a/sam/docs/features/approvals/README.md +++ /dev/null @@ -1,298 +0,0 @@ -# 결재관리 시스템 - -> **작성일**: 2026-02-28 -> **상태**: Phase 2 구현 완료 -> **프로젝트**: SAM MNG (관리자 웹) -> **우선순위**: 🔴 필수 - ---- - -## 1. 개요 - -### 1.1 목적 - -SAM MNG 전자결재 시스템. 기안부터 최종 승인, 반려, 회수, 보류, 전결, 참조까지 기업 결재 프로세스를 디지털화한다. - -### 1.2 문서 구조 - -| 문서 | 설명 | -|------|------| -| **README.md** (이 문서) | 시스템 전체 개요, 아키텍처, 상태 관리 | -| [form-types.md](form-types.md) | 양식별 필드/JSON 구조/인터랙션 기술 명세 | -| [workflows.md](workflows.md) | 상세 워크플로우 (승인/반려/회수/보류/전결/복사재기안) | -| [api-reference.md](api-reference.md) | API 엔드포인트 명세 | -| [ui-screens.md](ui-screens.md) | 화면별 UI 구성 및 동작 | -| [db-changes-and-model-sync.md](db-changes-and-model-sync.md) | DB 변경사항 및 API/MNG 모델 동기화 현황 | - -### 1.3 구현 현황 - -| Phase | 범위 | 상태 | -|-------|------|------| -| **Phase 1** | 순차결재, 기안/상신/승인/반려/회수 | ✅ 완료 | -| **Phase 2** | 보류/해제, 전결, 참조 열람 추적, 복사 재기안 | ✅ 완료 | -| **Phase 3** | 병렬결재, 위임(대결), 알림 | 미착수 | -| **Phase 4** | ERP 연동, 결재 통계, 관리자 설정 | 미착수 | - ---- - -## 2. 아키텍처 - -### 2.1 기술 스택 - -| 계층 | 기술 | 설명 | -|------|------|------| -| 뷰 | Blade + HTMX + Alpine.js | 동적 UI, 부분 렌더링 | -| API | Laravel Controller + Service | JSON API (내부용) | -| 모델 | Eloquent ORM | Multi-tenant 스코프 | -| DB | MySQL 8.0 | API 프로젝트에서 마이그레이션 관리 | - -### 2.2 프로젝트 분리 - -``` -API (/home/aweso/sam/api) -├── database/migrations/ ← 모든 결재 테이블 마이그레이션 - -MNG (/home/aweso/sam/mng) -├── app/Models/Approvals/ ← 모델 (Approval, ApprovalStep, ApprovalForm, ApprovalLine, ApprovalDelegation) -├── app/Services/ ← ApprovalService (비즈니스 로직) -├── app/Http/Controllers/ ← ApprovalController (웹), ApprovalApiController (API) -├── resources/views/approvals/ ← Blade 뷰 -└── routes/ ← 웹 라우트 + API 라우트 -``` - -### 2.3 핵심 클래스 - -``` -ApprovalService -├── 목록 조회: getMyDrafts(), getPendingForMe(), getCompletedByMe(), getReferencesForMe() -├── CRUD: createApproval(), updateApproval(), deleteApproval(), getApproval() -├── 워크플로우: submit(), approve(), reject(), cancel(), hold(), releaseHold(), preDecide(), copyForRedraft() -├── 참조: markAsRead() -└── 유틸: getBadgeCounts(), getApprovalLines(), getApprovalForms(), saveApprovalSteps() -``` - ---- - -## 3. 데이터베이스 - -### 3.1 테이블 관계 - -``` -approval_forms (결재 양식) - │ 1:N - ▼ -approvals (결재 문서) - │ 1:N │ N:1 (self) - ▼ ▼ -approval_steps (결재 단계) approvals (parent_doc_id → 원본 문서) - -approval_lines (결재선 템플릿) ← approvals.line_id 참조 - -approval_delegations (위임 설정) ← Phase 3 준비 -``` - -### 3.2 approvals (결재 문서) - -| 컬럼 | 타입 | 설명 | -|------|------|------| -| `id` | BIGINT PK | | -| `tenant_id` | BIGINT | 테넌트 격리 | -| `document_number` | VARCHAR | `APR-YYMMDD-001` 형식 | -| `form_id` | BIGINT FK | 양식 | -| `line_id` | BIGINT FK NULL | 결재선 템플릿 | -| `title` | VARCHAR(200) | 제목 | -| `content` | JSON | 양식 필드 데이터 | -| `body` | TEXT NULL | 본문 | -| `status` | VARCHAR(20) | 문서 상태 (6가지) | -| `is_urgent` | BOOLEAN | 긴급 여부 | -| `drafter_id` | BIGINT FK | 기안자 | -| `department_id` | BIGINT FK NULL | 기안 부서 | -| `current_step` | INT | 현재 결재 단계 번호 | -| `drafted_at` | TIMESTAMP NULL | 상신 일시 | -| `completed_at` | TIMESTAMP NULL | 완료 일시 | -| `recall_reason` | TEXT NULL | 회수 사유 | -| `parent_doc_id` | BIGINT FK NULL | 재기안 원본 문서 | -| `attachments` | JSON NULL | 첨부파일 | - -### 3.3 approval_steps (결재 단계) - -| 컬럼 | 타입 | 설명 | -|------|------|------| -| `id` | BIGINT PK | | -| `approval_id` | BIGINT FK | 결재 문서 | -| `step_order` | INT | 순서 (1, 2, 3...) | -| `step_type` | VARCHAR | `approval`, `agreement`, `reference` | -| `parallel_group` | INT NULL | 병렬 그룹 (Phase 3) | -| `approver_id` | BIGINT FK | 결재자 | -| `acted_by` | BIGINT FK NULL | 실제 처리자 (대결 시) | -| `approver_name` | VARCHAR | 결재자명 스냅샷 | -| `approver_department` | VARCHAR | 부서 스냅샷 | -| `approver_position` | VARCHAR | 직급 스냅샷 | -| `status` | VARCHAR(20) | 단계 상태 (5가지) | -| `approval_type` | VARCHAR(20) | `normal`, `pre_decided`, `delegated` | -| `comment` | TEXT NULL | 결재 의견 | -| `acted_at` | TIMESTAMP NULL | 처리 일시 | -| `is_read` | BOOLEAN | 참조 열람 여부 | -| `read_at` | TIMESTAMP NULL | 열람 일시 | - -### 3.4 approval_delegations (위임 설정, Phase 3) - -| 컬럼 | 타입 | 설명 | -|------|------|------| -| `id` | BIGINT PK | | -| `tenant_id` | BIGINT FK | | -| `delegator_id` | BIGINT FK | 위임자 | -| `delegate_id` | BIGINT FK | 대리인 | -| `start_date` | DATE | 위임 시작일 | -| `end_date` | DATE | 위임 종료일 | -| `form_ids` | JSON NULL | 대상 양식 (NULL=전체) | -| `notify_delegator` | BOOLEAN | 대결 시 보고 여부 | -| `is_active` | BOOLEAN | 활성 여부 | -| `reason` | VARCHAR(200) | 위임 사유 | - ---- - -## 4. 상태 관리 - -### 4.1 문서 상태 (6가지) - -| 상태 | 코드 | 라벨 | 색상 | 설명 | -|------|------|------|------|------| -| 임시저장 | `draft` | 임시저장 | gray | 작성 중, 미상신 | -| 진행 | `pending` | 진행 | blue | 결재선 순환 중 | -| 완료 | `approved` | 완료 | green | 최종 승인 | -| 반려 | `rejected` | 반려 | red | 결재자가 반려 | -| 회수 | `cancelled` | 회수 | yellow | 기안자가 회수 | -| 보류 | `on_hold` | 보류 | amber | 결재자가 보류 | - -### 4.2 단계 상태 (5가지) - -| 상태 | 코드 | 라벨 | 아이콘 | 설명 | -|------|------|------|--------|------| -| 대기 | `pending` | 대기 | 숫자 | 차례 아직 아님 | -| 승인 | `approved` | 승인 | ✓ (녹색) | 승인 완료 | -| 반려 | `rejected` | 반려 | ✗ (적색) | 반려 | -| 건너뜀 | `skipped` | 건너뜀 | — (회색) | 전결/회수로 소멸 | -| 보류 | `on_hold` | 보류 | ⏸ (노란) | 보류 중 | - -### 4.3 결재 유형 (approval_type) - -| 유형 | 코드 | 아이콘 | 설명 | -|------|------|--------|------| -| 일반결재 | `normal` | ✓ | 기본 승인 | -| 전결 | `pre_decided` | ⚡ (남색) | 이후 단계 모두 건너뛰고 즉시 완료 | -| 대결 | `delegated` | — | 대리인이 처리 (Phase 3) | - -### 4.4 참여자 역할 (step_type) - -| 역할 | 코드 | 의사결정 | 설명 | -|------|------|---------|------| -| 결재 | `approval` | ✅ 있음 | 승인/반려/보류/전결 가능 | -| 합의 | `agreement` | ✅ 있음 | 타부서 동의 (승인/반려 가능) | -| 참조 | `reference` | ❌ 없음 | 열람만 가능, 열람 추적 | - -### 4.5 상태 전이 다이어그램 - -``` - ┌─────────────────────────────┐ - │ │ - ┌────────┐ submit() │ ┌─────────┐ │ - │ draft │────────────→│ │ pending │ │ - └────────┘ │ └────┬────┘ │ - ▲ │ │ │ - │ │ ┌────┼─────────┬───────┐ │ - │ (수정 후 재상신) │ │ │ │ │ │ - │ │ │ approve() reject() hold()│ - │ │ │ │ │ │ │ - │ │ │ ▼ ▼ ▼ │ - │ │ │ 다음 step rejected on_hold│ - │ │ │ 또는 │ │ │ - │ │ │ approved │ releaseHold() - │ │ │ │ │ │ │ - │ │ │ │ │ │ │ - │ │ └────┼────────┼───────┘ │ - │ │ │ │ │ - │ │ preDecide() │ │ - │ │ → approved │ │ - │ │ │ │ cancel() │ - │ │ │ │ │ │ - │ │ ▼ │ ▼ │ - │ │ ┌─────────┐ │ ┌──────────┐ - │ │ │approved │ │ │cancelled │ - │ │ └─────────┘ │ └──────────┘ - │ │ │ │ │ - │ │ │ │ │ - │ │ copyForRedraft() │ - │ │ │ │ │ - └───────────────────┼───────┴────────┘ │ - (새 draft 생성) │ │ - │ copyForRedraft() │ - │◀──────────────────────┘ - └─────────────────────────────┘ -``` - ---- - -## 5. 권한 매트릭스 - -### 5.1 누가 무엇을 할 수 있는가 - -| 액션 | 대상자 | 조건 | -|------|--------|------| -| **기안 작성** | 모든 사용자 | — | -| **수정** | 기안자 | `draft` 또는 `rejected` | -| **삭제** | 기안자 | `draft`만 | -| **상신** | 기안자 | `draft` 또는 `rejected`, 결재선 1명 이상 | -| **승인** | 현재 결재자 | `pending`, 자신이 현재 차례 | -| **반려** | 현재 결재자 | `pending`, 사유 필수 | -| **보류** | 현재 결재자 | `pending`, 사유 필수 | -| **보류 해제** | 보류한 결재자 | `on_hold`, 자신이 보류한 건 | -| **전결** | 현재 결재자 | `pending`, 이후 모든 단계 건너뜀 | -| **회수** | 기안자 | `pending` 또는 `on_hold`, 첫 결재자 미처리 | -| **복사 재기안** | 기안자 | `approved`, `rejected`, `cancelled` | -| **참조 열람** | 참조자 | `reference` step 보유 | - -### 5.2 회수 가능 조건 상세 - -``` -회수(cancel) 가능 여부 판단: - -1. 문서 상태가 pending 또는 on_hold인가? → 아니면 불가 -2. 요청자가 기안자(drafter_id)인가? → 아니면 불가 -3. 첫 번째 결재자(approval/agreement)의 상태가 pending 또는 on_hold인가? - → 이미 approved/rejected이면 불가 (첫 결재자가 이미 처리) -``` - ---- - -## 6. 메뉴 구조 - -``` -결재관리 -├── 기안함 /approval-mgmt/drafts ← 내가 기안한 문서 -├── 결재 대기함 /approval-mgmt/pending ← 내가 결재해야 할 문서 -├── 처리 완료함 /approval-mgmt/completed ← 내가 결재한 문서 -└── 참조함 /approval-mgmt/references ← 참조 문서 (열람 추적) -``` - -### 추가 페이지 - -| URL | 설명 | -|-----|------| -| `/approval-mgmt/create` | 기안 작성 | -| `/approval-mgmt/{id}` | 상세 조회 | -| `/approval-mgmt/{id}/edit` | 기안 수정 | - ---- - -## 7. 관련 문서 - -- [결재 양식 기술 명세](form-types.md) — 양식별 필드, JSON 구조, 인터랙션 -- [결재관리 워크플로우 상세](workflows.md) — 각 동작의 상세 흐름 -- [API 명세](api-reference.md) — 엔드포인트 목록 및 요청/응답 예시 -- [UI 화면 구성](ui-screens.md) — 화면별 UI 요소 및 동작 -- [기획서 원본](../../plans/approval-management-system-plan.md) — Phase 1~4 전체 기획 - ---- - -**최종 업데이트**: 2026-03-06 diff --git a/sam/docs/features/approvals/api-reference.md b/sam/docs/features/approvals/api-reference.md deleted file mode 100644 index b63e31b..0000000 --- a/sam/docs/features/approvals/api-reference.md +++ /dev/null @@ -1,594 +0,0 @@ -# 결재관리 API 명세 - -> **작성일**: 2026-02-28 -> **상태**: Phase 2 구현 완료 -> **Base URL**: `/api/admin/approvals` -> **미들웨어**: `web`, `auth`, `hq.member` -> **관련**: [README.md](README.md) | [워크플로우](workflows.md) | [UI 화면](ui-screens.md) - ---- - -## 1. 개요 - -모든 API는 JSON 응답을 반환한다. 인증은 세션 기반이며, CSRF 토큰이 필요하다. - -### 1.1 공통 응답 형식 - -**성공:** - -```json -{ - "success": true, - "message": "처리 메시지", - "data": { ... } -} -``` - -**실패 (400):** - -```json -{ - "success": false, - "message": "에러 메시지" -} -``` - -### 1.2 공통 헤더 - -``` -Content-Type: application/json -Accept: application/json -X-CSRF-TOKEN: {csrf_token} -``` - ---- - -## 2. 목록 조회 API - -### 2.1 기안함 - -내가 기안한 문서 목록을 조회한다. - -``` -GET /api/admin/approvals/drafts -``` - -**Query Parameters:** - -| 파라미터 | 타입 | 설명 | -|---------|------|------| -| `search` | string | 제목/문서번호 검색 | -| `status` | string | 상태 필터 (`draft`, `pending`, `approved`, `rejected`, `cancelled`, `on_hold`) | -| `is_urgent` | boolean | 긴급 문서만 | -| `date_from` | date | 시작일 (YYYY-MM-DD) | -| `date_to` | date | 종료일 (YYYY-MM-DD) | -| `per_page` | int | 페이지당 건수 (기본 15) | -| `page` | int | 페이지 번호 | - -**응답:** Laravel 페이지네이션 형식 - -```json -{ - "data": [ - { - "id": 1, - "document_number": "APR-260228-001", - "title": "휴가 신청", - "status": "pending", - "is_urgent": false, - "form": { "id": 1, "name": "휴가신청서" }, - "steps": [...], - "created_at": "2026-02-28T10:00:00", - "drafted_at": "2026-02-28T10:05:00" - } - ], - "current_page": 1, - "last_page": 3, - "per_page": 15, - "total": 42 -} -``` - ---- - -### 2.2 결재 대기함 - -내가 현재 결재해야 할 문서 목록을 조회한다. - -``` -GET /api/admin/approvals/pending -``` - -**Query Parameters:** - -| 파라미터 | 타입 | 설명 | -|---------|------|------| -| `search` | string | 제목/문서번호 검색 | -| `is_urgent` | boolean | 긴급 문서만 | -| `date_from` | date | 시작일 | -| `date_to` | date | 종료일 | -| `per_page` | int | 페이지당 건수 | - -> 현재 사용자가 결재 차례인 문서만 표시된다. 이미 승인/반려한 문서는 표시되지 않는다. - ---- - -### 2.3 처리 완료함 - -내가 승인 또는 반려한 문서 목록을 조회한다. - -``` -GET /api/admin/approvals/completed -``` - -**Query Parameters:** - -| 파라미터 | 타입 | 설명 | -|---------|------|------| -| `search` | string | 제목/문서번호 검색 | -| `status` | string | 상태 필터 | -| `date_from` | date | 시작일 | -| `date_to` | date | 종료일 | -| `per_page` | int | 페이지당 건수 | - ---- - -### 2.4 참조함 - -내가 참조자로 지정된 문서 목록을 조회한다. - -``` -GET /api/admin/approvals/references -``` - -**Query Parameters:** - -| 파라미터 | 타입 | 설명 | -|---------|------|------| -| `search` | string | 제목/문서번호 검색 | -| `is_read` | string | 열람 상태 필터 (`true`=열람완료, `false`=미열람) | -| `date_from` | date | 시작일 | -| `date_to` | date | 종료일 | -| `per_page` | int | 페이지당 건수 | - ---- - -## 3. CRUD API - -### 3.1 상세 조회 - -``` -GET /api/admin/approvals/{id} -``` - -**응답:** - -```json -{ - "success": true, - "data": { - "id": 1, - "tenant_id": 1, - "document_number": "APR-260228-001", - "form_id": 1, - "line_id": null, - "title": "휴가 신청", - "content": {}, - "body": "2월 27일~28일 연차 사용 신청합니다.", - "status": "pending", - "is_urgent": false, - "drafter_id": 10, - "department_id": 3, - "current_step": 2, - "drafted_at": "2026-02-28T10:05:00", - "completed_at": null, - "recall_reason": null, - "parent_doc_id": null, - "form": { "id": 1, "name": "휴가신청서" }, - "drafter": { "id": 10, "name": "홍길동" }, - "line": null, - "steps": [ - { - "id": 1, - "step_order": 1, - "step_type": "approval", - "approver_id": 20, - "approver_name": "김과장", - "approver_department": "경영지원팀", - "approver_position": "과장", - "status": "approved", - "approval_type": "normal", - "comment": "승인합니다.", - "acted_at": "2026-02-28T11:00:00", - "is_read": false, - "read_at": null - }, - { - "id": 2, - "step_order": 2, - "step_type": "approval", - "approver_id": 30, - "approver_name": "박부장", - "approver_department": "경영지원팀", - "approver_position": "부장", - "status": "pending", - "approval_type": "normal", - "comment": null, - "acted_at": null, - "is_read": false, - "read_at": null - } - ] - } -} -``` - ---- - -### 3.2 생성 (임시저장) - -``` -POST /api/admin/approvals -``` - -**Request Body:** - -```json -{ - "form_id": 1, - "title": "휴가 신청", - "body": "2월 27일~28일 연차 사용", - "is_urgent": false, - "steps": [ - { "user_id": 20, "step_type": "approval" }, - { "user_id": 30, "step_type": "approval" }, - { "user_id": 40, "step_type": "reference" } - ] -} -``` - -**Validation:** - -| 필드 | 규칙 | -|------|------| -| `form_id` | required, exists:approval_forms,id | -| `title` | required, string, max:200 | -| `body` | nullable, string | -| `is_urgent` | boolean | -| `steps` | nullable, array | -| `steps.*.user_id` | required_with:steps, exists:users,id | -| `steps.*.step_type` | required_with:steps, in:approval,agreement,reference | - -**응답 (201):** - -```json -{ - "success": true, - "message": "결재 문서가 저장되었습니다.", - "data": { ... } -} -``` - ---- - -### 3.3 수정 - -``` -PUT /api/admin/approvals/{id} -``` - -> `draft` 또는 `rejected` 상태에서만 수정 가능 - -**Request Body:** (생성과 동일, 모든 필드 선택) - -**Validation:** - -| 필드 | 규칙 | -|------|------| -| `title` | sometimes, string, max:200 | -| `body` | nullable, string | -| `is_urgent` | boolean | -| `steps` | nullable, array | - ---- - -### 3.4 삭제 - -``` -DELETE /api/admin/approvals/{id} -``` - -> `draft` 상태에서만 삭제 가능 - -**응답:** - -```json -{ - "success": true, - "message": "결재 문서가 삭제되었습니다." -} -``` - ---- - -## 4. 워크플로우 API - -### 4.1 상신 - -``` -POST /api/admin/approvals/{id}/submit -``` - -> 기안자가 `draft`/`rejected` 문서를 결재 요청한다. - -**Request Body:** 없음 - -**응답:** `{ "success": true, "message": "결재가 상신되었습니다.", "data": {...} }` - ---- - -### 4.2 승인 - -``` -POST /api/admin/approvals/{id}/approve -``` - -> 현재 결재자가 승인한다. - -**Request Body:** - -```json -{ - "comment": "승인합니다." // 선택 -} -``` - -**응답:** `{ "success": true, "message": "승인되었습니다.", "data": {...} }` - ---- - -### 4.3 반려 - -``` -POST /api/admin/approvals/{id}/reject -``` - -> 현재 결재자가 반려한다. 사유 필수. - -**Request Body:** - -```json -{ - "comment": "예산 초과로 반려합니다." // 필수 -} -``` - -**Validation:** `comment` — required, string, max:1000 - -**응답:** `{ "success": true, "message": "반려되었습니다.", "data": {...} }` - ---- - -### 4.4 회수 - -``` -POST /api/admin/approvals/{id}/cancel -``` - -> 기안자가 `pending`/`on_hold` 문서를 회수한다. 첫 결재자 미처리 시에만 가능. - -**Request Body:** - -```json -{ - "recall_reason": "내용 수정 필요" // 선택 -} -``` - -**응답:** `{ "success": true, "message": "결재가 회수되었습니다.", "data": {...} }` - ---- - -### 4.5 보류 - -``` -POST /api/admin/approvals/{id}/hold -``` - -> 현재 결재자가 결재를 보류한다. 사유 필수. - -**Request Body:** - -```json -{ - "comment": "추가 자료 검토 필요" // 필수 -} -``` - -**Validation:** `comment` — required, string, max:1000 - -**응답:** `{ "success": true, "message": "보류되었습니다.", "data": {...} }` - ---- - -### 4.6 보류 해제 - -``` -POST /api/admin/approvals/{id}/release-hold -``` - -> 보류한 결재자가 보류를 해제한다. - -**Request Body:** 없음 - -**응답:** `{ "success": true, "message": "보류가 해제되었습니다.", "data": {...} }` - ---- - -### 4.7 전결 - -``` -POST /api/admin/approvals/{id}/pre-decide -``` - -> 현재 결재자가 이후 모든 결재를 건너뛰고 최종 승인한다. - -**Request Body:** - -```json -{ - "comment": "전결 처리합니다." // 선택 -} -``` - -**응답:** `{ "success": true, "message": "전결 처리되었습니다.", "data": {...} }` - ---- - -### 4.8 복사 재기안 - -``` -POST /api/admin/approvals/{id}/copy -``` - -> 기안자가 `approved`/`rejected`/`cancelled` 문서를 복사하여 새 draft를 생성한다. - -**Request Body:** 없음 - -**응답:** - -```json -{ - "success": true, - "message": "문서가 복사되었습니다.", - "data": { - "id": 15, - "document_number": "APR-260228-003", - "parent_doc_id": 1, - "status": "draft", - ... - } -} -``` - -> 응답의 `data.id`를 사용하여 `/approval-mgmt/{id}/edit`로 이동한다. - ---- - -### 4.9 참조 열람 추적 - -``` -POST /api/admin/approvals/{id}/mark-read -``` - -> 참조자가 문서를 열람했음을 기록한다. - -**Request Body:** 없음 - -**응답:** `{ "success": true, "message": "열람 처리되었습니다." }` - ---- - -## 5. 유틸리티 API - -### 5.1 결재선 템플릿 목록 - -``` -GET /api/admin/approvals/lines -``` - -**응답:** - -```json -{ - "success": true, - "data": [ - { "id": 1, "name": "일반 결재선", "steps": [...] } - ] -} -``` - ---- - -### 5.2 양식 목록 - -``` -GET /api/admin/approvals/forms -``` - -**응답:** - -```json -{ - "success": true, - "data": [ - { "id": 1, "name": "휴가신청서", "is_active": true } - ] -} -``` - ---- - -### 5.3 미처리 건수 (뱃지) - -``` -GET /api/admin/approvals/badge-counts -``` - -**응답:** - -```json -{ - "success": true, - "data": { - "pending": 3, - "draft": 1, - "reference_unread": 5 - } -} -``` - -| 필드 | 설명 | -|------|------| -| `pending` | 내가 결재해야 할 문서 수 | -| `draft` | 내 임시저장 문서 수 | -| `reference_unread` | 미열람 참조 문서 수 | - ---- - -## 6. 라우트 전체 목록 - -| Method | Path | 컨트롤러 메서드 | 이름 | 설명 | -|--------|------|---------------|------|------| -| GET | `/drafts` | `drafts` | `drafts` | 기안함 | -| GET | `/pending` | `pending` | `pending` | 결재 대기함 | -| GET | `/completed` | `completed` | `completed` | 처리 완료함 | -| GET | `/references` | `references` | `references` | 참조함 | -| GET | `/lines` | `lines` | `lines` | 결재선 템플릿 | -| GET | `/forms` | `forms` | `forms` | 양식 목록 | -| GET | `/badge-counts` | `badgeCounts` | `badge-counts` | 뱃지 건수 | -| POST | `/` | `store` | `store` | 생성 | -| GET | `/{id}` | `show` | `show` | 상세 | -| PUT | `/{id}` | `update` | `update` | 수정 | -| DELETE | `/{id}` | `destroy` | `destroy` | 삭제 | -| POST | `/{id}/submit` | `submit` | `submit` | 상신 | -| POST | `/{id}/approve` | `approve` | `approve` | 승인 | -| POST | `/{id}/reject` | `reject` | `reject` | 반려 | -| POST | `/{id}/cancel` | `cancel` | `cancel` | 회수 | -| POST | `/{id}/hold` | `hold` | `hold` | 보류 | -| POST | `/{id}/release-hold` | `releaseHold` | `release-hold` | 보류 해제 | -| POST | `/{id}/pre-decide` | `preDecide` | `pre-decide` | 전결 | -| POST | `/{id}/copy` | `copyForRedraft` | `copy` | 복사 재기안 | -| POST | `/{id}/mark-read` | `markAsRead` | `mark-read` | 열람 추적 | - ---- - -## 관련 문서 - -- [README.md](README.md) — 시스템 전체 개요 -- [워크플로우 상세](workflows.md) — 각 동작의 상세 흐름 -- [UI 화면 구성](ui-screens.md) — 화면별 동작 - ---- - -**최종 업데이트**: 2026-02-28 diff --git a/sam/docs/features/approvals/db-changes-and-model-sync.md b/sam/docs/features/approvals/db-changes-and-model-sync.md deleted file mode 100644 index e59cd2b..0000000 --- a/sam/docs/features/approvals/db-changes-and-model-sync.md +++ /dev/null @@ -1,286 +0,0 @@ -# 결재관리 DB 변경사항 및 API 모델 동기화 현황 - -> **작성일**: 2026-03-09 -> **상태**: 조사 완료 -> **관련**: [README.md](README.md) | [API 명세](api-reference.md) - ---- - -## 1. 개요 - -### 1.1 목적 - -2026-02-27 ~ 2026-03-05 기간에 결재관리 테이블에 대규모 컬럼 추가가 이루어졌다. 이 문서는 변경된 DB 스키마와 API/MNG 프로젝트 간 모델 동기화 상태를 기록한다. - -### 1.2 핵심 발견 - -- 마이그레이션 **15개** 실행 (API 프로젝트에서 관리) -- MNG 모델: ✅ 모든 신규 컬럼 반영 완료 -- API 모델: ❌ **`$fillable`/`$casts` 미반영** — 오류 원인 가능성 - ---- - -## 2. 마이그레이션 변경 타임라인 - -### 2.1 Phase 2 확장 (2026-02-27) - -| 마이그레이션 파일 | 대상 테이블 | 작업 | -|------------------|-----------|------| -| `add_columns_to_approvals_table` | `approvals` | `line_id`, `body`, `is_urgent`, `department_id` 추가 | -| `add_columns_to_approval_steps_table` | `approval_steps` | `approver_name`, `approver_department`, `approver_position` 추가 | -| `add_phase2_columns_to_approval_steps_table` | `approval_steps` | `parallel_group`, `acted_by`, `approval_type` 추가 | -| `add_phase2_columns_to_approvals_table` | `approvals` | `recall_reason`, `parent_doc_id` 추가 | -| `create_approval_delegations_table` | `approval_delegations` | 위임 테이블 신규 생성 | -| `add_linkable_to_approvals_table` | `approvals` | `linkable_type`, `linkable_id` 추가 (다형성) | - -### 2.2 도메인 연동 (2026-02-28) - -| 마이그레이션 파일 | 대상 테이블 | 작업 | -|------------------|-----------|------| -| `add_approval_id_to_leaves_table` | `leaves` | `approval_id` FK 추가 | -| `insert_leave_approval_form` | `approval_forms` | 휴가신청 양식 데이터 등록 | - -### 2.3 양식 확장 (2026-03-03 ~ 03-04) - -| 마이그레이션 파일 | 대상 테이블 | 작업 | -|------------------|-----------|------| -| `insert_attendance_approval_forms` | `approval_forms` | 근태신청, 사유서 양식 등록 | -| `add_body_template_to_approval_forms` | `approval_forms` | `body_template` 컬럼 추가 | -| `insert_expense_approval_form` | `approval_forms` | 지출결의서 양식 + body_template 등록 | -| `update_expense_approval_form_body_template` | `approval_forms` | 지출결의서 body_template 고도화 | - -### 2.4 추적 기능 (2026-03-05) - -| 마이그레이션 파일 | 대상 테이블 | 작업 | -|------------------|-----------|------| -| `add_drafter_read_at_to_approvals_table` | `approvals` | `drafter_read_at` 추가 | -| `add_resubmit_count_to_approvals_table` | `approvals` | `resubmit_count` 추가 | -| `add_rejection_history_to_approvals_table` | `approvals` | `rejection_history` 추가 | - ---- - -## 3. 추가된 컬럼 상세 - -### 3.1 `approvals` 테이블 (11개 컬럼 추가) - -| 컬럼 | 타입 | 기본값 | 추가일 | 용도 | -|------|------|--------|--------|------| -| `line_id` | BIGINT FK NULL | NULL | 02-27 | 결재선 템플릿 참조 | -| `body` | LONGTEXT NULL | NULL | 02-27 | 문서 본문 HTML | -| `is_urgent` | BOOLEAN | false | 02-27 | 긴급 여부 | -| `department_id` | BIGINT NULL | NULL | 02-27 | 기안 부서 | -| `recall_reason` | TEXT NULL | NULL | 02-27 | 회수 사유 | -| `parent_doc_id` | BIGINT FK NULL | NULL | 02-27 | 재기안 원본 문서 | -| `linkable_type` | VARCHAR NULL | NULL | 02-27 | 다형성 모델 타입 | -| `linkable_id` | BIGINT NULL | NULL | 02-27 | 다형성 모델 ID | -| `drafter_read_at` | TIMESTAMP NULL | NULL | 03-05 | 기안자 열람 시각 | -| `resubmit_count` | TINYINT UNSIGNED | 0 | 03-05 | 재상신 횟수 | -| `rejection_history` | JSON NULL | NULL | 03-05 | 반려 이력 배열 | - -### 3.2 `approval_steps` 테이블 (6개 컬럼 추가) - -| 컬럼 | 타입 | 기본값 | 추가일 | 용도 | -|------|------|--------|--------|------| -| `approver_name` | VARCHAR(50) NULL | NULL | 02-27 | 결재자명 스냅샷 | -| `approver_department` | VARCHAR(100) NULL | NULL | 02-27 | 결재자 부서 스냅샷 | -| `approver_position` | VARCHAR(50) NULL | NULL | 02-27 | 결재자 직급 스냅샷 | -| `parallel_group` | INT NULL | NULL | 02-27 | 병렬 결재 그룹 (Phase 3) | -| `acted_by` | BIGINT FK NULL | NULL | 02-27 | 실제 처리자 (대결) | -| `approval_type` | VARCHAR(20) | 'normal' | 02-27 | normal/pre_decided/delegated | - -### 3.3 `approval_forms` 테이블 (1개 컬럼 추가) - -| 컬럼 | 타입 | 기본값 | 추가일 | 용도 | -|------|------|--------|--------|------| -| `body_template` | TEXT NULL | NULL | 03-04 | HTML 양식 렌더링 템플릿 | - -### 3.4 `approval_delegations` 테이블 (신규 생성) - -| 컬럼 | 타입 | 설명 | -|------|------|------| -| `tenant_id` | BIGINT FK | 테넌트 격리 | -| `delegator_id` | BIGINT FK | 위임자 | -| `delegate_id` | BIGINT FK | 대리인 | -| `start_date` | DATE | 위임 시작일 | -| `end_date` | DATE | 위임 종료일 | -| `form_ids` | JSON NULL | 대상 양식 (NULL=전체) | -| `notify_delegator` | BOOLEAN | 대결 시 보고 여부 | -| `is_active` | BOOLEAN | 활성 여부 | -| `reason` | VARCHAR(200) | 위임 사유 | - ---- - -## 4. API/MNG 모델 동기화 현황 - -### 4.1 Approval 모델 비교 - -| 항목 | MNG (`mng/app/Models/Approvals/Approval.php`) | API (`api/app/Models/Tenants/Approval.php`) | -|------|:---:|:---:| -| `line_id` in $fillable | ✅ | ❌ | -| `body` in $fillable | ✅ | ❌ | -| `is_urgent` in $fillable/$casts | ✅ boolean | ❌ | -| `department_id` in $fillable | ✅ | ❌ | -| `recall_reason` in $fillable | ✅ | ❌ | -| `parent_doc_id` in $fillable | ✅ | ❌ | -| `linkable_type/id` in $fillable | ✅ | ✅ | -| `drafter_read_at` in $fillable/$casts | ✅ datetime | ❌ | -| `resubmit_count` in $fillable/$casts | ✅ integer | ❌ | -| `rejection_history` in $fillable/$casts | ✅ array | ❌ | - -### 4.2 ApprovalStep 모델 비교 - -| 항목 | MNG | API | -|------|:---:|:---:| -| `approver_name` in $fillable | ✅ | ❌ | -| `approver_department` in $fillable | ✅ | ❌ | -| `approver_position` in $fillable | ✅ | ❌ | -| `parallel_group` in $fillable | ✅ | ❌ | -| `acted_by` in $fillable | ✅ | ❌ | -| `approval_type` in $fillable | ✅ | ❌ | - -### 4.3 ApprovalForm 모델 비교 - -| 항목 | MNG | API | -|------|:---:|:---:| -| `body_template` in $fillable | ✅ | ❌ | - -### 4.4 ApprovalDelegation 모델 - -| 항목 | MNG | API | -|------|:---:|:---:| -| 모델 파일 존재 | ✅ | ❌ 미생성 | - ---- - -## 5. 오류 영향 분석 - -### 5.1 API 모델 미반영으로 인한 잠재적 오류 - -API 프로젝트의 모델 `$fillable`에 신규 컬럼이 누락되어, API 엔드포인트를 통한 결재 문서 처리 시 다음 오류가 발생할 수 있다: - -| 증상 | 원인 | 영향 범위 | -|------|------|----------| -| `create()`/`update()` 시 신규 필드 저장 안 됨 | `$fillable` 미포함 → mass assignment 차단 | API v1 결재 CRUD | -| JSON 필드(`rejection_history`) 문자열로 반환 | `$casts` 미정의 → 타입 변환 안 됨 | API 응답 파싱 오류 | -| `drafter_read_at` 날짜 비교 실패 | `$casts` datetime 미정의 → Carbon 미변환 | 열람 추적 기능 | -| `is_urgent` 비교 오류 | `$casts` boolean 미정의 → 문자열 비교 | 긴급 필터링 | -| 위임(delegation) 기능 완전 불가 | 모델 자체 미생성 | Phase 3 기능 전체 | - -### 5.2 MNG는 정상 - -MNG 프로젝트의 모델은 모든 신규 컬럼이 `$fillable`, `$casts`, `$attributes`에 반영되어 있으며, `ApprovalService`에서 정상 사용 중이다. - -``` -MNG 정상 동작 확인 기능: -✅ 반려 이력 저장 (rejection_history) -✅ 재상신 횟수 추적 (resubmit_count) -✅ 기안자 열람 추적 (drafter_read_at) -✅ 결재자 스냅샷 저장 (approver_name/department/position) -✅ 전결 처리 (approval_type = pre_decided) -✅ 회수 사유 기록 (recall_reason) -``` - ---- - -## 6. 수정 필요 파일 목록 - -### 6.1 API 모델 업데이트 필요 - -| 파일 | 수정 내용 | -|------|----------| -| `api/app/Models/Tenants/Approval.php` | `$fillable`에 9개 필드, `$casts`에 4개 필드 추가 | -| `api/app/Models/Tenants/ApprovalStep.php` | `$fillable`에 6개 필드 추가 | -| `api/app/Models/Tenants/ApprovalForm.php` | `$fillable`에 `body_template` 추가 | -| `api/app/Models/Tenants/ApprovalDelegation.php` | 모델 파일 신규 생성 | - -### 6.2 Approval.php 수정 상세 - -**`$fillable` 추가 필요:** - -```php -'line_id', -'body', -'is_urgent', -'department_id', -'recall_reason', -'parent_doc_id', -'drafter_read_at', -'resubmit_count', -'rejection_history', -``` - -**`$casts` 추가 필요:** - -```php -'drafter_read_at' => 'datetime', -'resubmit_count' => 'integer', -'rejection_history' => 'array', -'is_urgent' => 'boolean', -``` - -### 6.3 ApprovalStep.php 수정 상세 - -**`$fillable` 추가 필요:** - -```php -'approver_name', -'approver_department', -'approver_position', -'parallel_group', -'acted_by', -'approval_type', -``` - -### 6.4 ApprovalForm.php 수정 상세 - -**`$fillable` 추가 필요:** - -```php -'body_template', -``` - ---- - -## 7. 연관 테이블 참조 변경 - -결재 시스템과 연동된 다른 테이블의 변경사항: - -| 테이블 | 추가 컬럼 | 추가일 | 용도 | -|--------|----------|--------|------| -| `leaves` | `approval_id` (BIGINT FK) | 02-28 | 휴가 ↔ 결재 연동 | -| `purchases` | `approval_id` (BIGINT FK) | (기존) | 구매 ↔ 결재 연동 | - ---- - -## 8. 등록된 결재 양식 (13종) - -2026-02-28 ~ 03-07 기간에 마이그레이션으로 등록된 양식: - -| 코드 | 양식명 | 카테고리 | 등록일 | -|------|--------|---------|--------| -| `leave` | 휴가신청서 | request | 02-28 | -| `attendance_request` | 근태신청서 | request | 03-03 | -| `reason_report` | 사유서 | request | 03-03 | -| `expense` | 지출결의서 | expense | 03-04 | -| `employment_cert` | 재직증명서 | request | 03-05 | -| `career_cert` | 경력증명서 | request | 03-05 | -| `appointment_cert` | 위촉증명서 | request | 03-05 | -| `resignation` | 사직서 | request | 03-06 | -| `seal_usage` | 사용인감계 | request | 03-06 | -| `delegation` | 위임장 | request | 03-06 | -| `board_minutes` | 이사회의사록 | request | 03-06 | -| `quotation` | 견적서 | request | 03-06 | -| `official_letter` | 공문서 | request | 03-07 | - ---- - -## 관련 문서 - -- [결재관리 시스템 개요](README.md) — 아키텍처, 상태 관리, 권한 -- [API 명세](api-reference.md) — 20개 엔드포인트 상세 -- [워크플로우 상세](workflows.md) — 승인/반려/회수/보류/전결 흐름 -- [기획서 원본](../../plans/approval-management-system-plan.md) — Phase 1~4 전체 기획 - ---- - -**최종 업데이트**: 2026-03-09 diff --git a/sam/docs/features/approvals/form-types.md b/sam/docs/features/approvals/form-types.md deleted file mode 100644 index 3242b78..0000000 --- a/sam/docs/features/approvals/form-types.md +++ /dev/null @@ -1,999 +0,0 @@ -# 결재 양식 기술 명세 - -> **작성일**: 2026-03-06 -> **상태**: Phase 2 구현 완료 -> **관련**: [README.md](README.md) | [워크플로우](workflows.md) | [API 명세](api-reference.md) | [UI 화면](ui-screens.md) - ---- - -## 1. 개요 - -### 1.1 목적 - -SAM MNG 결재관리의 **기안함 양식** 기술 명세. 각 양식의 필드 구조, JSON Content 데이터 형식, UI 인터랙션, 특수 로직을 정의한다. - -### 1.2 양식 목록 - -| 코드 | 양식명 | 분류 | Blade 파일 | 설명 | -|------|--------|------|------------|------| -| `BUSINESS_DRAFT` | 업무기안서 | 일반 | (body 편집기) | 일반 업무 보고·요청 | -| `leave` | 휴가신청 | 인사/근태 | `_leave-form.blade.php` | 연차, 휴가, 근태 신청 | -| `attendance_request` | 근태신청 | 인사/근태 | `_leave-form.blade.php` | 외근, 출장, 조퇴 등 | -| `reason_report` | 사유서 | 인사/근태 | `_leave-form.blade.php` | 지각, 결근 등 사유 소명 | -| `resignation` | 사직서 | 인사/근태 | `_resignation-form.blade.php` | 퇴직 서류 | -| `employment_cert` | 재직증명서 | 증명서 | `_certificate-form.blade.php` | 재직 증명 발급 (PDF) | -| `career_cert` | 경력증명서 | 증명서 | `_career-cert-form.blade.php` | 경력 증명 발급 (PDF) | -| `appointment_cert` | 위촉증명서 | 증명서 | `_appointment-cert-form.blade.php` | 위촉/임명 증명 발급 (PDF) | -| `pr_expense` | 지출품의서 | 품의 | `_purchase-request-form.blade.php` | 지출 전 사전 승인 | -| `pr_contract` | 계약체결품의서 | 품의 | `_purchase-request-form.blade.php` | 계약 체결 전 승인 | -| `pr_purchase` | 구매품의서 | 품의 | `_purchase-request-form.blade.php` | 물품 구매 전 승인 | -| `pr_trip` | 출장품의서 | 품의 | `_purchase-request-form.blade.php` | 출장 계획 승인 | -| `pr_settlement` | 비용정산품의서 | 품의 | `_purchase-request-form.blade.php` | 비용 정산 승인 | -| `expense` | 지출결의서 | 재무 | `_expense-form.blade.php` | 법인카드/송금/자동이체 지출 | - -### 1.3 공통 구조 - -모든 양식은 동일한 패턴으로 동작한다: - -``` -양식 선택 (form_id) - ↓ -양식별 Blade 파셜 렌더링 (create.blade.php 내 조건부 display) - ↓ -사용자 입력 → Alpine.js / JavaScript 인터랙션 - ↓ -getFormData() → JSON content 생성 - ↓ -ApprovalService::createApproval() → Approval.content (JSON 컬럼) 저장 -``` - -### 1.4 양식 선택 UI (2단계 분류 + 설명 카드) - -양식 선택은 **2단계 드롭다운 + 설명 카드** 레이아웃으로 구성된다. - -``` -┌─────────────────────────────────────────────────────────────────────────┐ -│ 양식 * │ -│ ┌──── 30% ────────┐ ┌─────────────── 70% ───────────────────────────┐ │ -│ │ 📋 품의 ▼ │ │ ┌─────────────────────────────────────────┐ │ │ -│ │ │ │ │ 📋 지출품의서 │ │ │ -│ │ 지출품의서 ▼ │ │ │ 지출이 발생하기 전 사전 승인을 받는 │ │ │ -│ │ │ │ │ 문서입니다. 예산 범위 내에서 지출 항목과 │ │ │ -│ │ │ │ │ 금액을 기재하여 사전에 승락을 받습니다. │ │ │ -│ └──────────────────┘ │ └─────────────────────────────────────────┘ │ │ -│ └─────────────────────────────────────────────┘ │ -└─────────────────────────────────────────────────────────────────────────┘ -``` - -#### 1단계: 분류 선택 (`form_category`) - -| 분류 | 아이콘 | 포함 양식 | -|------|--------|----------| -| 일반 | 📄 | 업무기안서 | -| 인사/근태 | 👤 | 휴가신청, 근태신청, 사유서, 사직서 | -| 증명서 | 📜 | 재직증명서, 경력증명서, 위촉증명서 | -| 품의 | 📋 | 지출품의서, 계약체결품의서, 구매품의서, 출장품의서, 비용정산품의서 | -| 재무 | 💰 | 지출결의서 | - -#### 2단계: 양식 선택 (`form_id`) - -- 1단계 분류 선택 시 해당 분류에 속하지 않는 양식은 `display:none` + `disabled` -- 분류 내 첫 번째 양식 자동 선택 - -#### 설명 카드 (`formDescriptions`) - -- 양식 선택 시 우측에 해당 양식의 아이콘/제목/설명 텍스트 표시 -- 14종 전체 양식에 대한 설명 정의 (create/edit 공통) -- 색상: 양식별 Tailwind 테마 색상 (`border-*-200 bg-*-50`) - -#### 핵심 JavaScript 함수 - -| 함수 | 설명 | -|------|------| -| `buildCategoryOptions()` | 사용 가능한 카테고리만 `form_category` 옵션으로 생성 | -| `filterFormsByCategory(cat)` | 선택된 분류 외 양식 옵션 숨김/비활성화 | -| `selectCategoryByFormId(formId)` | formId로 카테고리 역산하여 자동 선택 | -| `updateFormDescription(formId)` | 설명 카드 DOM 업데이트 | - -### 1.5 파일 구조 - -``` -resources/views/approvals/ -├── create.blade.php ← 기안 작성 (2단계 양식 선택 + 설명 카드 + 동적 폼) -├── edit.blade.php ← 기안 수정 (create와 동일한 2단계 선택 구조) -├── show.blade.php ← 상세 조회 (양식별 조회 컴포넌트) -└── partials/ - ├── _leave-form.blade.php ← 휴가신청 폼 - ├── _expense-form.blade.php ← 지출결의서 폼 - ├── _expense-show.blade.php ← 지출결의서 조회 - ├── _purchase-request-form.blade.php ← 품의서 5종 통합 폼 (Alpine.js) - ├── _purchase-request-show.blade.php ← 품의서 5종 통합 조회 - ├── _certificate-form.blade.php ← 재직증명서 폼 - ├── _certificate-show.blade.php ← 재직증명서 조회 - ├── _career-cert-form.blade.php ← 경력증명서 폼 - ├── _career-cert-show.blade.php ← 경력증명서 조회 - ├── _appointment-cert-form.blade.php ← 위촉증명서 폼 - ├── _appointment-cert-show.blade.php ← 위촉증명서 조회 - ├── _resignation-form.blade.php ← 사직서 폼 - ├── _resignation-show.blade.php ← 사직서 조회 - ├── _approval-stamp-table.blade.php ← 결재 도장 테이블 - └── _approval-line-editor.blade.php ← 결재선 편집기 -``` - ---- - -## 2. 휴가신청 (leave) - -### 2.1 폼 필드 - -| 필드 ID | 라벨 | 타입 | 필수 | 기본값 | 설명 | -|---------|------|------|------|--------|------| -| `leave-user-id` | 신청자 | select | 필수 | `auth()->id()` | 활성 사원 목록 | -| `leave-type` | 유형 | select | 필수 | - | 휴가/근태신청/사유서 | -| `leave-start-date` | 시작일 | date | 필수 | - | `YYYY-MM-DD` | -| `leave-end-date` | 종료일 | date | 필수 | - | `YYYY-MM-DD` | -| `leave-reason` | 사유 | textarea | 선택 | - | 자유 텍스트 | - -### 2.2 Content JSON - -```json -{ - "user_id": "10", - "leave_type": "연차", - "start_date": "2026-03-06", - "end_date": "2026-03-07", - "reason": "개인 사유" -} -``` - -### 2.3 특수 로직 - -- **자동 선택**: 로그인 사용자가 기본 선택 (`auth()->id()`) -- **직원 목록**: `$employees` Props로 전달 (활성 사원만) -- **단순 구조**: Alpine.js 없이 Blade 폼으로 구현 - ---- - -## 3. 지출결의서 (expense) - -### 3.1 폼 구조 (Alpine.js 기반) - -```javascript -x-data="expenseForm(initialData, authUserName, initialFiles, cardsData, accountsData)" -``` - -### 3.2 기본 정보 필드 - -| 필드 | 라벨 | 타입 | 필수 | 기본값 | -|------|------|------|------|--------| -| `expense_type` | 지출형식 | radio | 필수 | `corporate_card` | -| `tax_invoice` | 세금계산서 | radio | 필수 | `normal` | -| `write_date` | 작성일자 | date | 선택 | 오늘 | -| `approval_date` | 결재일자 | date | 선택 | 오늘 | -| `department` | 부서 | text | 선택 | `경리부` | -| `writer_name` | 이름 | text | 선택 | 인증 사용자명 | - -### 3.3 지출형식별 선택 - -| 지출형식 | 코드 | 연결 데이터 | -|---------|------|------------| -| 법인카드 | `corporate_card` | `$cards` → `selected_card` | -| 송금 | `transfer` | `$accounts` → `selected_account` | -| 자동이체 출금 | `auto_transfer` | `$accounts` → `selected_account` | -| 현금/가지급정산 | `cash_advance` | 없음 | - -**법인카드 선택 시 저장 구조:** - -```json -{ - "selected_card": { - "id": 1, - "card_name": "삼성카드", - "card_company": "삼성", - "card_number_last4": "1234", - "card_holder_name": "홍길동" - } -} -``` - -**계좌 선택 시 저장 구조:** - -```json -{ - "selected_account": { - "id": 1, - "bank_name": "국민은행", - "account_number": "123-456-789012", - "account_holder": "주일기업" - } -} -``` - -### 3.4 세금계산서 옵션 - -| 옵션 | 코드 | -|------|------| -| 일반 | `normal` | -| 이월발행 | `deferred` | -| 없음 | `none` | - -### 3.5 내역 테이블 - -**동적 rows** (`.items` 배열): - -| 필드 | 라벨 | 타입 | 설명 | -|------|------|------|------| -| `date` | 일자 | date | `YYYY-MM-DD` | -| `description` | 적요 | text | 지출 설명 | -| `amount` | 금액 | number | 콤마 제거 정수 | -| `vendor` | 거래처 | text | Autocomplete 검색 | -| `vendor_id` | 거래처 ID | hidden | API 연결 ID | -| `vendor_biz_no` | 사업자번호 | hidden | 자동 채움 | -| `bank` | 은행명 | text | 수동 입력 | -| `account_no` | 계좌번호 | text | 수동 입력 | -| `depositor` | 예금주 | text | 수동 입력 | -| `remark` | 비고 | text | 메모 | - -### 3.6 Content JSON (전체) - -```json -{ - "expense_type": "corporate_card", - "tax_invoice": "normal", - "write_date": "2026-03-06", - "approval_date": "2026-03-06", - "department": "경리부", - "writer_name": "홍길동", - "items": [ - { - "date": "2026-03-05", - "description": "사무용품 구매", - "amount": 150000, - "vendor": "오피스디포", - "vendor_id": 123, - "vendor_biz_no": "123-45-67890", - "bank": "", - "account_no": "", - "depositor": "", - "remark": "" - } - ], - "total_amount": 150000, - "attachment_memo": "영수증 첨부", - "selected_card": { ... }, - "selected_account": null -} -``` - -### 3.7 특수 기능 - -#### 거래처 검색 (Autocomplete) - -``` -입력 → 250ms 디바운싱 → API 호출 → 드롭다운 렌더링 - -API: /barobill/tax-invoice/search-partners?keyword=... -키보드: ↑↓(네비게이션), Enter(선택), Esc(닫기) -마우스: 항목 클릭(선택) -``` - -#### 금액 입력 포맷팅 - -``` -입력 시: 콤마 제거 → 정수 저장 (parseMoney) -표시 시: 콤마 포맷 (formatMoney) -합계: totalAmount getter → footer 실시간 업데이트 -``` - -#### 파일 업로드 - -``` -드래그 앤 드롭 + 파일 입력 -최대: 20MB -형식: pdf, doc, docx, xls, xlsx, ppt, pptx, txt, jpg, jpeg, png, gif, zip, rar -API: POST /api/admin/approvals/upload-file -진행률: XHR 업로드 이벤트 -``` - -#### 카드/계좌 연동 - -``` -카드 선택 → 모든 내역 행에 "결제카드" 자동 표시 -계좌 선택 → 모든 내역 행에 "은행/계좌/예금주" 자동 채움 -``` - -### 3.8 조회 화면 (_expense-show.blade.php) - -| 섹션 | 내용 | -|------|------| -| 기본 정보 | 지출형식, 세금계산서, 작성일, 결재일, 부서, 이름 | -| 선택 카드/계좌 | 유색 박스로 표시 | -| 내역 테이블 | 읽기 전용, `number_format()` 금액 | -| 첨부서류 메모 | `whitespace-pre-wrap` | -| 첨부파일 목록 | 다운로드 링크 + 파일 크기 | - ---- - -## 4. 증명서 양식 공통 - -### 4.1 공통 패턴 - -모든 증명서 양식은 동일한 패턴을 따른다: - -``` -사원 선택 → loadXxxInfo(userId) → API 호출 → 읽기 전용 필드 자동 채움 - ↓ - 일부 필드만 수정 가능 - ↓ - 미리보기 모달 (인쇄 가능) -``` - -### 4.2 공통 함수 - -| 함수 | 설명 | -|------|------| -| `loadXxxInfo(userId)` | 사원 선택 시 인적/재직 정보 로드 | -| `openXxxPreview()` | 미리보기 모달 열기 | -| `printXxxPreview()` | 미리보기 인쇄 (`window.print()`) | -| `closeXxxPreview()` | 미리보기 닫기 | -| `onXxxPurposeChange()` | 용도 선택 시 직접입력 필드 표시 | - -### 4.3 조회 화면 공통 - -- 읽기 전용 필드 표시 -- PDF 다운로드: `route('api.admin.approvals.cert-pdf', $approval->id)` - ---- - -## 5. 재직증명서 (employment_cert) - -### 5.1 폼 필드 - -| 섹션 | 필드 ID | 라벨 | 타입 | 수정 | 설명 | -|------|---------|------|------|------|------| -| 인적사항 | `cert-name` | 성명 | text | readonly | DB 자동 채움 | -| | `cert-resident` | 주민등록번호 | text | readonly | DB 자동 채움 | -| | `cert-address` | 주소 | text | editable | 직접 입력 | -| 재직사항 | `cert-company` | 회사명 | text | readonly | DB 자동 채움 | -| | `cert-business-num` | 사업자번호 | text | readonly | DB 자동 채움 | -| | `cert-department` | 근무부서 | text | readonly | DB 자동 채움 | -| | `cert-position` | 직급 | text | readonly | DB 자동 채움 | -| | `cert-hire-date` | 재직기간 | text | readonly | DB 자동 채움 | -| 발급정보 | `cert-purpose-select` | 사용용도 | select | editable | 드롭다운 선택 | -| | (custom) | 기타 용도 | text | editable | "기타" 선택 시 표시 | -| | `cert-issue-date` | 발급일 | text | readonly | `now()->format('Y-m-d')` | - -### 5.2 Content JSON - -```json -{ - "name": "홍길동", - "resident_number": "900101-1XXXXXX", - "address": "서울특별시 강남구", - "company_name": "(주)코드브릿지엑스", - "business_num": "123-45-67890", - "department": "개발팀", - "position": "과장", - "hire_date": "2020-03-01", - "purpose": "은행 제출용", - "issue_date": "2026-03-06" -} -``` - ---- - -## 6. 경력증명서 (career_cert) - -### 6.1 폼 필드 (재직증명서 대비 추가/변경) - -| 섹션 | 필드 ID | 라벨 | 타입 | 수정 | 설명 | -|------|---------|------|------|------|------| -| 인적사항 | `cc-birth-date` | 생년월일 | text | readonly | DB 자동 채움 | -| 경력사항 | `cc-ceo-name` | 대표자 | text | readonly | DB 자동 채움 | -| | `cc-phone` | 대표전화 | text | readonly | DB 자동 채움 | -| | `cc-company-address` | 소재지 | text | readonly | DB 자동 채움 | -| | `cc-department` | 소속부서 | text | readonly | DB 자동 채움 | -| | `cc-position` | 직위/직급 | text | readonly | DB 자동 채움 | -| | `cc-hire-date` | 근무기간 시작 | text | readonly | DB 자동 채움 | -| | `cc-resign-date` | 근무기간 종료 | date | editable | 직접 입력 | -| | `cc-job-description` | 담당업무 | text | editable | 직접 입력 | -| 발급정보 | 용도 | select | editable | + "이직 제출용" 옵션 | - -### 6.2 Content JSON - -```json -{ - "name": "홍길동", - "birth_date": "1990-01-01", - "address": "서울특별시 강남구", - "company_name": "(주)코드브릿지엑스", - "business_num": "123-45-67890", - "ceo_name": "김대표", - "phone": "02-1234-5678", - "company_address": "서울특별시 강남구 테헤란로", - "department": "개발팀", - "position": "과장", - "hire_date": "2020-03-01", - "resign_date": "2026-02-28", - "job_description": "웹 애플리케이션 개발", - "purpose": "이직 제출용", - "issue_date": "2026-03-06" -} -``` - ---- - -## 7. 위촉증명서 (appointment_cert) - -### 7.1 폼 필드 - -| 섹션 | 필드 ID | 라벨 | 타입 | 수정 | 설명 | -|------|---------|------|------|------|------| -| 인적사항 | `ac-name` | 성명 | text | readonly | DB 자동 채움 | -| | `ac-resident` | 주민등록번호 | text | readonly | DB 자동 채움 | -| | `ac-department` | 소속 | text | readonly | DB 자동 채움 | -| | `ac-phone` | 연락처 | text | editable | 직접 입력 | -| 위촉정보 | `ac-hire-date` | 위촉기간 시작 | text | readonly | DB 자동 채움 | -| | `ac-resign-date` | 위촉기간 종료 | date | editable | 직접 입력 | -| | `ac-contract-type` | 계약자격 | text | editable | 직접 입력 | -| 발급정보 | `ac-purpose-select` | 용도 | select | editable | 드롭다운 선택 | -| | `ac-issue-date` | 발급일 | text | readonly | 자동 설정 | -| (숨김) | `ac-company-name` | 회사명 | hidden | - | 미리보기용 | -| | `ac-ceo-name` | 대표자명 | hidden | - | 미리보기용 | - -### 7.2 Content JSON - -```json -{ - "name": "홍길동", - "resident_number": "900101-1XXXXXX", - "department": "기술자문팀", - "phone": "010-1234-5678", - "hire_date": "2024-01-01", - "resign_date": "2026-12-31", - "contract_type": "기술자문위원", - "purpose": "관공서 제출용", - "issue_date": "2026-03-06" -} -``` - ---- - -## 8. 사직서 (resignation) - -### 8.1 폼 필드 - -| 섹션 | 필드 ID | 라벨 | 타입 | 수정 | 필수 | -|------|---------|------|------|------|------| -| 인적사항 | `rg-department` | 소속 | text | readonly | - | -| | `rg-position` | 직위 | text | readonly | - | -| | `rg-name` | 성명 | text | readonly | - | -| | `rg-resident` | 주민등록번호 | text | readonly | - | -| | `rg-hire-date` | 입사일 | text | readonly | - | -| | `rg-resign-date` | 퇴사(예정)일 | date | editable | 필수 | -| | `rg-address` | 주소 | text | editable | - | -| 사직사유 | `rg-reason-select` | 사유 | select | editable | 필수 | -| | (custom) | 기타 사유 | text | editable | - | -| 제출일 | `rg-issue-date` | 제출일 | text | readonly | - | - -### 8.2 사직사유 옵션 - -| 옵션 | -|------| -| 일신상의 사유 | -| 가사 사정 | -| 건강상의 이유 | -| 진학/학업 | -| 이직 | -| 기타 (직접입력) | - -### 8.3 Content JSON - -```json -{ - "department": "개발팀", - "position": "대리", - "name": "홍길동", - "resident_number": "900101-1XXXXXX", - "hire_date": "2020-03-01", - "resign_date": "2026-04-01", - "address": "서울특별시 강남구", - "reason": "이직", - "issue_date": "2026-03-06" -} -``` - ---- - -## 9. 품의서 5종 공통 (_purchase-request-form/show) - -### 9.1 통합 Alpine.js 컴포넌트 - -품의서 5종은 **단일 Blade 파일**(`_purchase-request-form.blade.php`)에서 `prType` 프로퍼티로 동적 전환된다. - -```javascript -x-data="purchaseRequestForm(initialData, authUserName, initialFiles)" -``` - -#### 타입 전환 메커니즘 - -``` -create.blade.php → switchFormMode() - ↓ -code.startsWith('pr_') 감지 - ↓ -#purchase-request-form-container display: block - ↓ -setTimeout(50ms) → _x_dataStack[0].setPrType(code) - ↓ -Alpine.js x-if 분기 → 해당 폼 렌더링 -``` - -#### prType 코드 및 라벨 - -| prType | 라벨 | 색상 | -|--------|------|------| -| `pr_expense` | 지출품의서 | `bg-orange-50 text-orange-700` | -| `pr_contract` | 계약체결품의서 | `bg-purple-50 text-purple-700` | -| `pr_purchase` | 구매품의서 | `bg-blue-50 text-blue-700` | -| `pr_trip` | 출장품의서 | `bg-green-50 text-green-700` | -| `pr_settlement` | 비용정산품의서 | `bg-teal-50 text-teal-700` | - -### 9.2 공통 필드 (모든 품의서) - -| 필드 | 라벨 | 타입 | 기본값 | -|------|------|------|--------| -| `write_date` | 작성일자 | date | 오늘 | -| `department` | 요청부서 | text | - | -| `writer_name` | 요청자 | text | 인증 사용자명 | -| `attachment_memo` | 첨부서류 메모 | textarea | - | -| `files` | 파일 업로드 | file[] | - | - -### 9.3 공통 함수 - -| 함수 | 설명 | -|------|------| -| `setPrType(type)` | 외부에서 prType 설정 (switchFormMode에서 호출) | -| `getFormData()` | prType별 다른 JSON 구조 반환 (base에 `pr_type` 포함) | -| `addItem()` | 내역 행 추가 | -| `removeItem(index)` | 내역 행 삭제 | -| `formatMoney(val)` | 숫자 → 콤마 포맷 | -| `parseMoney(str)` | 콤마 문자열 → 정수 | -| `prVendorSearch(target, fieldName)` | 범용 거래처 Autocomplete 검색 | - -### 9.4 조회 화면 분기 (show.blade.php) - -```php -// show.blade.php에서 pr_ prefix로 분기 -@if(str_starts_with($approval->form?->code ?? '', 'pr_')) - @include('approvals.partials._purchase-request-show', ['content' => $content]) -@endif -``` - -`_purchase-request-show.blade.php`에서 `$content['pr_type']`으로 5종 분기 렌더링. - ---- - -## 10. 지출품의서 (pr_expense) - -### 10.1 추가 필드 - -| 필드 | 라벨 | 타입 | 필수 | -|------|------|------|------| -| `expense_category` | 지출항목 | text | 선택 | -| `usage_date` | 사용일자 | date | 선택 | -| `purpose` | 사용목적 | textarea | 필수 | - -### 10.2 내역 테이블 - -| 컬럼 | 라벨 | 타입 | -|------|------|------| -| `description` | 항목 | text | -| `amount` | 금액 | number (콤마 포맷) | -| `remark` | 비고 | text | - -### 10.3 Content JSON - -```json -{ - "pr_type": "pr_expense", - "write_date": "2026-03-06", - "department": "개발팀", - "writer_name": "홍길동", - "expense_category": "사무용품", - "usage_date": "2026-03-05", - "purpose": "업무용 모니터 구매", - "items": [ - { "description": "27인치 모니터", "amount": 350000, "remark": "LG전자" } - ], - "total_amount": 350000, - "attachment_memo": "견적서 첨부" -} -``` - ---- - -## 11. 계약체결품의서 (pr_contract) - -### 11.1 추가 필드 - -| 필드 | 라벨 | 타입 | 필수 | -|------|------|------|------| -| `contract_party` | 계약상대방 | text + Autocomplete | 필수 | -| `contract_party_biz_no` | 사업자번호 | text (자동) | - | -| `contract_content` | 계약내용 | textarea | 필수 | -| `contract_period_start` | 계약기간 시작 | date | 선택 | -| `contract_period_end` | 계약기간 종료 | date | 선택 | -| `contract_amount` | 계약금액 | number (콤마) | 필수 | -| `contract_conditions` | 주요조건 | textarea | 선택 | - -### 11.2 Content JSON - -```json -{ - "pr_type": "pr_contract", - "write_date": "2026-03-06", - "department": "경영지원팀", - "writer_name": "홍길동", - "contract_party": "(주)에이비씨", - "contract_party_biz_no": "123-45-67890", - "contract_content": "연간 IT 유지보수 계약", - "contract_period_start": "2026-04-01", - "contract_period_end": "2027-03-31", - "contract_amount": 12000000, - "contract_conditions": "월 1회 정기점검, 장애 발생 시 4시간 내 대응", - "attachment_memo": "계약서 초안 첨부" -} -``` - -### 11.3 특수 로직 - -- **거래처 검색**: `prVendorSearch(formData, 'contract_party')` — 계약상대방 필드에 Autocomplete 적용 -- 선택 시 `contract_party_biz_no` 자동 채움 - ---- - -## 12. 구매품의서 (pr_purchase) - -### 12.1 추가 필드 - -| 필드 | 라벨 | 타입 | 필수 | -|------|------|------|------| -| `vendor` | 납품업체 | text + Autocomplete | 선택 | -| `vendor_biz_no` | 사업자번호 | text (자동) | - | -| `delivery_date` | 납품예정일 | date | 선택 | -| `delivery_location` | 납품장소 | text | 선택 | - -### 12.2 내역 테이블 - -| 컬럼 | 라벨 | 타입 | -|------|------|------| -| `name` | 품목 | text | -| `spec` | 규격 | text | -| `quantity` | 수량 | number | -| `unit_price` | 단가 | number (콤마) | -| `amount` | 금액 | number (자동: 수량×단가) | -| `remark` | 비고 | text | - -### 12.3 Content JSON - -```json -{ - "pr_type": "pr_purchase", - "write_date": "2026-03-06", - "department": "생산팀", - "writer_name": "홍길동", - "vendor": "(주)공급사", - "vendor_biz_no": "987-65-43210", - "delivery_date": "2026-03-20", - "delivery_location": "본사 1층 창고", - "items": [ - { "name": "A4용지", "spec": "80g 500매", "quantity": 10, "unit_price": 25000, "amount": 250000, "remark": "" } - ], - "total_amount": 250000, - "attachment_memo": "" -} -``` - -### 12.4 특수 로직 - -- **금액 자동 계산**: `quantity × unit_price → amount` (x-effect 반응) -- **거래처 검색**: `prVendorSearch(formData, 'vendor')` — 납품업체 필드에 Autocomplete 적용 - ---- - -## 13. 출장품의서 (pr_trip) - -### 13.1 추가 필드 - -| 필드 | 라벨 | 타입 | 필수 | -|------|------|------|------| -| `destination` | 출장지 | text | 필수 | -| `trip_period_start` | 출장기간 시작 | date | 필수 | -| `trip_period_end` | 출장기간 종료 | date | 필수 | -| `trip_purpose` | 출장목적 | textarea | 필수 | - -### 13.2 일정표 (items) - -| 컬럼 | 라벨 | 타입 | -|------|------|------| -| `date` | 일자 | date | -| `schedule` | 일정 | text | -| `remark` | 비고 | text | - -### 13.3 경비 내역 (expenses) - -| 필드 | 라벨 | 타입 | -|------|------|------| -| `transport` | 교통비 | number (콤마) | -| `accommodation` | 숙박비 | number (콤마) | -| `meals` | 식비 | number (콤마) | -| `others` | 기타 | number (콤마) | -| (자동) | 합계 | number (합산) | - -### 13.4 Content JSON - -```json -{ - "pr_type": "pr_trip", - "write_date": "2026-03-06", - "department": "영업팀", - "writer_name": "홍길동", - "destination": "부산 해운대", - "trip_period_start": "2026-03-10", - "trip_period_end": "2026-03-11", - "trip_purpose": "거래처 방문 및 현장 점검", - "items": [ - { "date": "2026-03-10", "schedule": "거래처 미팅", "remark": "오전 10시" }, - { "date": "2026-03-11", "schedule": "현장 점검 및 복귀", "remark": "" } - ], - "expenses": { - "transport": 120000, - "accommodation": 80000, - "meals": 40000, - "others": 0 - }, - "total_amount": 240000, - "attachment_memo": "" -} -``` - -### 13.5 조회 화면 특수 구조 - -- **일정표**: 테이블 형태로 일자/일정/비고 렌더링 -- **경비 카드**: 교통비/숙박비/식비/기타 4개 항목 + 합계를 카드 그리드로 표시 - ---- - -## 14. 비용정산품의서 (pr_settlement) - -### 14.1 추가 필드 - -| 필드 | 라벨 | 타입 | 필수 | -|------|------|------|------| -| `settlement_period_start` | 정산기간 시작 | date | 선택 | -| `settlement_period_end` | 정산기간 종료 | date | 선택 | -| `payment_method` | 지급방법 | radio | 필수 | - -### 14.2 지급방법 옵션 - -| 값 | 라벨 | -|----|------| -| `corporate_card` | 법인카드 사용 | -| `personal_advance` | 개인 선지출 (환급 요청) | - -### 14.3 내역 테이블 - -| 컬럼 | 라벨 | 타입 | -|------|------|------| -| `date` | 사용일자 | date | -| `description` | 항목 | text | -| `amount` | 금액 | number (콤마) | -| `remark` | 비고 | text | - -### 14.4 Content JSON - -```json -{ - "pr_type": "pr_settlement", - "write_date": "2026-03-06", - "department": "개발팀", - "writer_name": "홍길동", - "settlement_period_start": "2026-02-01", - "settlement_period_end": "2026-02-28", - "payment_method": "personal_advance", - "items": [ - { "date": "2026-02-15", "description": "택시비", "amount": 25000, "remark": "야근 귀가" }, - { "date": "2026-02-20", "description": "회의 다과", "amount": 15000, "remark": "팀 미팅" } - ], - "total_amount": 40000, - "attachment_memo": "영수증 첨부" -} -``` - -### 14.5 조회 화면 특수 구조 - -- **지급방법 표시**: `corporate_card` → "법인카드 사용", `personal_advance` → "개인 선지출 (환급 요청)" -- 해당 라벨을 뱃지 형태로 표시 - ---- - -## 15. 결재 도장 테이블 (_approval-stamp-table.blade.php) - -### 15.1 구조 - -전통 한글 결재 양식의 도장 테이블을 구현한다. - -``` -┌──────┬────────┬────────┬────────┐ -│ │ 과장 │ 부장 │ 이사 │ ← 1행: 직급 헤더 -│ 결재 ├────────┼────────┼────────┤ -│ │ [승인] │ [대기] │ [대기] │ ← 2행: 서명/도장 영역 -│ ├────────┼────────┼────────┤ -│ │ 김과장 │ 박부장 │ 이이사 │ ← 3행: 이름 + 처리일 -│ │ 03/06 │ │ │ -└──────┴────────┴────────┴────────┘ -``` - -### 15.2 상태별 표시 - -| 상태 | approval_type | 표시 | 색상 | -|------|---------------|------|------| -| 승인 | `normal` | 빨간 원형 "승인" | `bg-red-500` | -| 전결 | `pre_decided` | 파란 원형 "전결" | `bg-blue-500` | -| 반려 | - | 빨간 원형 "반려" | `bg-red-500` | -| 보류 | - | 주황 원형 "보류" | `bg-amber-500` | -| 건너뜀 | - | 회색 "-" | `bg-gray-300` | - ---- - -## 16. 결재선 편집기 (_approval-line-editor.blade.php) - -### 16.1 2패널 구조 - -``` -┌─────────────────────┬─────────────────────┐ -│ 인원 목록 │ 결재선 │ -│ │ │ -│ [검색 input] │ [템플릿 선택 ▼] │ -│ │ │ -│ ▼ 개발팀 │ ① 김과장 (결재) [✗] │ -│ 홍길동 과장 [+] │ ② 박부장 (합의) [✗] │ -│ 김영희 대리 [+] │ ③ 이대리 (참조) [✗] │ -│ │ │ -│ ▼ 경영지원팀 │ (드래그로 순서 변경) │ -│ 박부장 부장 [+] │ │ -│ │ │ -├─────────────────────┴─────────────────────┤ -│ 결재: 1명 합의: 1명 참조: 1명 합계: 3명 │ -└───────────────────────────────────────────┘ -``` - -### 16.2 기능 - -| 기능 | 설명 | -|------|------| -| **인원 검색** | 이름/부서 실시간 검색 | -| **부서별 접기** | 부서 헤더 클릭으로 인원 접기/펼치기 | -| **드래그 정렬** | SortableJS로 결재선 순서 변경 | -| **유형 선택** | 각 단계별 approval/agreement/reference 선택 | -| **템플릿 로드** | 저장된 결재선 템플릿 드롭다운 | - -### 16.3 데이터 소스 - -``` -API: /api/admin/tenant-users/list - -응답: -[ - { - "department_id": 1, - "department_name": "개발팀", - "users": [ - { "id": 10, "name": "홍길동", "position": "과장", "job_title": "팀장" } - ] - } -] -``` - -### 16.4 Hidden Inputs (form 전송) - -```html - - - - -``` - ---- - -## 17. ApprovalForm 모델 - -### 17.1 테이블 스키마 - -| 컬럼 | 타입 | 설명 | -|------|------|------| -| `id` | BIGINT PK | | -| `tenant_id` | BIGINT FK | 테넌트 격리 | -| `name` | VARCHAR | 양식명 (예: "휴가신청서") | -| `code` | VARCHAR UNIQUE | 양식 코드 (예: `leave`) | -| `category` | ENUM | `request`, `expense`, `certificate`, `expense_estimate` | -| `template` | JSON | 필드 정의 메타데이터 | -| `body_template` | LONGTEXT NULL | HTML 본문 템플릿 | -| `is_active` | BOOLEAN | 활성 여부 | - -### 17.2 카테고리 - -#### DB 카테고리 (ApprovalForm.category) - -| 카테고리 | 설명 | 양식 코드 | -|---------|------|----------| -| `request` | 신청서 | `leave`, `attendance_request`, `reason_report` | -| `expense` | 지출결의서 | `expense` | -| `certificate` | 증명서/서류 | `employment_cert`, `career_cert`, `appointment_cert`, `resignation` | -| `expense_estimate` | 품의서 | `pr_expense`, `pr_contract`, `pr_purchase`, `pr_trip`, `pr_settlement` | - -#### UI 분류 (formCategoryMap — 2단계 선택용) - -| UI 분류 | 양식 코드 | -|---------|----------| -| 일반 | `BUSINESS_DRAFT` | -| 인사/근태 | `leave`, `attendance_request`, `reason_report`, `resignation` | -| 증명서 | `employment_cert`, `career_cert`, `appointment_cert` | -| 품의 | `pr_expense`, `pr_contract`, `pr_purchase`, `pr_trip`, `pr_settlement` | -| 재무 | `expense` | - -> **참고**: DB 카테고리와 UI 분류는 별도 매핑이다. DB는 `approval_forms.category` ENUM이고, UI 분류는 JavaScript `formCategoryMap` 객체로 정의된다. - ---- - -## 18. 양식별 저장/조회 흐름 - -### 18.1 저장 (create/update) - -``` -사용자 입력 - ↓ -getFormData() (JavaScript) - ↓ -POST /api/admin/approvals - body: { form_id, title, content: {...}, body, steps: [...] } - ↓ -ApprovalService::createApproval() - ↓ -Approval.content = JSON encode → DB 저장 -``` - -### 18.2 조회 (show) - -``` -GET /approval-mgmt/{id} - ↓ -ApprovalController::show() - ↓ -Blade: show.blade.php - ↓ -양식 코드별 분기: - leave → (본문에 인라인 표시) - expense → @include('_expense-show') - pr_* → @include('_purchase-request-show') ← str_starts_with 매칭 - employment_cert → @include('_certificate-show') - career_cert → @include('_career-cert-show') - appointment_cert → @include('_appointment-cert-show') - resignation → @include('_resignation-show') -``` - -> **품의서 분기**: `str_starts_with($approval->form?->code ?? '', 'pr_')` 조건으로 5종 모두 단일 include로 처리. `_purchase-request-show.blade.php` 내부에서 `$content['pr_type']`으로 세부 분기. - ---- - -## 관련 문서 - -- [README.md](README.md) — 결재관리 시스템 전체 개요 -- [워크플로우 상세](workflows.md) — 승인/반려/회수/보류/전결 흐름 -- [API 명세](api-reference.md) — 엔드포인트별 요청/응답 -- [UI 화면 구성](ui-screens.md) — 화면별 UI 요소 및 동작 - ---- - -**최종 업데이트**: 2026-03-06 diff --git a/sam/docs/features/approvals/ui-screens.md b/sam/docs/features/approvals/ui-screens.md deleted file mode 100644 index f81b9ae..0000000 --- a/sam/docs/features/approvals/ui-screens.md +++ /dev/null @@ -1,381 +0,0 @@ -# 결재관리 UI 화면 구성 - -> **작성일**: 2026-02-28 -> **상태**: Phase 2 구현 완료 -> **기술**: Blade + HTMX + Alpine.js + Tailwind CSS -> **관련**: [README.md](README.md) | [워크플로우](workflows.md) | [API 명세](api-reference.md) - ---- - -## 1. 개요 - -결재관리 화면은 MNG(관리자 웹)에서 Blade 템플릿으로 구현되며, API 호출은 `fetch()`를 사용한다. - -### 1.1 파일 구조 - -``` -resources/views/approvals/ -├── drafts.blade.php ← 기안함 (목록) -├── pending.blade.php ← 결재 대기함 (목록) -├── completed.blade.php ← 처리 완료함 (목록) -├── references.blade.php ← 참조함 (목록) -├── create.blade.php ← 기안 작성 -├── edit.blade.php ← 기안 수정 -├── show.blade.php ← 상세 조회 + 결재 처리 -└── partials/ - ├── _status-badge.blade.php ← 상태 뱃지 컴포넌트 - └── _step-progress.blade.php ← 결재 단계 진행 표시 -``` - ---- - -## 2. 목록 화면 - -### 2.1 기안함 (`/approval-mgmt/drafts`) - -내가 기안한 모든 문서를 표시한다. - -**UI 구성:** - -``` -┌──────────────────────────────────────────────────────────┐ -│ 기안함 [+ 새 기안] │ -├──────────────────────────────────────────────────────────┤ -│ [검색] [상태 필터 ▼] [긴급만 □] [날짜 범위] │ -├──────────────────────────────────────────────────────────┤ -│ 문서번호 │ 제목 │ 양식 │ 상태 │ 기안일 │ -│ APR-260228-001│ 휴가 신청 │ 휴가서 │ 🟢완료 │ 02-28 │ -│ APR-260228-002│ 출장 보고 │ 출장서 │ 🔵진행 │ 02-28 │ -│ APR-260227-001│ 경비 청구 │ 경비서 │ ⬜임시 │ 02-27 │ -├──────────────────────────────────────────────────────────┤ -│ [◀ 이전] 1 / 3 [다음 ▶] │ -└──────────────────────────────────────────────────────────┘ -``` - -**상태 필터:** 전체, 임시저장, 진행, 완료, 반려, 회수, 보류 - ---- - -### 2.2 결재 대기함 (`/approval-mgmt/pending`) - -내가 현재 결재해야 할 문서를 표시한다. - -**UI 구성:** - -``` -┌──────────────────────────────────────────────────────────┐ -│ 결재 대기함 [뱃지: 3건] │ -├──────────────────────────────────────────────────────────┤ -│ 문서번호 │ 제목 │ 기안자 │ 양식 │ 상신일 │ -│ 🔴 APR-260..│ 긴급 승인 │ 홍길동 │ 구매서 │ 02-28 │ -│ APR-260..│ 휴가 신청 │ 김영희 │ 휴가서 │ 02-27 │ -└──────────────────────────────────────────────────────────┘ -``` - -> 긴급 문서는 🔴 아이콘과 함께 상단에 표시 - ---- - -### 2.3 참조함 (`/approval-mgmt/references`) - -내가 참조자로 지정된 문서를 표시한다. - -**UI 구성:** - -``` -┌──────────────────────────────────────────────────────────┐ -│ 참조함 │ -├──────────────────────────────────────────────────────────┤ -│ [전체] [미열람 (5)] [열람완료] │ -├──────────────────────────────────────────────────────────┤ -│ 문서번호 │ 제목 │ 기안자 │ 상태 │ 열람 │ -│ APR-260228-001│ 회의록 │ 박부장 │ 🟢완료 │ ❌미열람│ -│ APR-260227-003│ 인사발령 │ 이팀장 │ 🔵진행 │ ✅열람 │ -└──────────────────────────────────────────────────────────┘ -``` - -**열람 추적:** -- 문서 클릭 시 `mark-read` API가 자동 호출된다 -- 미열람/열람완료 탭으로 필터링 가능 -- 미열람 건수가 뱃지로 표시된다 - ---- - -## 3. 상세 화면 (`/approval-mgmt/{id}`) - -### 3.1 전체 레이아웃 - -``` -┌──────────────────────────────────────────────────────────┐ -│ 결재 상세 [수정] [목록으로] │ -│ APR-260228-001 │ -├──────────────────────────────────────────────────────────┤ -│ │ -│ 상태: [🔵 진행] [🔴 긴급] │ -│ 양식: 휴가신청서 기안자: 홍길동 │ -│ 기안일: 2026-02-28 10:05 완료일: - │ -│ 원본 문서: APR-260225-003 (재기안 시 표시) │ -│ │ -│ ┌──────────────────────────────────────────────────┐ │ -│ │ 회수 사유 (cancelled 상태에서만) │ │ -│ │ 내용 수정이 필요하여 회수합니다. │ │ -│ └──────────────────────────────────────────────────┘ │ -│ │ -│ 제목: 2월 연차 사용 신청 │ -│ 본문: 2월 27일~28일 연차 사용합니다... │ -│ │ -├──────────────────────────────────────────────────────────┤ -│ │ -│ 결재 진행 │ -│ ┌────────────────────────────────────────────────┐ │ -│ │ [결재 단계 프로그레스 바] │ │ -│ │ ✓김과장(승인) → ●박부장(대기) → ③이사(대기) │ │ -│ └────────────────────────────────────────────────┘ │ -│ │ -│ 결재 의견 │ -│ ┌────────────────────────────────────────────────┐ │ -│ │ ✓ 김과장 2026-02-28 11:00 │ │ -│ │ 승인합니다. │ │ -│ └────────────────────────────────────────────────┘ │ -│ │ -├──────────────────────────────────────────────────────────┤ -│ │ -│ 결재 처리 (현재 결재자에게만 표시) │ -│ [결재 의견 textarea] │ -│ [승인] [반려] [보류] [전결] │ -│ │ -├──────────────────────────────────────────────────────────┤ -│ 보류 해제 (on_hold + 보류한 본인에게만) │ -│ [보류 해제] │ -├──────────────────────────────────────────────────────────┤ -│ 회수 (기안자 + pending/on_hold) │ -│ [회수 사유 textarea] │ -│ [결재 회수] │ -├──────────────────────────────────────────────────────────┤ -│ 복사 재기안 (기안자 + approved/rejected/cancelled) │ -│ [복사하여 재기안] │ -└──────────────────────────────────────────────────────────┘ -``` - -### 3.2 조건부 섹션 표시 - -| 섹션 | 표시 조건 | -|------|----------| -| **수정 버튼** | 기안자 + `draft`/`rejected` | -| **회수 사유** | `cancelled` + `recall_reason` 존재 | -| **원본 문서 링크** | `parent_doc_id` 존재 (재기안 문서) | -| **결재 처리** | `pending` + 현재 결재자 | -| **보류 해제** | `on_hold` + 보류한 본인 | -| **회수** | 기안자 + `pending`/`on_hold` | -| **복사 재기안** | 기안자 + `approved`/`rejected`/`cancelled` | - ---- - -## 4. 파셜 컴포넌트 - -### 4.1 상태 뱃지 (`_status-badge.blade.php`) - -문서 상태를 색상 뱃지로 표시한다. - -| 상태 | 라벨 | 스타일 | -|------|------|--------| -| `draft` | 임시저장 | `bg-gray-100 text-gray-700` | -| `pending` | 진행 | `bg-blue-100 text-blue-700` | -| `approved` | 완료 | `bg-green-100 text-green-700` | -| `rejected` | 반려 | `bg-red-100 text-red-700` | -| `cancelled` | 회수 | `bg-yellow-100 text-yellow-700` | -| `on_hold` | 보류 | `bg-amber-100 text-amber-700` | - ---- - -### 4.2 결재 단계 프로그레스 (`_step-progress.blade.php`) - -결재선의 각 단계를 가로 프로그레스 바로 표시한다. - -**단계 아이콘:** - -| 상태 | 아이콘 | 배경색 | 텍스트색 | -|------|--------|--------|---------| -| `approved` (normal) | ✓ | `bg-green-500` | white | -| `approved` (pre_decided) | ⚡ | `bg-indigo-500` | white | -| `rejected` | ✗ | `bg-red-500` | white | -| `on_hold` | ⏸ | `bg-amber-400` | white | -| `skipped` | — | `bg-gray-300` | gray | -| `pending` (현재 차례) | 번호 | `bg-blue-500` | white | -| `pending` (대기) | 번호 | `bg-gray-200` | gray | - -**레이아웃:** - -``` -┌──────────────────────────────────────────────────────┐ -│ │ -│ ✓ ──── ⚡ ──── — ──── — ──── ● ──── 3 │ -│ 김과장 박부장 이사장 팀장 최대리 참조자 │ -│ 경영팀 경영팀 대표실 개발팀 개발팀 인사팀 │ -│ (승인) (전결) (건너뜀)(건너뜀)(대기) (참조) │ -│ │ -└──────────────────────────────────────────────────────┘ -``` - -**특수 표시:** -- **전결** step: ⚡ 아이콘 + "전결" 라벨 (남색) -- **보류** step: ⏸ 아이콘 + "보류" 라벨 (노란색) -- **건너뜀** step: 이름에 취소선 (line-through) -- **참조** step: 별도 구분 없이 동일 프로그레스 바에 표시 -- **연결선**: 단계 사이 가로선 (`border-t-2`) - ---- - -## 5. 결재 처리 인터랙션 - -### 5.1 승인 - -``` -[승인 버튼 클릭] - → confirm("승인하시겠습니까?") - → POST /api/admin/approvals/{id}/approve - body: { comment: "의견 텍스트" } - → 성공 시: 토스트("승인되었습니다") + 페이지 리로드 -``` - -### 5.2 반려 - -``` -[반려 버튼 클릭] - → comment 빈 값 체크 → 경고 토스트("반려 시 사유를 입력해주세요") - → confirm("반려하시겠습니까?") - → POST /api/admin/approvals/{id}/reject - body: { comment: "사유" } - → 성공 시: 토스트("반려되었습니다") + 페이지 리로드 -``` - -### 5.3 보류 - -``` -[보류 버튼 클릭] - → comment 빈 값 체크 → 경고 토스트("보류 사유를 입력해주세요") - → confirm("이 결재를 보류하시겠습니까?") - → POST /api/admin/approvals/{id}/hold - body: { comment: "사유" } - → 성공 시: 토스트("보류되었습니다") + 페이지 리로드 -``` - -### 5.4 전결 - -``` -[전결 버튼 클릭] - → confirm("전결 처리하시겠습니까?\n이후 모든 결재를 건너뛰고 문서를 최종 승인합니다.") - → POST /api/admin/approvals/{id}/pre-decide - body: { comment: "의견(선택)" } - → 성공 시: 토스트("전결 처리되었습니다") + 페이지 리로드 -``` - -### 5.5 보류 해제 - -``` -[보류 해제 버튼 클릭] - → confirm("보류를 해제하시겠습니까?") - → POST /api/admin/approvals/{id}/release-hold - → 성공 시: 토스트("보류가 해제되었습니다") + 페이지 리로드 -``` - -### 5.6 회수 - -``` -[결재 회수 버튼 클릭] - → confirm("결재를 회수하시겠습니까? 이 작업은 되돌릴 수 없습니다.") - → POST /api/admin/approvals/{id}/cancel - body: { recall_reason: "사유(선택)" } - → 성공 시: 토스트("결재가 회수되었습니다") + 페이지 리로드 -``` - -### 5.7 복사 재기안 - -``` -[복사하여 재기안 버튼 클릭] - → confirm("이 문서를 복사하여 새 결재를 작성하시겠습니까?") - → POST /api/admin/approvals/{id}/copy - → 성공 시: 토스트("문서가 복사되었습니다") - → /approval-mgmt/{newId}/edit로 이동 -``` - ---- - -## 6. 결재 의견 표시 - -상세 페이지에서 결재 의견이 있는 step을 카드 형태로 표시한다. - -``` -┌──────────────────────────────────────┐ -│ ✓ 김과장 2026-02-28 11:00 │ -│ 승인합니다. │ -├──────────────────────────────────────┤ -│ ⚡ 박부장 (전결) 2026-02-28 14:00 │ -│ 전결 처리합니다. │ -├──────────────────────────────────────┤ -│ ⏸ 이사장 (보류) 2026-02-28 15:00 │ -│ 추가 자료 검토 필요 │ -├──────────────────────────────────────┤ -│ ✗ 팀장 2026-02-28 16:00 │ -│ 예산 초과로 반려합니다. │ -└──────────────────────────────────────┘ -``` - -**아이콘 색상:** -- ✓ 승인: 녹색 (`bg-green-100 text-green-600`) -- ⚡ 전결: 남색 (`bg-indigo-100 text-indigo-600`) -- ⏸ 보류: 노란색 (`bg-amber-100 text-amber-600`) -- ✗ 반려: 적색 (`bg-red-100 text-red-600`) - ---- - -## 7. 참조함 열람 추적 UI - -### 7.1 탭 필터 - -``` -[전체] [미열람 (5)] [열람완료] -``` - -- 탭 클릭 시 `is_read` 파라미터로 API 재호출 -- 미열람 탭에 건수 뱃지 표시 - -### 7.2 열람 상태 표시 - -| 상태 | 표시 | -|------|------| -| 미열람 | `bg-red-100 text-red-700` "미열람" | -| 열람완료 | `bg-green-100 text-green-700` "열람완료" | - -### 7.3 자동 열람 처리 - -문서 행 클릭 시: -1. `mark-read` API 호출 (비동기) -2. 상세 페이지로 이동 - ---- - -## 8. 버튼 스타일 가이드 - -| 버튼 | 색상 | Tailwind 클래스 | -|------|------|----------------| -| 승인 | 녹색 | `bg-green-600 hover:bg-green-700` | -| 반려 | 적색 | `bg-red-600 hover:bg-red-700` | -| 보류 | 노란색 | `bg-amber-500 hover:bg-amber-600` | -| 전결 | 남색 | `bg-indigo-600 hover:bg-indigo-700` | -| 보류 해제 | 노란색 | `bg-amber-500 hover:bg-amber-600` | -| 회수 | 노란색 | `bg-yellow-500 hover:bg-yellow-600` | -| 복사 재기안 | 회색 | `bg-gray-600 hover:bg-gray-700` | -| 수정 | 회색 | `bg-gray-600 hover:bg-gray-700` | - ---- - -## 관련 문서 - -- [README.md](README.md) — 시스템 전체 개요 -- [워크플로우 상세](workflows.md) — 각 동작의 상세 흐름 -- [API 명세](api-reference.md) — 엔드포인트별 요청/응답 - ---- - -**최종 업데이트**: 2026-02-28 diff --git a/sam/docs/features/approvals/workflows.md b/sam/docs/features/approvals/workflows.md deleted file mode 100644 index 202d525..0000000 --- a/sam/docs/features/approvals/workflows.md +++ /dev/null @@ -1,565 +0,0 @@ -# 결재관리 워크플로우 상세 - -> **작성일**: 2026-02-28 -> **상태**: Phase 2 구현 완료 -> **관련**: [README.md](README.md) | [API 명세](api-reference.md) | [UI 화면](ui-screens.md) - ---- - -## 1. 개요 - -이 문서는 결재관리 시스템의 각 동작(Action)에 대한 상세 워크플로우를 정의한다. -모든 워크플로우는 `ApprovalService`에서 트랜잭션으로 처리된다. - -### 1.1 용어 정의 - -| 용어 | 설명 | -|------|------| -| **기안자** | 결재 문서를 작성한 사람 (`drafter_id`) | -| **현재 결재자** | 결재선에서 현재 차례인 사람 (가장 작은 `step_order`의 `pending` step) | -| **결재자** | `step_type`이 `approval` 또는 `agreement`인 참여자 | -| **참조자** | `step_type`이 `reference`인 참여자 (의사결정 권한 없음) | -| **전결** | 현재 결재자가 이후 모든 결재를 건너뛰고 즉시 최종 승인 | - ---- - -## 2. 기안 작성 (createApproval) - -### 2.1 흐름 - -``` -사용자 → [양식 선택] → [제목/본문 입력] → [결재선 설정] → [임시저장] - │ - ▼ - 새 Approval 생성 - status = 'draft' - current_step = 0 -``` - -### 2.2 조건 - -- 모든 로그인 사용자가 작성 가능 -- `form_id` 필수 (양식 선택) -- 결재선(steps)은 저장 시 선택사항 (상신 시 필수) - -### 2.3 처리 로직 - -1. 문서번호 자동 채번 (`APR-YYMMDD-001` 형식) -2. `numbering_sequences` 테이블로 일일 순번 관리 -3. 결재선 설정 시 `approval_steps` 저장 + 사용자 정보 스냅샷 (이름, 부서, 직급) -4. `status = 'draft'`, `current_step = 0` - ---- - -## 3. 상신 (submit) - -### 3.1 흐름 - -``` -기안자 → [상신 버튼] → 유효성 검사 → 결재선 검사 → 상신 완료 - │ - ▼ - status = 'pending' - current_step = 1 - drafted_at = now() -``` - -### 3.2 조건 - -| 조건 | 설명 | -|------|------| -| 문서 상태 | `draft` 또는 `rejected` | -| 결재선 | 결재/합의 step 1명 이상 필수 | -| 요청자 | 기안자만 | - -### 3.3 처리 로직 - -1. `isSubmittable()` 검증 → `draft` 또는 `rejected`인지 확인 -2. 결재/합의 step 존재 확인 -3. **반려 후 재상신인 경우**: 모든 step을 `pending`으로 초기화 (comment, acted_at도 초기화) -4. `status → pending`, `drafted_at → now()`, `current_step → 1` - -### 3.4 반려 후 재상신 - -``` -rejected 문서 - │ - ├── 기안자가 내용 수정 (updateApproval) - │ - └── 상신 (submit) - ├── 모든 steps → pending (초기화) - ├── status → pending - └── current_step → 1 (처음부터 다시) -``` - -> 반려 후 재상신 시 결재선이 초기화되므로, 이전 결재 의견(comment)은 사라진다. - ---- - -## 4. 승인 (approve) - -### 4.1 흐름 - -``` -현재 결재자 → [의견 입력(선택)] → [승인 버튼] - │ - ┌──────────┴──────────┐ - │ 현재 step │ - │ status → 'approved' │ - │ comment → (입력값) │ - │ acted_at → now() │ - └──────────┬──────────┘ - │ - ┌─────────────────┴─────────────────┐ - │ │ - 다음 pending step 있음 마지막 결재자 - │ │ - current_step 갱신 status → 'approved' - (다음 순서 결재자 대기) completed_at → now() -``` - -### 4.2 조건 - -| 조건 | 설명 | -|------|------| -| 문서 상태 | `pending` | -| 요청자 | 현재 차례 결재자 (`approver_id === auth()->id()`) | - -### 4.3 처리 로직 - -1. `isActionable()` 검증 → `pending` 상태인지 확인 -2. `getCurrentApproverStep()` → 현재 차례 step 조회 -3. 현재 step → `approved` + comment + acted_at -4. 다음 pending 결재/합의 step 조회 - - **있으면**: `current_step` 갱신 - - **없으면**: 문서 `approved` + `completed_at` - -### 4.4 순차결재 순서 결정 - -``` -step_order = 1 (결재) → step_order = 2 (합의) → step_order = 3 (결재) - │ │ │ - 1번째 승인 → 2번째 승인 → 3번째 승인 → 문서 완료 -``` - -> 결재와 합의는 동일한 순차 흐름을 따른다. `step_order` 순서대로 처리된다. - ---- - -## 5. 반려 (reject) - -### 5.1 흐름 - -``` -현재 결재자 → [반려 사유 입력(필수)] → [반려 버튼] - │ - ┌──────────┴──────────┐ - │ 현재 step │ - │ status → 'rejected' │ - │ comment → (사유) │ - │ acted_at → now() │ - └──────────┬──────────┘ - │ - ▼ - 문서 status → 'rejected' - completed_at → now() -``` - -### 5.2 조건 - -| 조건 | 설명 | -|------|------| -| 문서 상태 | `pending` | -| 요청자 | 현재 차례 결재자 | -| 반려 사유 | **필수** (빈 값 불가) | - -### 5.3 처리 로직 - -1. `isActionable()` 검증 -2. 현재 결재자 확인 -3. 반려 사유 빈 값 체크 -4. 현재 step → `rejected` + comment + acted_at -5. 문서 → `rejected` + completed_at - -### 5.4 반려 후 가능한 동작 - -``` -rejected 문서 - │ - ├── 기안자가 수정 → 재상신 (submit) - │ └── 결재선 초기화, 처음부터 다시 진행 - │ - └── 기안자가 복사 재기안 (copyForRedraft) - └── 새 문서 생성 (draft), 원본은 그대로 유지 -``` - ---- - -## 6. 회수 (cancel) - -### 6.1 흐름 - -``` -기안자 → [회수 사유 입력(선택)] → [회수 버튼] - │ - ┌──────────┴──────────┐ - │ 회수 가능 여부 판단 │ - │ (첫 결재자 미처리?) │ - └──────────┬──────────┘ - │ - ┌───────────┴───────────┐ - │ │ - 첫 결재자 첫 결재자 이미 - pending/on_hold 승인/반려 - │ │ - 회수 진행 회수 불가 - │ (에러 반환) - ▼ - 모든 pending/on_hold steps → 'skipped' - 문서 status → 'cancelled' - recall_reason → (입력값) - completed_at → now() -``` - -### 6.2 조건 - -| 조건 | 설명 | -|------|------| -| 문서 상태 | `pending` 또는 `on_hold` | -| 요청자 | 기안자만 (`drafter_id === auth()->id()`) | -| 첫 결재자 상태 | `pending` 또는 `on_hold` (이미 처리했으면 불가) | - -### 6.3 회수 가능 판단 로직 - -```php -// 1단계: 문서 상태 확인 -$approval->isCancellable() // pending 또는 on_hold - -// 2단계: 기안자 확인 -$approval->drafter_id === auth()->id() - -// 3단계: 첫 결재자 상태 확인 -$firstStep = steps.approvalOnly().orderBy('step_order').first() -$firstStep->status === 'pending' || 'on_hold' // 미처리 상태여야 함 -``` - -### 6.4 처리 로직 - -1. `isCancellable()` 검증 → `pending` 또는 `on_hold` -2. 기안자 확인 -3. 첫 번째 결재/합의 step의 상태 확인 → `pending`/`on_hold`이 아니면 거부 -4. 모든 `pending`/`on_hold` steps → `skipped` -5. 문서 → `cancelled` + `recall_reason` + `completed_at` - ---- - -## 7. 보류 (hold) - -### 7.1 흐름 - -``` -현재 결재자 → [보류 사유 입력(필수)] → [보류 버튼] - │ - ┌──────────┴──────────┐ - │ 현재 step │ - │ status → 'on_hold' │ - │ comment → (사유) │ - │ acted_at → now() │ - └──────────┬──────────┘ - │ - ▼ - 문서 status → 'on_hold' -``` - -### 7.2 조건 - -| 조건 | 설명 | -|------|------| -| 문서 상태 | `pending` (`isHoldable()`) | -| 요청자 | 현재 차례 결재자 | -| 보류 사유 | **필수** (빈 값 불가) | - -### 7.3 처리 로직 - -1. `isHoldable()` 검증 → `pending` 상태인지 확인 -2. `getCurrentApproverStep()` → 현재 차례 step 조회 -3. 현재 결재자 확인 (`approver_id === auth()->id()`) -4. 보류 사유 빈 값 체크 -5. 현재 step → `on_hold` + comment + acted_at -6. 문서 → `on_hold` - -### 7.4 보류 상태의 영향 - -``` -on_hold 상태에서: -├── 다른 결재자는 아무 동작 불가 (결재 흐름 중단) -├── 기안자는 회수 가능 (첫 결재자가 미처리 상태이면) -└── 보류한 결재자만 보류 해제 가능 -``` - ---- - -## 8. 보류 해제 (releaseHold) - -### 8.1 흐름 - -``` -보류한 결재자 → [보류 해제 버튼] - │ - ┌──────────┴──────────┐ - │ on_hold step │ - │ status → 'pending' │ - │ comment → null │ - │ acted_at → null │ - └──────────┬──────────┘ - │ - ▼ - 문서 status → 'pending' - (결재 흐름 재개) -``` - -### 8.2 조건 - -| 조건 | 설명 | -|------|------| -| 문서 상태 | `on_hold` (`isHoldReleasable()`) | -| 요청자 | 보류한 본인만 (`on_hold` step의 `approver_id === auth()->id()`) | - -### 8.3 처리 로직 - -1. `isHoldReleasable()` 검증 → `on_hold` 상태인지 확인 -2. `on_hold` 상태인 step 조회 -3. 해당 step의 `approver_id`가 현재 사용자인지 확인 -4. step → `pending` + comment/acted_at 초기화 -5. 문서 → `pending` - ---- - -## 9. 전결 (preDecide) - -### 9.1 흐름 - -``` -현재 결재자 → [의견 입력(선택)] → [전결 버튼] → 확인 팝업 - │ - ┌──────────┴──────────┐ - │ 현재 step │ - │ status → 'approved' │ - │ approval_type → │ - │ 'pre_decided' │ - │ comment → (입력값) │ - │ acted_at → now() │ - └──────────┬──────────┘ - │ - ▼ - 이후 모든 pending - approval/agreement steps - → status = 'skipped' - │ - ▼ - 문서 status → 'approved' - completed_at → now() -``` - -### 9.2 조건 - -| 조건 | 설명 | -|------|------| -| 문서 상태 | `pending` (`isActionable()`) | -| 요청자 | 현재 차례 결재자 | - -### 9.3 처리 로직 - -1. `isActionable()` 검증 -2. `getCurrentApproverStep()` → 현재 차례 step 조회 -3. 현재 결재자 확인 -4. 현재 step → `approved` + `approval_type = 'pre_decided'` + comment + acted_at -5. 이후 모든 pending 결재/합의 steps → `skipped` -6. 문서 → `approved` + `completed_at` - -### 9.4 전결 예시 - -``` -step_order=1 (이사장, 결재) → approved (normal) -step_order=2 (부장, 결재) → approved (pre_decided) ← 여기서 전결 -step_order=3 (과장, 합의) → skipped (전결로 건너뜀) -step_order=4 (팀장, 결재) → skipped (전결로 건너뜀) -step_order=5 (참조자, 참조) → (참조는 영향 없음, 그대로 유지) - -문서 → approved, completed_at = now() -``` - -> 전결은 결재/합의 step만 건너뛴다. 참조 step은 영향받지 않는다. - ---- - -## 10. 복사 재기안 (copyForRedraft) - -### 10.1 흐름 - -``` -기안자 → [복사하여 재기안 버튼] - │ - ▼ - ┌─────────────────────────────┐ - │ 원본 문서에서 복사 │ - │ ├── form_id │ - │ ├── title │ - │ ├── content (양식 데이터) │ - │ ├── body │ - │ ├── is_urgent │ - │ ├── department_id │ - │ └── 결재선 (모두 pending) │ - └─────────────┬───────────────┘ - │ - ▼ - 새 문서 생성 (status = 'draft') - parent_doc_id = 원본.id - 새 문서번호 채번 - │ - ▼ - 수정 페이지로 이동 - (/approval-mgmt/{newId}/edit) -``` - -### 10.2 조건 - -| 조건 | 설명 | -|------|------| -| 원본 문서 상태 | `approved`, `rejected`, `cancelled` (`isCopyable()`) | -| 요청자 | 기안자만 (`drafter_id === auth()->id()`) | - -### 10.3 처리 로직 - -1. `isCopyable()` 검증 → `approved`/`rejected`/`cancelled` 중 하나 -2. 기안자 확인 -3. 새 문서 생성: - - 새 문서번호 채번 - - 원본의 양식, 제목, 내용, 본문, 긴급 여부, 부서 복사 - - `parent_doc_id = 원본.id` - - `status = 'draft'`, `current_step = 0` -4. 결재선 복사: 원본의 모든 steps를 새 문서에 복사 (모두 `pending` 상태) -5. 새 문서의 edit 페이지로 리다이렉트 - -### 10.4 원본과의 관계 - -``` -원본 문서 (approved/rejected/cancelled) - │ - └── parent_doc_id로 연결 - │ - ▼ - 새 문서 (draft) - ├── 상세 페이지에서 "원본 문서" 링크 표시 - └── 기안자가 내용 수정 후 상신 가능 -``` - ---- - -## 11. 참조 열람 추적 (markAsRead) - -### 11.1 흐름 - -``` -참조자 → [참조함 목록에서 문서 클릭] - │ - ├── markAsRead API 호출 - │ ├── is_read → true - │ └── read_at → now() - │ - └── 상세 페이지로 이동 -``` - -### 11.2 조건 - -| 조건 | 설명 | -|------|------| -| 요청자 | 해당 문서의 참조자 (`step_type = 'reference'`) | - -### 11.3 처리 로직 - -1. 현재 사용자의 참조 step 조회 -2. `is_read = false`인 step → `is_read = true`, `read_at = now()` -3. 이미 열람한 경우 중복 업데이트 없음 (`where('is_read', false)`) - ---- - -## 12. 전체 상태 전이 요약 - -``` -┌───────────────────────────────────────────────────────────────────┐ -│ │ -│ draft ──submit()──→ pending ──approve()──→ (다음 step 또는) │ -│ ▲ │ │ approved │ -│ │ │ │ │ -│ │ │ ├──reject()──→ rejected │ -│ │ │ │ │ │ -│ │ │ │ ├── 수정 → submit() │ -│ │ │ │ │ (재상신, draft X) │ -│ │ │ │ │ │ -│ │ │ │ └── copyForRedraft() │ -│ │ │ │ → 새 draft 생성 │ -│ │ │ │ │ -│ │ │ ├──hold()──→ on_hold │ -│ │ │ │ │ │ -│ │ │ │ ├── releaseHold() │ -│ │ │ │ │ → pending 복원 │ -│ │ │ │ │ │ -│ │ │ │ └── cancel() (기안자) │ -│ │ │ │ → cancelled │ -│ │ │ │ │ -│ │ │ ├──preDecide()──→ approved │ -│ │ │ │ (이후 steps → skipped) │ -│ │ │ │ │ -│ │ │ └──cancel()──→ cancelled │ -│ │ │ (기안자, 첫결재자 미처리 시) │ -│ │ │ │ │ -│ │ │ └── copyForRedraft() │ -│ │ │ → 새 draft 생성 │ -│ │ │ │ -│ │ └── approved ──copyForRedraft() │ -│ │ → 새 draft 생성 │ -│ │ │ -│ └── updateApproval() (draft/rejected 상태에서 수정) │ -│ │ -└───────────────────────────────────────────────────────────────────┘ -``` - ---- - -## 13. 에러 케이스 정리 - -| 동작 | 에러 조건 | 에러 메시지 | -|------|----------|------------| -| submit | 상태가 draft/rejected 아님 | "상신할 수 없는 상태입니다." | -| submit | 결재선 없음 | "결재선을 설정해주세요." | -| approve | 상태가 pending 아님 | "승인할 수 없는 상태입니다." | -| approve | 현재 결재자 아님 | "현재 결재자가 아닙니다." | -| reject | 상태가 pending 아님 | "반려할 수 없는 상태입니다." | -| reject | 사유 미입력 | "반려 사유를 입력해주세요." | -| cancel | 상태가 pending/on_hold 아님 | "회수할 수 없는 상태입니다." | -| cancel | 기안자 아님 | "기안자만 회수할 수 있습니다." | -| cancel | 첫 결재자 이미 처리 | "첫 번째 결재자가 이미 처리하여 회수할 수 없습니다." | -| hold | 상태가 pending 아님 | "보류할 수 없는 상태입니다." | -| hold | 현재 결재자 아님 | "현재 결재자가 아닙니다." | -| hold | 사유 미입력 | "보류 사유를 입력해주세요." | -| releaseHold | 상태가 on_hold 아님 | "보류 해제할 수 없는 상태입니다." | -| releaseHold | 보류한 본인 아님 | "보류한 결재자만 해제할 수 있습니다." | -| preDecide | 상태가 pending 아님 | "전결할 수 없는 상태입니다." | -| preDecide | 현재 결재자 아님 | "현재 결재자가 아닙니다." | -| copyForRedraft | 상태가 approved/rejected/cancelled 아님 | "복사할 수 없는 상태입니다." | -| copyForRedraft | 기안자 아님 | "기안자만 복사할 수 있습니다." | -| update | 상태가 draft/rejected 아님 | "수정할 수 없는 상태입니다." | -| delete | 상태가 draft 아님 | "삭제할 수 없는 상태입니다." | - ---- - -## 관련 문서 - -- [README.md](README.md) — 시스템 전체 개요 -- [API 명세](api-reference.md) — 엔드포인트별 요청/응답 -- [UI 화면 구성](ui-screens.md) — 화면별 동작 - ---- - -**최종 업데이트**: 2026-02-28 diff --git a/sam/docs/features/barobill-kakaotalk/README.md b/sam/docs/features/barobill-kakaotalk/README.md deleted file mode 100644 index 09f1909..0000000 --- a/sam/docs/features/barobill-kakaotalk/README.md +++ /dev/null @@ -1,410 +0,0 @@ -# 바로빌 카카오톡 (알림톡/친구톡) 연동 - -> **문서 버전**: 1.1 -> **작성일**: 2026-02-14 -> **최종 수정**: 2026-02-27 -> **상태**: 운영 중 (알림톡 + SMS + 환경별 분기 완료) -> **대상 프로젝트**: MNG - ---- - -## 1. 개요 - -### 1.1 목적 - -바로빌(Barobill) 플랫폼의 카카오톡 알림톡/친구톡 API를 SAM에 연동하여, -고객사에 카카오톡 메시지를 자동 또는 수동으로 발송하는 기능을 제공한다. - -### 1.2 사전 요구사항 - -| 항목 | 상태 | 설명 | -|------|------|------| -| 법인 명의 휴대폰 준비 | **완료** | 카카오톡 채널 가입에 법인 명의 번호 사용 | -| 카카오톡 채널 개설 | **완료** (2026-02-20) | 채널 ID: `@codebridge`, 채널명: (주)코드브릿지엑스 | -| 바로빌 카카오톡 서비스 신청 | **완료** (2026-02-20) | 바로빌 관리자 페이지에서 카카오톡 서비스 활성화 | -| 채널 연동 (바로빌↔카카오) | **완료** (2026-02-20) | 바로빌 관리 URL에서 채널 연동 처리 | -| 바로빌 파트너 과금 설정 | **완료** (2026-02-23) | 바로빌 측에서 파트너사 과금 설정 완료 | -| 알림톡 템플릿 v1 검수 | **완료** (2026-02-22) | `전자계약_서명요청`, `전자계약_리마인드` 2종 승인 | -| 알림톡 템플릿 v2 검수 | **완료** (2026-02-25) | 버튼 URL에 `#{토큰}` 변수 포함 3종 승인 | -| 알림톡 `전자계약_완료` | **완료** (2026-02-26) | 서명 완료 알림 발송용 템플릿 승인 | -| 역할 기반 알림 분기 | **완료** (2026-02-26) | 본사=이메일, 상대방=알림톡/SMS | -| 환경별 템플릿 분기 | **완료** (2026-02-27) | `_DEV` 접미사 개발 템플릿 등록 | -| DEV 템플릿 검수 | **심사 중** (2026-02-27 접수) | 개발서버용 3종 (`admin.codebridge-x.com`) | - -> 상세 등록 가이드: [카카오톡 알림톡 채널 및 템플릿 등록 가이드](../../guides/카카오톡-알림톡-채널-템플릿-등록.md) - -### 1.3 알림톡 vs 친구톡 - -| 구분 | 알림톡 | 친구톡 | -|------|--------|--------| -| **용도** | 정보성 메시지 (주문확인, 배송안내 등) | 광고성 메시지 (프로모션, 이벤트 등) | -| **수신 대상** | 모든 카카오톡 사용자 | 채널 친구 추가한 사용자만 | -| **템플릿** | 필수 (카카오 사전 검수) | 불필요 (자유 형식) | -| **광고 표시** | 불가 | 필수 (`(광고)` 표기) | -| **이미지 첨부** | 불가 | 가능 (이미지/와이드 이미지) | -| **비용** | 건당 약 8~9원 | 건당 약 15~20원 | -| **SMS 대체발송** | 설정 가능 | 설정 가능 | - ---- - -## 2. 아키텍처 - -### 2.1 시스템 구조 - -``` -SAM MNG (브라우저) - │ - ├─ [페이지] /barobill/kakaotalk/* ← Blade 뷰 - │ KakaotalkController (페이지 렌더링) - │ - ├─ [API] /api/admin/barobill/kakaotalk/* ← AJAX 호출 - │ BarobillKakaotalkController - │ - └─ [전자계약] /esign/* ← 자동 발송 - EsignApiController::sendAlimtalk() - │ - └─ BarobillService (SOAP 클라이언트) - │ - └─ 바로빌 KAKAOTALK.asmx (WSDL) - │ - └─ 카카오톡 서버 -``` - -### 2.2 바로빌 SOAP API 엔드포인트 - -| 환경 | WSDL URL | -|------|----------| -| **테스트** | `https://testws.baroservice.com/KAKAOTALK.asmx?WSDL` | -| **운영** | `https://ws.baroservice.com/KAKAOTALK.asmx?WSDL` | - ---- - -## 3. 전자계약 알림톡 연동 (핵심) - -### 3.1 발송 흐름 - -``` -전자계약 생성 (E-Sign) - │ - ├─ [1단계] EsignApiController::sendAlimtalk() - │ │ - │ ├─ 채널 ID 조회 (getKakaotalkChannelId) - │ ├─ 템플릿 본문 + 버튼 조회 (getTemplateData) - │ ├─ 변수 치환 (#{이름}, #{계약명}, #{기한}) - │ └─ SendATKakaotalkEx 호출 - │ - ├─ [2단계] 바로빌 접수 → SendKey 반환 - │ - ├─ [3단계] 3초 대기 후 GetSendKakaotalk으로 전달 결과 확인 - │ │ - │ ├─ ResultCode = 1 → 성공 - │ └─ ResultCode != 1 → 실패 (에러 반환) - │ - └─ [이메일 폴백] 알림톡 실패 시 이메일로 자동 전환 -``` - -### 3.2 등록된 템플릿 (v1 — 현재 운영) - -**`전자계약_서명요청`** - -``` - 안녕하세요, #{이름}님. - 전자계약 서명 요청이 도착했습니다. - - ■ 계약명: #{계약명} - ■ 서명 기한: #{기한} - - 아래 버튼을 눌러 계약서를 확인하고 서명해 주세요. -``` - -- 버튼: `계약서 확인하기` (WL) -- Url1/Url2: `https://mng.codebridge-x.com` - -**`전자계약_리마인드`** - -``` -안녕하세요, #{이름}님. -아직 서명이 완료되지 않은 전자계약이 있습니다. - - ■ 계약명: #{계약명} - ■ 서명 기한: #{기한} - - 기한 내에 서명을 완료해 주세요. -``` - -- 버튼: `계약서 확인하기` (WL) -- Url1/Url2: `https://mng.codebridge-x.com` - -### 3.3 등록 예정 템플릿 (v2 — 심사 중) - -> **2026-02-24 재등록**: 버튼 URL에 `#{토큰}` 변수를 포함하여 동적 서명 URL 지원 - -- Url1/Url2: `https://mng.codebridge-x.com/esign/sign/#{토큰}` - -v2 승인 후 코드 변경 필요: -- `EsignApiController::sendAlimtalk()`에서 동적 `$signUrl`을 버튼 URL로 전달 -- 현재 코드의 등록된 URL 그대로 사용 → 동적 URL 사용으로 전환 - -### 3.4 임시 우회: 로그인 페이지 서명 확인 - -v1 템플릿의 버튼 URL이 대시보드(`https://mng.codebridge-x.com`)로 고정되어 있어, -로그인 페이지에 전화번호 기반 서명 확인 기능을 추가하였다. - -``` -알림톡 버튼 클릭 → https://mng.codebridge-x.com → 로그인 페이지 - │ - └─ "전자계약 서명하기" 섹션 - │ - ├─ 전화번호 입력 - ├─ POST /esign/verify-phone - └─ 대기 중인 계약 조회 → /esign/sign/{token} 리다이렉트 -``` - -- 라우트: `POST /esign/verify-phone` -- 컨트롤러: `EsignPublicController::verifyPhone()` -- v2 템플릿 승인 후에도 유지 (비로그인 사용자 대응) - -### 3.5 관련 파일 - -| 파일 | 역할 | -|------|------| -| `app/Http/Controllers/ESign/EsignApiController.php` | `sendAlimtalk()`, `getTemplateData()` | -| `app/Http/Controllers/ESign/EsignPublicController.php` | `verifyPhone()` 전화번호 확인 | -| `app/Services/Barobill/BarobillService.php` | SOAP 클라이언트, `sendATKakaotalkEx()` | -| `resources/views/auth/login.blade.php` | 로그인 페이지 서명 확인 UI | -| `routes/web.php` | `/esign/verify-phone` 라우트 | - ---- - -## 4. 트러블슈팅 (실전 경험) - -> **경고: 아래 내용은 실제 연동 과정에서 발견한 핵심 이슈다. 반드시 숙지할 것.** - -### 4.1 바로빌 API 응답 구조 - -바로빌 SOAP 응답은 `stdClass` 객체로 반환된다. 배열이 아니므로 주의: - -```php -// ❌ 잘못된 접근 -$channels = $result['data']; // 배열이 아님 - -// ✅ 올바른 접근 -$data = $result['data']; // stdClass -$channels = is_array($data->KakaotalkChannel) - ? $data->KakaotalkChannel - : [$data->KakaotalkChannel]; // 1건이면 객체, N건이면 배열 -``` - -### 4.2 SendKey vs ResultCode (2단계 검증 필수) - -> **핵심**: 바로빌이 SendKey를 반환해도 **실제 카카오톡 전달이 실패할 수 있다.** - -``` -[1단계] SendATKakaotalkEx 호출 - → SendKey 반환 (예: BB_6648603713_AT_3044107_260224) - → 이것은 "접수 성공"이지 "전달 성공"이 아님! - -[2단계] 3초 후 GetSendKakaotalk(SendKey) 호출 - → ResultCode = 1: 전달 성공 ✅ - → ResultCode = 4: 템플릿 데이터 일치 오류 ❌ - → ResultCode != 1: 기타 실패 ❌ -``` - -```php -// 반드시 2단계 검증 필요 -if ($result['success'] && is_string($result['data'])) { - $sendKey = $result['data']; - sleep(3); // 카카오톡 전달 대기 - $sendResult = $barobill->getSendKakaotalk($member->biz_no, $sendKey); - $resultCode = $sendResult['data']->ResultCode ?? null; - if ($resultCode != 1) { - // 실패 처리! - } -} -``` - -### 4.3 템플릿 URL 정확 일치 규칙 - -> **핵심**: 버튼 URL은 등록된 템플릿의 URL과 **정확히 일치**해야 한다. 1글자라도 다르면 실패. - -| 등록된 URL | 전송 시 URL | 결과 | -|------------|------------|------| -| `https://mng.codebridge-x.com` | `https://mng.codebridge-x.com` | ResultCode=1 (성공) | -| `https://mng.codebridge-x.com` | `https://mng.codebridge-x.com/esign/sign/xxx` | ResultCode=4 (실패) | -| `https://mng.codebridge-x.com` | `https://mng.codebridge-x.com?sign=xxx` | ResultCode=4 (실패) | -| `https://mng.codebridge-x.com` | `https://mng.codebridge-x.com#sign=xxx` | ResultCode=4 (실패) | - -- 경로 추가: 실패 -- 쿼리 파라미터 추가: 실패 -- URL 프래그먼트(#) 추가: 실패 -- **동적 URL을 사용하려면 템플릿에 `#{변수}` 포함하여 재등록 필요** - -### 4.4 SmsReply 오류 (-31325) - -`SmsReply` 파라미터가 `'S'`(대체발송 사용)인데 `SmsSenderNum`이 비어있으면 `-31325` 오류 발생. - -```php -// ❌ 오류 발생 -'SmsReply' => empty($smsMessage) ? 'N' : 'S', // SmsSenderNum이 비어도 S로 설정 - -// ✅ 수정 -'SmsReply' => (empty($smsMessage) || empty($smsSenderNum)) ? 'N' : 'S', -``` - -### 4.5 SOAP 파라미터 구조 - -바로빌 SOAP API의 파라미터 구조에 주의: - -```php -// 올바른 구조 -$params = [ - 'CorpNum' => $bizNo, // 사업자번호 (하이픈 포함: 123-45-67890) - 'SenderID' => $barobillId, // 바로빌 계정 ID - 'YellowId' => $channelId, // 카카오 채널 ID (@codebridge) - 'TemplateName' => '전자계약_서명요청', - 'SendDT' => '', // 즉시발송: 빈 문자열 - 'SmsReply' => 'N', // SMS 발신번호 없으면 반드시 'N' - 'SmsSenderNum' => '', - 'KakaotalkMessage' => [ - 'ReceiverName' => $name, - 'ReceiverNum' => $phone, // 하이픈 없이: 01012345678 - 'Title' => '', - 'Message' => $message, // 템플릿 변수 치환 완료된 본문 - 'SmsMessage' => '', - 'SmsSubject' => '', - 'Buttons' => ['KakaotalkButton' => $buttons], // 버튼 배열 - ], -]; -``` - -### 4.6 에러 코드 정리 - -| 코드 | 메시지 | 원인 | 해결 | -|------|--------|------|------| -| 1 | 성공 | 정상 전달 | - | -| 4 | 템플릿 데이터 일치 오류 | 본문/버튼 URL이 등록 템플릿과 불일치 | 등록된 템플릿과 동일하게 전송 | -| -31325 | 대체문자 유형 오류 | SmsReply=S인데 SmsSenderNum 비어있음 | SmsReply를 N으로 설정 | -| 음수값 | 바로빌 API 오류 | 파라미터 오류 또는 서비스 미설정 | 바로빌 에러코드 문서 참조 | - ---- - -## 5. 구현 현황 - -### 5.1 완료된 항목 - -| 구분 | 파일 | 설명 | -|------|------|------| -| SOAP 서비스 | `app/Services/Barobill/BarobillService.php` | kakaotalk SOAP 클라이언트 + 15개 API 메서드 | -| 전자계약 알림톡 | `app/Http/Controllers/ESign/EsignApiController.php` | `sendAlimtalk()`, `getTemplateData()` | -| 서명 확인 | `app/Http/Controllers/ESign/EsignPublicController.php` | `verifyPhone()` 전화번호 기반 서명 확인 | -| API 컨트롤러 | `app/Http/Controllers/Api/Admin/Barobill/BarobillKakaotalkController.php` | 15개 API 엔드포인트 | -| 페이지 컨트롤러 | `app/Http/Controllers/Barobill/KakaotalkController.php` | 6개 관리 페이지 | -| 로그인 페이지 | `resources/views/auth/login.blade.php` | 전자계약 서명하기 섹션 | -| 라우트 | `routes/web.php` | `/esign/verify-phone`, `/barobill/kakaotalk/*` | -| 메뉴 등록 | DB (menus 테이블) | 로컬/서버 모두 등록 완료 | - -### 5.2 검증 완료 항목 - -| 항목 | 결과 | 날짜 | -|------|------|------| -| 채널 API 호출 | **성공** | 2026-02-22 | -| 템플릿 조회 | **성공** | 2026-02-22 | -| 알림톡 발송 (본문) | **성공** (ResultCode=1) | 2026-02-24 | -| 알림톡 버튼 URL | **성공** (등록된 URL 사용 시) | 2026-02-24 | -| 전달 결과 확인 (2단계) | **구현 완료** | 2026-02-24 | -| 로그인 페이지 서명 확인 | **성공** | 2026-02-24 | - -### 5.3 완료된 추가 항목 (2026-02-26~27) - -| 항목 | 상태 | 비고 | -|------|------|------| -| 템플릿 v2 승인 | **완료** | 버튼 URL에 `#{토큰}` 변수 포함 3종 승인 | -| `전자계약_완료` 템플릿 | **완료** | 서명 완료 알림 발송 — PDF 다운로드 버튼 | -| 역할 기반 알림 분기 | **완료** | 본사(creator)=이메일, 상대방(counterpart)=알림톡 | -| OTP SMS 발송 | **완료** | 상대방에게 SMS로 인증코드 발송 | -| 환경별 템플릿 분기 | **완료** | `resolveTemplateName()` — `_DEV` 접미사 자동 적용 | -| 서명 PDF 재생성 | **완료** | `downloadDocument()`에서 완료 계약 PDF 자동 재생성 | - -> 상세 가이드: [전자계약 알림톡/SMS 환경별 설정 가이드](./esign-notification-guide.md) - -### 5.4 대기 중인 항목 - -| 항목 | 상태 | 비고 | -|------|------|------| -| DEV 템플릿 검수 | **심사 중** | `admin.codebridge-x.com` 도메인 3종 | -| 친구톡 발송 | **대기** | 채널 친구 추가 후 가능 | -| 대량 발송 | **대기** | 단건 안정화 후 | - ---- - -## 6. v2 템플릿 승인 후 코드 변경 가이드 - -### 6.1 변경 대상 - -`EsignApiController::sendAlimtalk()` (약 1059~1063행) - -### 6.2 현재 코드 (v1) - -```php -// 등록된 버튼 URL을 그대로 사용 (동적 URL 사용 시 템플릿 불일치 오류) -$buttons = ! empty($templateButtons) ? $templateButtons : [ - ['Name' => '계약서 확인하기', 'ButtonType' => 'WL', - 'Url1' => 'https://mng.codebridge-x.com', 'Url2' => 'https://mng.codebridge-x.com'], -]; -``` - -### 6.3 변경 코드 (v2 승인 후) - -```php -// v2 템플릿: 버튼 URL에 동적 서명 URL 사용 -$buttons = [ - ['Name' => '계약서 확인하기', 'ButtonType' => 'WL', - 'Url1' => $signUrl, 'Url2' => $signUrl], -]; -``` - -- `$signUrl`은 1033행에서 이미 생성됨: `config('app.url').'/esign/sign/'.$signer->access_token` -- `getTemplateData()`에서 등록된 버튼 조회는 더 이상 필요 없음 (제거 가능) - ---- - -## 7. API 메서드 목록 - -### 7.1 BarobillService 카카오톡 메서드 - -| 메서드 | SOAP Action | 설명 | -|--------|-------------|------| -| `getKakaotalkChannels` | `GetKakaotalkChannels` | 채널 목록 조회 | -| `getKakaotalkChannelManagementUrl` | `GetKakaotalkChannelManagementURL` | 채널 관리 URL | -| `getKakaotalkTemplates` | `GetKakaotalkTemplates` | 템플릿 목록 조회 | -| `getKakaotalkTemplateManagementUrl` | `GetKakaotalkTemplateManagementURL` | 템플릿 관리 URL | -| `sendATKakaotalk` | `SendATKakaotalk` | 알림톡 단건 발송 | -| `sendATKakaotalkEx` | `SendATKakaotalkEx` | 알림톡 단건 발송 (버튼 포함) | -| `sendATKakaotalks` | `SendATKakaotalks` | 알림톡 대량 발송 | -| `sendFTKakaotalk` | `SendFTKakaotalk` | 친구톡 텍스트 단건 | -| `sendFTKakaotalks` | `SendFTKakaotalks` | 친구톡 텍스트 대량 | -| `sendFIKakaotalk` | `SendFIKakaotalk` | 친구톡 이미지 | -| `sendFWKakaotalk` | `SendFWKakaotalk` | 친구톡 와이드 이미지 | -| `getSendKakaotalk` | `GetSendKakaotalk` | 전송 결과 단건 조회 | -| `getSendKakaotalks` | `GetSendKakaotalks` | 전송 결과 다건 조회 | -| `cancelReservedKakaotalk` | `CancelReservedKakaotalk` | 예약 전송 취소 | - ---- - -## 8. 참고 자료 - -- [바로빌 API 문서](https://dev.barobill.co.kr) -- [카카오비즈니스 채널 관리](https://business.kakao.com) -- [카카오 알림톡 가이드](https://kakaobusiness.gitbook.io) -- 바로빌 템플릿 관리: 로그인 후 `https://www.barobill.co.kr` → 카카오톡 템플릿 관리 - ---- - -## 변경 이력 - -| 날짜 | 버전 | 변경 내용 | -|------|------|----------| -| 2026-02-27 | 1.1 | 역할 기반 알림, OTP SMS, 환경별 템플릿 분기, 완료 알림톡 추가 | -| 2026-02-24 | 1.0 | 전자계약 알림톡 연동 완료, 트러블슈팅 문서화, v2 템플릿 가이드 추가 | -| 2026-02-14 | 0.2 | 전자계약(E-Sign) 알림톡 연동 활용 계획 추가 | -| 2026-02-14 | 0.1 | 초안 작성 - 코드 구현 완료, 실 서비스 연동 대기 | diff --git a/sam/docs/features/barobill-kakaotalk/esign-notification-guide.md b/sam/docs/features/barobill-kakaotalk/esign-notification-guide.md deleted file mode 100644 index dce2345..0000000 --- a/sam/docs/features/barobill-kakaotalk/esign-notification-guide.md +++ /dev/null @@ -1,250 +0,0 @@ -# 전자계약 알림톡/SMS 환경별 설정 가이드 - -> **작성일**: 2026-02-27 -> **상태**: 운영 중 -> **대상 프로젝트**: MNG - ---- - -## 1. 개요 - -### 1.1 목적 - -전자계약(E-Sign) 시스템의 카카오톡 알림톡, SMS, 이메일 발송을 **3개 환경(로컬/개발/운영)**에서 올바르게 설정하고 테스트하기 위한 가이드이다. - -### 1.2 핵심 원칙 - -- **역할 기반 알림**: 본사(creator)는 이메일, 상대방(counterpart)은 카카오톡/SMS -- **환경별 템플릿 분리**: 운영은 원본 템플릿, 개발은 `_DEV` 접미사 템플릿 사용 -- **URL 자동 분기**: `config('app.url')`로 환경별 도메인 자동 적용 - ---- - -## 2. 환경별 설정 - -### 2.1 도메인 및 APP_URL - -| 환경 | `APP_ENV` | `APP_URL` | 알림톡 버튼 URL 도메인 | -|------|-----------|-----------|----------------------| -| 로컬 (Docker) | `local` | `https://mng.sam.kr` | 로컬 — 알림톡 미사용 | -| 개발 서버 | `local` | `https://admin.codebridge-x.com` | `admin.codebridge-x.com` | -| 운영 서버 | `production` | `https://mng.codebridge-x.com` | `mng.codebridge-x.com` | - -### 2.2 바로빌 서버 모드 - -`barobill_members.server_mode` 컬럼으로 바로빌 API 엔드포인트를 결정한다: - -| server_mode | WSDL (카카오톡) | WSDL (SMS) | 용도 | -|-------------|----------------|------------|------| -| `test` | `testws.baroservice.com/KAKAOTALK.asmx` | `testws.baroservice.com/SMS.asmx` | 테스트 | -| `production` | `ws.baroservice.com/KAKAOTALK.asmx` | `ws.baroservice.com/SMS.asmx` | 실제 발송 | - -> `server_mode`는 환경(로컬/개발/운영)과 독립적이다. 개발서버에서도 `production` 모드로 실제 발송 가능. - -### 2.3 알림톡 템플릿 환경별 분기 - -코드에서 `resolveTemplateName()` 메서드가 `APP_ENV`에 따라 템플릿명을 자동 결정한다: - -```php -private function resolveTemplateName(string $baseName): string -{ - return $baseName . (app()->environment('production') ? '' : '_DEV'); -} -``` - -| 기본 템플릿명 | 운영 (`production`) | 개발/로컬 (기타) | -|-------------|--------------------|--------------------| -| `전자계약_서명요청` | `전자계약_서명요청` | `전자계약_서명요청_DEV` | -| `전자계약_완료` | `전자계약_완료` | `전자계약_완료_DEV` | -| `전자계약_리마인드` | `전자계약_리마인드` | `전자계약_리마인드_DEV` | - ---- - -## 3. 등록된 알림톡 템플릿 - -### 3.1 운영 템플릿 (mng.codebridge-x.com) - -| 템플릿명 | 용도 | 상태 | 버튼 URL | -|---------|------|------|---------| -| `전자계약_서명요청` | 서명 요청 알림 | 승인 완료 | `https://mng.codebridge-x.com/esign/sign/#{토큰}` | -| `전자계약_완료` | 서명 완료 알림 | 승인 완료 | `https://mng.codebridge-x.com/esign/sign/#{토큰}` | -| `전자계약_리마인드` | 서명 독촉 알림 | 승인 완료 | `https://mng.codebridge-x.com/esign/sign/#{토큰}` | - -### 3.2 개발 템플릿 (admin.codebridge-x.com) - -| 템플릿명 | 용도 | 상태 | 버튼 URL | -|---------|------|------|---------| -| `전자계약_서명요청_DEV` | 서명 요청 알림 | 심사 중 | `https://admin.codebridge-x.com/esign/sign/#{토큰}` | -| `전자계약_완료_DEV` | 서명 완료 알림 | 심사 중 | `https://admin.codebridge-x.com/esign/sign/#{토큰}` | -| `전자계약_리마인드_DEV` | 서명 독촉 알림 | 심사 중 | `https://admin.codebridge-x.com/esign/sign/#{토큰}` | - -> 개발 템플릿 본문은 운영 템플릿과 동일하며, 버튼 URL 도메인만 다르다. - -### 3.3 템플릿 변수 - -| 변수 | 용도 | 사용 템플릿 | -|------|------|-----------| -| `#{이름}` | 서명자 이름 | 서명요청, 완료, 리마인드 | -| `#{계약명}` | 계약 제목 | 서명요청, 완료, 리마인드 | -| `#{기한}` | 서명 기한 | 서명요청, 리마인드 | -| `#{완료일}` | 계약 완료일 | 완료 | -| `#{토큰}` | 서명자 액세스 토큰 | 버튼 URL | - ---- - -## 4. 역할 기반 알림 흐름 - -### 4.1 전체 흐름 - -``` -① 계약 발송 ─→ 본사: 이메일 / 상대방: 카카오톡 알림톡 -② OTP 인증 ─→ 본사: 이메일 / 상대방: SMS -③ 다음 서명자 ─→ 본사: 이메일 / 상대방: 카카오톡 알림톡 -④ 서명 완료 ─→ 본사: 이메일(PDF) / 상대방: 카카오톡(PDF 다운로드) -``` - -### 4.2 역할 판별 - -```php -$isCounterpart = $signer->role === EsignSigner::ROLE_COUNTERPART; -``` - -| 역할 | 상수 | 알림톡 | SMS(OTP) | 이메일 | -|------|------|--------|----------|--------| -| 본사 (creator) | `ROLE_CREATOR` | ❌ | ❌ | ✅ 항상 | -| 상대방 (counterpart) | `ROLE_COUNTERPART` | ✅ 우선 | ✅ OTP만 | ✅ 폴백 | - -### 4.3 이메일 폴백 조건 - -상대방(counterpart)에게도 이메일을 보내는 경우: -- 전화번호가 없을 때 (`$signer->phone` 없음) -- 알림톡 발송 실패 시 (`$alimtalkFailed = true`) -- 발송 방식이 `email` 또는 `both`일 때 - -### 4.4 완료 알림 특수 처리 - -완료 알림톡 버튼은 **서명 페이지가 아닌 문서 다운로드 URL**로 강제 변경된다: - -```php -// sendCompletionAlimtalk() 내부 -$documentUrl = config('app.url') . '/esign/sign/' . $signer->access_token . '/api/document'; - -// 버튼 URL 강제 변경 (서명페이지 → 문서 다운로드) -if (str_contains($btn[$urlKey], '/esign/sign/') && !str_contains($btn[$urlKey], '/api/document')) { - $btn[$urlKey] = $documentUrl; -} -``` - ---- - -## 5. SMS (OTP 인증) - -### 5.1 발송 조건 - -상대방(counterpart)이 `alimtalk` 또는 `both` 발송 방식이고 전화번호가 있을 때 SMS로 OTP 발송: - -```php -if (in_array($sendMethod, ['alimtalk', 'both']) - && $signer->phone - && $signer->role === EsignSigner::ROLE_COUNTERPART) { - $this->sendOtpViaSms($contract, $signer, $otpCode); -} -``` - -### 5.2 SMS 발송 파라미터 - -| 항목 | 값 | -|------|-----| -| API | `BarobillService::sendSMSMessage()` | -| 발신번호 | `barobill_members.manager_hp` | -| 수신번호 | `esign_signers.phone` | -| 메시지 | `[SAM] 전자계약 인증코드: {코드} (5분 이내 입력)` | -| OTP 유효시간 | 5분 | -| 최대 시도 | 5회 | - -### 5.3 SMS 실패 시 이메일 폴백 - -SMS 발송 실패 → 이메일 OTP 폴백 → 이메일도 없으면 500 에러 반환. - ---- - -## 6. 바로빌 템플릿 등록 절차 - -### 6.1 관리자 페이지 - -``` -https://www.barobill.co.kr 로그인 → 카카오톡 → 템플릿관리 -``` - -### 6.2 DEV 템플릿 등록 시 주의사항 - -1. **본문**: 운영 템플릿과 **완전히 동일** (1글자도 다르면 안 됨) -2. **버튼 URL**: 도메인만 `admin.codebridge-x.com`으로 변경 -3. **템플릿명**: 운영 이름 + `_DEV` 접미사 (예: `전자계약_서명요청_DEV`) -4. **검수 기간**: 영업일 기준 2~3일 - -### 6.3 새 템플릿 추가 시 체크리스트 - -- [ ] 바로빌에서 운영용 + 개발용 2개 등록 -- [ ] 코드에서 `resolveTemplateName('기본명')`으로 호출 -- [ ] 본문의 변수 치환 로직 추가 (str_replace) -- [ ] 버튼 URL의 `#{토큰}` 치환 확인 -- [ ] 2단계 검증 (SendKey → GetSendKakaotalk) 포함 - ---- - -## 7. 관련 파일 - -| 파일 | 역할 | -|------|------| -| `app/Http/Controllers/ESign/EsignApiController.php` | 계약 발송, `sendAlimtalk()`, `resolveTemplateName()` | -| `app/Http/Controllers/ESign/EsignPublicController.php` | OTP SMS, 완료 알림톡, `sendCompletionAlimtalk()` | -| `app/Services/Barobill/BarobillService.php` | SOAP 클라이언트 (`sendATKakaotalkEx`, `sendSMSMessage`) | -| `app/Models/ESign/EsignSigner.php` | `ROLE_CREATOR`, `ROLE_COUNTERPART` 상수 | -| `app/Mail/EsignCompletedMail.php` | 완료 이메일 (PDF 다운로드 링크) | -| `app/Services/ESign/PdfSignatureService.php` | 서명 PDF 합성 (`mergeSignatures`) | - ---- - -## 8. 트러블슈팅 - -### 8.1 환경별 템플릿 미스매치 - -**증상**: `ResultCode=4` (템플릿 데이터 일치 오류) -**원인**: 개발서버에서 운영용 템플릿(`전자계약_서명요청`)으로 발송 시 버튼 URL 도메인 불일치 -**해결**: DEV 템플릿 등록 후 `APP_ENV`가 `production`이 아닌지 확인 - -### 8.2 서명 PDF 누락 (이메일) - -**증상**: 완료 이메일의 다운로드 링크가 서명 없는 초안 PDF 반환 -**원인**: `mergeSignatures()` 실패 → `signed_file_path` 미설정 → preview PDF 폴백 -**해결**: `downloadDocument()`가 완료 상태에서 자동 재생성 시도. 로그에서 trace 확인: - -```bash -# 개발서버 로그 확인 -ssh pro@114.203.209.83 "tail -100 /home/webservice/mng/storage/logs/laravel.log | grep 'PDF 서명'" -``` - -**주요 실패 원인**: -- `storage/fonts/Pretendard-Regular.ttf` 폰트 파일 누락 -- FPDI/TCPDF 패키지 미설치 → `composer install` 필요 -- `storage/app/esign/{tenant_id}/signed/` 디렉토리 권한 문제 - -### 8.3 MNG 모델 상수 누락 - -**증상**: `Undefined constant App\Models\ESign\EsignSigner::ROLE_COUNTERPART` -**원인**: API 프로젝트와 MNG 프로젝트의 모델이 독립적 — API에만 상수 정의됨 -**해결**: MNG `EsignSigner.php`에도 동일한 상수 추가 (2026-02-26 핫픽스 완료) - ---- - -## 관련 문서 - -- [바로빌 카카오톡 연동 README](./README.md) — SOAP API 전체 연동 가이드 -- [E-Sign 기술 설계](../../projects/e-sign/technical-design.md) — 전자계약 아키텍처 -- [E-Sign API 명세](../../projects/e-sign/api-specification.md) — API 엔드포인트 -- [알림톡 연동 계획](../../plans/esign-alimtalk-integration.md) — 초기 계획 (구현 완료) - ---- - -**최종 업데이트**: 2026-02-27 diff --git a/sam/docs/features/business-card-request.md b/sam/docs/features/business-card-request.md deleted file mode 100644 index b574f00..0000000 --- a/sam/docs/features/business-card-request.md +++ /dev/null @@ -1,173 +0,0 @@ -# 명함신청 관리 - -> **작성일**: 2026-02-25 -> **상태**: 구현 완료 - ---- - -## 1. 개요 - -### 1.1 목적 - -영업파트너가 명함을 신청하면 본사에서 제작소에 의뢰하고, 완료 후 처리하는 3단계 워크플로우를 제공한다. - -### 1.2 워크플로우 - -``` -요청(pending) ──제작의뢰──→ 제작중(ordered) ──처리완료──→ 완료(processed) - 노랑 파랑 초록 -``` - -### 1.3 메뉴 구조 - -| 메뉴 | URL | 대상 | 설명 | -|------|-----|------|------| -| 파트너 명함신청 | `/sales/business-cards` | 모든 사용자 | 신청폼 + 내 이력 | -| 명함신청 처리 | `/sales/business-cards/manage` | 관리자 전용 | 3단계 처리 + 뱃지 | - ---- - -## 2. 테이블 구조 - -### 2.1 `business_card_requests` - -| 필드 | 타입 | 설명 | -|------|------|------| -| `id` | bigint | PK | -| `tenant_id` | bigint | 테넌트 ID | -| `user_id` | bigint | 신청자 ID | -| `name` | varchar(50) | 성함 | -| `phone` | varchar(20) | 전화번호 | -| `title` | varchar(50) | 직함 (nullable) | -| `email` | varchar(100) | 이메일 (nullable) | -| `quantity` | int | 수량 (기본 100) | -| `memo` | text | 비고 (nullable) | -| `status` | varchar(20) | 상태: `pending`, `ordered`, `processed` | -| `ordered_by` | bigint | 제작의뢰 처리자 ID (nullable) | -| `ordered_at` | timestamp | 제작의뢰 일시 (nullable) | -| `processed_by` | bigint | 처리완료 처리자 ID (nullable) | -| `processed_at` | timestamp | 처리완료 일시 (nullable) | -| `process_memo` | text | 처리 메모 (nullable) | -| `created_at` | timestamp | 생성일 | -| `updated_at` | timestamp | 수정일 | - -**인덱스**: `(tenant_id, status)`, `user_id` - ---- - -## 3. 상태 전이 - -``` -pending ──→ ordered ──→ processed - │ ▲ - └── (역방향 전이 없음) ──┘ -``` - -| 상태 | 라벨 | 색상 | 설명 | -|------|------|------|------| -| `pending` | 요청 | 노랑 | 파트너가 신청, 관리자 확인 대기 | -| `ordered` | 제작의뢰 | 파랑 | 관리자가 제작소에 의뢰 | -| `processed` | 처리완료 | 초록 | 제작 완료, 전달 완료 | - ---- - -## 4. API 엔드포인트 - -| Method | Path | 이름 | 설명 | -|--------|------|------|------| -| GET | `/sales/business-cards` | `sales.business-cards.index` | 파트너 명함신청 (신청폼 + 이력) | -| POST | `/sales/business-cards` | `sales.business-cards.store` | 신청 등록 | -| GET | `/sales/business-cards/manage` | `sales.business-cards.manage` | 관리자 처리 화면 | -| POST | `/sales/business-cards/{id}/order` | `sales.business-cards.order` | 제작의뢰 (관리자) | -| POST | `/sales/business-cards/{id}/process` | `sales.business-cards.process` | 처리완료 (관리자) | - ---- - -## 5. 파일 구조 - -### 5.1 API 프로젝트 - -| 파일 | 설명 | -|------|------| -| `database/migrations/2026_02_24_100000_create_business_card_requests_table.php` | 테이블 생성 | -| `database/migrations/2026_02_25_100000_add_ordered_columns_to_business_card_requests_table.php` | ordered 컬럼 추가 | - -### 5.2 MNG 프로젝트 - -| 파일 | 설명 | -|------|------| -| `app/Models/Sales/BusinessCardRequest.php` | 모델 (상태 상수, 스코프, 헬퍼) | -| `app/Services/Sales/BusinessCardRequestService.php` | 서비스 (CRUD, 통계, 뱃지) | -| `app/Http/Controllers/Sales/BusinessCardRequestController.php` | 컨트롤러 | -| `app/Providers/ViewServiceProvider.php` | 사이드바 뱃지 연동 | -| `routes/web.php` | 라우트 5개 | -| `resources/views/sales/business-cards/admin-index.blade.php` | 관리자 뷰 | -| `resources/views/sales/business-cards/partner-index.blade.php` | 파트너 뷰 | - ---- - -## 6. 화면 구성 - -### 6.1 파트너 명함신청 (`partner-index`) - -``` -┌─ 회사 정보 안내 (코드브릿지엑스) ──────────────┐ -├─ 신청 폼 ─────────────────────────────────────┤ -│ 성함* │ 직함 │ 전화번호* │ 이메일 │ -│ 수량 │ 메모 │ [명함 신청하기] │ -├─ 내 신청 이력 ────────────────────────────────┤ -│ 신청일 │ 성함 │ 직함 │ 전화번호 │ 수량 │ 상태 │ -│ (요청=노랑, 제작중=파랑, 처리완료=초록) │ -└───────────────────────────────────────────────┘ -``` - -- 로그인 사용자 정보(name, phone, email)로 자동 채움 -- 관리자도 동일한 화면 접근 가능 - -### 6.2 명함신청 처리 (`admin-index`) - -``` -┌─ 통계 ──────────────────────────────────────┐ -│ 신규요청(노랑) │ 제작의뢰(파랑) │ 오늘처리(초록) │ 전체 │ -├─────────────────┬───────────────────────────┤ -│ 신규 요청 │ 제작 중 │ -│ [제작의뢰] 버튼 │ 의뢰일 + [처리완료] 버튼 │ -├─────────────────┴───────────────────────────┤ -│ 처리 완료 이력 (하단 스크롤 테이블) │ -└─────────────────────────────────────────────┘ -``` - -- 사이드바 뱃지: 요청 + 제작의뢰 합산 건수 표시 -- 처리 버튼 클릭 시 `showConfirm()` 확인 다이얼로그 - ---- - -## 7. 뱃지 연동 - -`ViewServiceProvider`에서 `BusinessCardRequestService::getPendingCount()`를 호출하여 사이드바 메뉴 뱃지에 대기 건수를 표시한다. - -- **카운트 기준**: `pending` + `ordered` 합산 -- **표시 위치**: "명함신청 처리" 메뉴 (`sales.business-cards.manage`) -- **0건일 때**: 뱃지 미표시 - ---- - -## 8. 메뉴 등록 정보 - -| ID | parent_id | 이름 | URL | sort_order | -|----|-----------|------|-----|------------| -| 15507 | 15456 | 파트너 명함신청 | `/sales/business-cards` | 5 | -| 15508 | 15456 | 명함신청 처리 | `/sales/business-cards/manage` | 6 | - -> 영업파트너에게는 "파트너 명함신청"만 보이도록 메뉴 권한 설정 필요 - ---- - -## 관련 문서 - -- 참고 패턴: `api/app/Models/CompanyRequest.php` (상태 관리 모델) -- 참고 뷰: `mng/resources/views/sales/managers/approvals.blade.php` (2분할 레이아웃) - ---- - -**최종 업데이트**: 2026-02-25 diff --git a/sam/docs/features/credit-evaluation/README.md b/sam/docs/features/credit-evaluation/README.md deleted file mode 100644 index d4d38b3..0000000 --- a/sam/docs/features/credit-evaluation/README.md +++ /dev/null @@ -1,284 +0,0 @@ -# 신용평가 시스템 (쿠콘 연동) - -> **작성일**: 2026-03-02 -> **상태**: 운영중 - ---- - -## 1. 개요 - -### 1.1 목적 - -SAM에서 거래처/협력업체의 **기업 신용정보를 조회**하여, 거래 안전성을 사전 판단하는 시스템이다. - -### 1.2 핵심 원칙 - -- **쿠콘(KooCon/나이스평가정보)** API로 기업 신용정보 7개 항목 조회 -- **국세청 공공데이터포털** API로 사업자등록 상태(영업/휴업/폐업) 확인 -- 모든 조회 결과는 DB에 원본 저장 (감사 추적용) -- 테넌트별 월 5건 무료, 초과 시 건당 2,000원 과금 - ---- - -## 2. 시스템 구조 - -### 2.1 전체 흐름 - -``` -사용자 (SAM MNG) - │ - ▼ -CreditController::search() - │ - ├──▶ CooconService::getAllCreditInfo() - │ ├── OA08: 기업 기본정보 - │ ├── OA12: 신용요약정보 - │ ├── OA13: 단기연체정보 - │ ├── OA14: 신용도판단정보 (KCI) - │ ├── OA15: 신용도판단정보 (CB) - │ ├── OA16: 당좌거래정지정보 - │ └── OA17: 법정관리/워크아웃 - │ - ├──▶ NtsBusinessService::getBusinessStatus() - │ └── 국세청 사업자등록 상태 조회 - │ - └──▶ CreditInquiry::createFromApiResponse() - └── DB에 조회 이력 저장 -``` - -### 2.2 파트너 구조 - -| 역할 | 대상 | 설명 | -|------|------|------| -| **API 제공사** | 쿠콘(KooCon) / 나이스평가정보 | 기업 신용정보 API 플랫폼 | -| **파트너사** | (주)코드브릿지엑스 | API 키 보유, 쿠콘과 직접 계약 | -| **이용사** | 각 테넌트 (주일, 경동 등) | SAM을 통해 신용조회 실행 | - ---- - -## 3. 쿠콘(KooCon) API - -### 3.1 API 엔드포인트 - -| 환경 | URL | -|------|-----| -| 테스트 | `https://dev2.coocon.co.kr:8443/sol/gateway/oapi_relay.jsp` | -| 운영 | `https://sgw.coocon.co.kr/sol/gateway/oapi_relay.jsp` | - -### 3.2 인증 방식 - -- **API_KEY**: 쿠콘에서 발급받은 인증키 (DB `coocon_configs` 테이블에서 관리) -- **API_ID**: 조회할 API 식별자 (OA08~OA17) -- **TR_SEQ**: 거래일련번호 (중복 방지용, `YmdHis` + 마이크로초 6자리) - -### 3.3 요청 형식 - -```json -{ - "API_KEY": "발급받은_API_키", - "API_ID": "OA12", - "TR_SEQ": "20260302173000123456", - "COMPANY_KEY": "1234567890" -} -``` - -- **Method**: POST -- **Content-Type**: application/json -- **Timeout**: 30초 - -### 3.4 API 목록 - -| API ID | 상수명 | 설명 | 데이터 출처 | -|--------|--------|------|------------| -| `OA08` | `API_COMPANY_INFO` | 기업 기본정보 | 나이스평가정보 | -| `OA12` | `API_CREDIT_SUMMARY` | 신용요약정보 (이슈 건수 요약) | 나이스평가정보 | -| `OA13` | `API_SHORT_TERM_OVERDUE` | 단기연체정보 | 한국신용정보원 | -| `OA14` | `API_NEGATIVE_INFO_KCI` | 신용도판단정보 (KCI) | 한국신용정보원 + 공공정보 | -| `OA15` | `API_NEGATIVE_INFO_CB` | 신용도판단정보 (CB) | 신용정보사 | -| `OA16` | `API_SUSPENSION_INFO` | 당좌거래정지정보 | 금융결제원 | -| `OA17` | `API_WORKOUT_INFO` | 법정관리/워크아웃정보 | 법원 | - -### 3.5 응답 형식 - -```json -{ - "RSLT_CD": "00000000", - "RSLT_MSG": "정상처리되었습니다.", - "RSLT_DATA": { ... } -} -``` - -- `RSLT_CD === '00000000'`: 성공 -- 기타 값: 에러 (에러 메시지는 `RSLT_MSG`에 포함) - ---- - -## 4. 국세청 사업자등록 조회 API - -### 4.1 API 정보 - -| 항목 | 값 | -|------|------| -| URL | `https://api.odcloud.kr/api/nts-businessman/v1/status` | -| 인증 | serviceKey (쿼리 파라미터) | -| 출처 | 공공데이터포털 | - -### 4.2 상태 코드 - -| 코드 | 상태 | 설명 | -|------|------|------| -| `01` | 계속사업자 | 정상 영업 중 | -| `02` | 휴업자 | 영업 중지 | -| `03` | 폐업자 | 사업 종료 | - ---- - -## 5. 데이터베이스 - -### 5.1 `coocon_configs` — API 설정 - -| 컬럼 | 타입 | 설명 | -|------|------|------| -| `id` | BIGINT PK | | -| `name` | VARCHAR(100) | 설정 이름 | -| `environment` | ENUM('test', 'production') | 환경 | -| `api_key` | VARCHAR(100) | 쿠콘 API 키 | -| `base_url` | VARCHAR(255) | API 기본 URL | -| `description` | TEXT | 설명 | -| `is_active` | BOOLEAN | 활성화 여부 | - -> **규칙**: 환경당 1개만 활성화 가능. 새 설정 활성화 시 기존 설정은 자동 비활성화. - -### 5.2 `credit_inquiries` — 조회 이력 - -| 컬럼 | 타입 | 설명 | -|------|------|------| -| `id` | BIGINT PK | | -| `tenant_id` | BIGINT FK | 테넌트 | -| `inquiry_key` | VARCHAR(32) UNIQUE | 조회 고유키 | -| `company_key` | VARCHAR(20) | 사업자번호/법인번호 | -| `company_name` | VARCHAR | 업체명 | -| `user_id` | BIGINT FK | 조회자 | -| `inquired_at` | TIMESTAMP | 조회 일시 | -| `nts_status` | VARCHAR(20) | 국세청 상태 | -| `nts_status_code` | VARCHAR(2) | 국세청 상태코드 | -| `short_term_overdue_cnt` | UINT | 단기연체 건수 | -| `negative_info_kci_cnt` | UINT | KCI 건수 | -| `negative_info_pb_cnt` | UINT | 공공정보 건수 | -| `negative_info_cb_cnt` | UINT | CB 건수 | -| `suspension_info_cnt` | UINT | 당좌거래정지 건수 | -| `workout_cnt` | UINT | 법정관리/워크아웃 건수 | -| `raw_*` | JSON | 각 API 원본 응답 (7개 + NTS) | -| `status` | ENUM | success / partial / failed | - ---- - -## 6. 과금 정책 - -| 항목 | 값 | -|------|------| -| 월 무료 할당량 | **5건** | -| 초과 건당 요금 | **2,000원** | -| 계산식 | `max(0, (조회건수 - 5)) × 2,000` | - -### 요금 예시 - -| 월 조회 건수 | 무료 | 유료 | 요금 | -|-------------|------|------|------| -| 3건 | 3 | 0 | 0원 | -| 5건 | 5 | 0 | 0원 | -| 10건 | 5 | 5 | 10,000원 | -| 20건 | 5 | 15 | 30,000원 | - ---- - -## 7. 환경 설정 - -### 7.1 테스트/운영 분리 - -| 환경 | API URL | 설명 | -|------|---------|------| -| 테스트 | `dev2.coocon.co.kr:8443` | 개발/검증용 (과금 없음) | -| 운영 | `sgw.coocon.co.kr` | 실 서비스 (과금 발생) | - -- `coocon_configs` 테이블에서 환경별로 별도 설정 관리 -- 각 환경에서 `is_active=true`인 설정 1개만 사용 - -### 7.2 필요한 설정 - -| 항목 | 관리 위치 | 설명 | -|------|----------|------| -| 쿠콘 API 키 | DB (`coocon_configs`) | 쿠콘에서 발급 | -| 쿠콘 API URL | DB (`coocon_configs`) | 환경별 URL | -| 국세청 API 키 | 코드 내 하드코딩 | 공공데이터포털 발급 | - ---- - -## 8. MNG 라우트 - -| Method | Path | 설명 | -|--------|------|------| -| GET | `/credit/inquiry` | 조회 이력 목록 | -| POST | `/credit/inquiry/search` | 신용정보 조회 실행 | -| POST | `/credit/inquiry/test` | API 연결 테스트 | -| GET | `/credit/inquiry/{key}/raw` | 원본 데이터 조회 | -| GET | `/credit/inquiry/{key}/report` | 리포트 조회 | -| DELETE | `/credit/inquiry/{id}` | 이력 삭제 | -| GET | `/credit/usage` | 조회회수 집계 | -| GET | `/credit/settings` | 설정 관리 | -| POST | `/credit/settings` | 설정 생성 | -| PUT | `/credit/settings/{id}` | 설정 수정 | -| DELETE | `/credit/settings/{id}` | 설정 삭제 | -| POST | `/credit/settings/{id}/toggle` | 활성화 토글 | - ---- - -## 9. 에러 코드 - -### 9.1 쿠콘 API - -| 코드 | 설명 | -|------|------| -| `NO_CONFIG` | API 설정 없음 | -| `HTTP_ERROR` | HTTP 통신 오류 | -| `EXCEPTION` | 예외 발생 | -| `RSLT_CD ≠ 00000000` | 쿠콘 API 에러 (RSLT_MSG 참조) | - -### 9.2 국세청 API - -| 코드 | 설명 | -|------|------| -| `INVALID_FORMAT` | 사업자번호 형식 오류 | -| `NOT_FOUND` | 조회 결과 없음 | -| `HTTP_ERROR` | HTTP 통신 오류 | - ---- - -## 10. 관련 파일 - -### MNG 프로젝트 - -| 구분 | 경로 | -|------|------| -| 컨트롤러 | `app/Http/Controllers/Credit/CreditController.php` | -| 컨트롤러 | `app/Http/Controllers/Credit/CreditUsageController.php` | -| 서비스 | `app/Services/Coocon/CooconService.php` | -| 서비스 | `app/Services/Nts/NtsBusinessService.php` | -| 모델 | `app/Models/Coocon/CooconConfig.php` | -| 모델 | `app/Models/Credit/CreditInquiry.php` | -| 뷰 | `resources/views/credit/inquiry/index.blade.php` | -| 뷰 | `resources/views/credit/usage/index.blade.php` | -| 뷰 | `resources/views/credit/settings/index.blade.php` | - -### API 프로젝트 (마이그레이션) - -| 경로 | -|------| -| `database/migrations/2026_01_22_192637_create_coocon_configs_table.php` | -| `database/migrations/2026_01_22_201143_create_credit_inquiries_table.php` | -| `database/migrations/2026_01_22_203001_add_company_info_to_credit_inquiries_table.php` | -| `database/migrations/2026_01_28_163000_add_tenant_id_to_credit_inquiries_table.php` | - ---- - -**최종 업데이트**: 2026-03-02 diff --git a/sam/docs/features/documents/README.md b/sam/docs/features/documents/README.md deleted file mode 100644 index ab1f4d5..0000000 --- a/sam/docs/features/documents/README.md +++ /dev/null @@ -1,122 +0,0 @@ -# 문서관리 시스템 (Document Management) - -> **상태**: API 완전 구현 -> **최종 갱신**: 2026-02-27 - ---- - -## 1. 개요 - -EAV(Entity-Attribute-Value) 패턴 기반의 동적 문서 관리 시스템. 문서 서식(Template)을 정의하면 해당 서식에 따라 문서를 생성·결재·관리할 수 있다. 제품 검사(FQC), 공정 검사 등 다양한 문서 유형을 하나의 시스템으로 처리한다. - -**핵심 기능:** -- 문서 서식(Template) 관리: 결재선, 기본필드, 섹션, 컬럼 정의 -- EAV 기반 동적 데이터 저장 (section_id + column_id + row_index + field_key) -- 결재 워크플로우: 작성 → 검토 → 승인 (다단계) -- FQC(제품검사) 일괄 생성 및 진행 현황 -- 첨부파일 관리 (서명, 이미지, 참조 문서) - ---- - -## 2. 모델 - -### 서식 (Template) 계층 - -| 모델 | 설명 | -|------|------| -| `DocumentTemplate` | 서식 마스터 (이름, 카테고리, 회사 정보, 활성 여부) | -| `DocumentTemplateApprovalLine` | 결재선 (이름, 부서, 역할, 순서) | -| `DocumentTemplateBasicField` | 기본 필드 (라벨, 유형, 기본값) | -| `DocumentTemplateSection` | 섹션 (제목, 이미지, 순서) | -| `DocumentTemplateSectionField` | 섹션 필드 (field_key, 유형, 옵션, 필수 여부) | -| `DocumentTemplateColumn` | 컬럼 (라벨, 너비, 유형, 하위 라벨) | -| `DocumentTemplateLink` | 서식 간 연결 | - -### 문서 (Document) 계층 - -| 모델 | 설명 | Traits | -|------|------|--------| -| `Document` | 문서 인스턴스 (서식 기반, 상태, 연결 대상) | BelongsToTenant, Auditable, SoftDeletes | -| `DocumentApproval` | 결재 기록 (단계, 역할, 상태, 코멘트) | BelongsToTenant | -| `DocumentData` | EAV 데이터 (section + column + row + field_key → value) | BelongsToTenant | -| `DocumentAttachment` | 첨부파일 (유형: general, signature, image, reference) | BelongsToTenant | - -**문서 상태 흐름:** -``` -DRAFT → PENDING → APPROVED - → REJECTED → DRAFT (재작성) - → CANCELLED -``` - -**컬럼 유형:** text, check, complex, select, measurement - ---- - -## 3. 서비스 - -| 서비스 | 주요 메서드 | -|--------|-----------| -| `DocumentService` | list, show, create, update, destroy, submit, approve, reject, cancel, bulkCreateFqc, fqcStatus, resolve, upsert, formatTemplateForReact | -| `DocumentTemplateService` | list, show | - ---- - -## 4. API 엔드포인트 - -### 서식 조회 (읽기 전용) - -| HTTP | URI | 설명 | -|------|-----|------| -| GET | `/v1/document-templates` | 서식 목록 | -| GET | `/v1/document-templates/{id}` | 서식 상세 (필드·컬럼·섹션 포함) | - -### 문서 CRUD + 워크플로우 - -| HTTP | URI | 설명 | -|------|-----|------| -| GET | `/v1/documents` | 문서 목록 (필터: status, template_id, 날짜, 검색) | -| POST | `/v1/documents` | 문서 생성 | -| GET | `/v1/documents/{id}` | 문서 상세 | -| PATCH | `/v1/documents/{id}` | 문서 수정 | -| DELETE | `/v1/documents/{id}` | 문서 삭제 | -| POST | `/v1/documents/{id}/submit` | 결재 요청 | -| POST | `/v1/documents/{id}/approve` | 승인 | -| POST | `/v1/documents/{id}/reject` | 반려 | -| POST | `/v1/documents/{id}/cancel` | 취소/회수 | - -### 특수 기능 - -| HTTP | URI | 설명 | -|------|-----|------| -| POST | `/v1/documents/bulk-create-fqc` | FQC 일괄 생성 | -| GET | `/v1/documents/fqc-status` | FQC 진행 현황 | -| GET | `/v1/documents/resolve` | 카테고리+item_id로 문서 조회 | -| POST | `/v1/documents/upsert` | 생성 또는 업데이트 | - ---- - -## 5. FormRequest - -| Request | 주요 검증 | -|---------|----------| -| `StoreRequest` | template_id (필수, exists), title, approvers[], data[] (EAV), attachments[] | -| `UpdateRequest` | title, data[] (EAV), attachments[] | -| `IndexRequest` | status, template_id, search, 날짜 범위, 정렬 | -| `BulkCreateFqcRequest` | order_id, template_id, item_count | -| `ResolveRequest` | category, item_id | -| `ApproveRequest` | comment (선택) | -| `RejectRequest` | comment (필수) | - ---- - -## 관련 문서 - -- [MNG 문서관리 시스템 상세](mng-document-system.md) — MNG 화면 구성, 탭별 기능, 서식 빌더, EAV 저장 패턴 상세 -- [MNG 문서양식관리](mng-document-template.md) — 서식 생성/편집, Legacy/Block Builder, 프리셋, 연결품목 관리 -- [DB 스키마 — 문서/전자서명](../../system/database/documents.md) -- [게시판 시스템](../boards/README.md) — 유사한 EAV 패턴 적용 -- Swagger: `/api-docs` → Documents 섹션 - ---- - -**최종 업데이트**: 2026-03-06 diff --git a/sam/docs/features/documents/mng-document-system.md b/sam/docs/features/documents/mng-document-system.md deleted file mode 100644 index eae95a6..0000000 --- a/sam/docs/features/documents/mng-document-system.md +++ /dev/null @@ -1,738 +0,0 @@ -# MNG 문서관리 시스템 상세 기술 명세 - -> **작성일**: 2026-03-06 -> **상태**: 운영 중 -> **프로젝트**: SAM MNG (관리자 웹) -> **관련**: [README.md](README.md) (API 명세) - ---- - -## 1. 개요 - -### 1.1 목적 - -블라인드/스크린 제조 현장의 **검사 성적서, 작업일지, 수입검사 기록** 등 품질/생산 문서를 전자화하여 관리하는 시스템. 문서 양식(Template)을 정의하면 EAV 패턴으로 데이터를 동적 저장하며, 다단계 결재 워크플로우를 지원한다. - -### 1.2 핵심 특징 - -| 특징 | 설명 | -|------|------| -| **EAV 패턴** | 양식별로 다른 필드를 하나의 `document_data` 테이블에 저장 | -| **2가지 양식 빌더** | 레거시 빌더 (DB 정규화) + 블록 빌더 (A4 JSON 스키마) | -| **결재 워크플로우** | 작성 → 검토 → 승인 (다단계 순차 결재) | -| **자동 데이터 매핑** | 작업지시서/수주 데이터에서 기본필드 자동 채움 | -| **다형성 연결** | work_order, sales_order 등 다양한 모델과 연결 | -| **자재 LOT 추적** | 검사 문서에서 투입 자재의 LOT 이력 조회 | - -### 1.3 문서 구조 - -| 문서 | 설명 | -|------|------| -| [README.md](README.md) | API 엔드포인트, 모델 요약, FormRequest | -| **이 문서** | MNG 화면별 상세, 동작원리, 데이터 흐름 | - ---- - -## 2. 메뉴/탭 구조 - -``` -생산 관리 -└── 문서관리 - ├── 문서 목록 /documents ← 문서 검색/필터/관리 - ├── 새 문서 작성 /documents/create ← 템플릿 선택 → 폼 입력 - ├── 문서 상세 /documents/{id} ← 읽기 전용 + 결재 현황 - ├── 문서 수정 /documents/{id}/edit ← DRAFT/REJECTED만 - ├── 인쇄 /documents/{id}/print ← 성적서 인쇄용 - │ - └── 문서양식 관리 - ├── 양식 목록 /document-templates ← 양식 검색/관리 - ├── 새 양식 (레거시) /document-templates/create ← 레거시 빌더 - ├── 양식 수정 /document-templates/{id}/edit ← 자동 빌더 판별 - ├── 양식 디자이너 /document-templates/block-create ← 블록 빌더 - └── 블록 수정 /document-templates/{id}/block-edit ← 블록 빌더 수정 -``` - ---- - -## 3. 파일 구조 - -``` -mng/ -├── app/Http/Controllers/ -│ ├── DocumentController.php ← 문서 CRUD 화면 -│ └── DocumentTemplateController.php ← 양식 관리 화면 -├── app/Models/Documents/ -│ ├── Document.php ← 문서 모델 -│ ├── DocumentApproval.php ← 결재 단계 -│ ├── DocumentData.php ← EAV 데이터 -│ ├── DocumentTemplate.php ← 양식 마스터 -│ └── ... (기타 템플릿 관련 모델) -└── resources/views/ - ├── documents/ - │ ├── index.blade.php ← 문서 목록 - │ ├── edit.blade.php ← 문서 작성/수정 - │ ├── show.blade.php ← 문서 상세 - │ └── print.blade.php ← 인쇄 전용 - └── document-templates/ - ├── index.blade.php ← 양식 목록 - ├── edit.blade.php ← 레거시 빌더 - ├── block-editor.blade.php ← 블록 빌더 - └── partials/ - ├── block-palette.blade.php ← 블록 타입 목록 - ├── block-canvas.blade.php ← 편집 캔버스 - └── block-properties.blade.php ← 속성 패널 -``` - ---- - -## 4. 데이터베이스 아키텍처 - -### 4.1 테이블 관계도 - -``` -document_templates (양식 마스터) -├── 1:N → document_template_approval_lines (결재선 정의) -├── 1:N → document_template_basic_fields (기본필드 정의) -├── 1:N → document_template_sections (섹션 정의) -│ └── 1:N → document_template_section_items (검사항목) -├── 1:N → document_template_columns (테이블 컬럼 정의) -├── 1:N → document_template_section_fields (섹션 필드) -├── 1:N → document_template_links (외부 연결 정의) -│ └── 1:N → document_template_link_values (템플릿 레벨 연결값) -│ -└── 1:N → documents (문서 인스턴스) - ├── 1:N → document_approvals (결재 진행) - ├── 1:N → document_data (EAV 필드값) - ├── 1:N → document_attachments (첨부파일) - └── 1:N → document_links (문서 레벨 연결) -``` - -### 4.2 documents (문서) - -| 컬럼 | 타입 | 설명 | -|------|------|------| -| `id` | BIGINT PK | | -| `tenant_id` | BIGINT FK | 테넌트 격리 | -| `template_id` | BIGINT FK | 사용 양식 | -| `document_no` | VARCHAR UNIQUE | 문서번호 (자동 채번) | -| `title` | VARCHAR | 문서 제목 | -| `status` | VARCHAR(20) | 상태 (5가지) | -| `linkable_type` | VARCHAR NULL | 다형성 모델 타입 | -| `linkable_id` | BIGINT NULL | 다형성 모델 ID | -| `submitted_at` | TIMESTAMP NULL | 결재 요청 일시 | -| `completed_at` | TIMESTAMP NULL | 결재 완료 일시 | -| `created_by` | BIGINT FK | 작성자 | -| `deleted_at` | TIMESTAMP NULL | 소프트 삭제 | - -**인덱스**: `(tenant_id, status)`, `document_no`, `(linkable_type, linkable_id)` - -### 4.3 document_data (EAV 필드값) - -| 컬럼 | 타입 | 설명 | -|------|------|------| -| `id` | BIGINT PK | | -| `document_id` | BIGINT FK | 소속 문서 | -| `section_id` | BIGINT FK NULL | 소속 섹션 (NULL=기본필드) | -| `column_id` | BIGINT FK NULL | 소속 컬럼 (테이블 데이터용) | -| `row_index` | INT | 테이블 행 번호 (기본: 0) | -| `field_key` | VARCHAR | 필드 식별자 (`bf_1`, `cf_2`, `col_3`) | -| `field_value` | TEXT NULL | 실제 값 | - -**인덱스**: `(document_id, section_id)`, `(document_id, field_key)` - -### 4.4 document_approvals (결재) - -| 컬럼 | 타입 | 설명 | -|------|------|------| -| `id` | BIGINT PK | | -| `document_id` | BIGINT FK | 소속 문서 | -| `user_id` | BIGINT FK | 결재자 | -| `step` | INT | 결재 순서 (1, 2, 3...) | -| `role` | VARCHAR | 역할 (작성, 검토, 승인) | -| `status` | VARCHAR(20) | PENDING / APPROVED / REJECTED | -| `comment` | TEXT NULL | 결재 의견 | -| `acted_at` | TIMESTAMP NULL | 처리 일시 | - -**인덱스**: `(document_id, step)`, `(user_id, status)` - -### 4.5 document_attachments (첨부파일) - -| 컬럼 | 타입 | 설명 | -|------|------|------| -| `document_id` | BIGINT FK | 소속 문서 | -| `file_id` | BIGINT FK | File 모델 연결 | -| `attachment_type` | VARCHAR | `general`, `signature`, `image`, `reference` | -| `description` | VARCHAR NULL | 설명 | -| `created_by` | BIGINT FK | 업로드자 | - ---- - -## 5. 양식(Template) 시스템 - -### 5.1 두 가지 빌더 방식 - -| 방식 | 필드명 | 저장 구조 | UI | 상태 | -|------|--------|----------|-----|------| -| **레거시 빌더** | `builder_type = null` | 정규화 테이블들 | `edit.blade.php` | 기존 양식용 | -| **블록 빌더** | `builder_type = 'block'` | `schema` JSON | `block-editor.blade.php` | 신규 양식용 | - -**자동 판별 로직:** - -```php -// DocumentTemplateController::edit() -if ($template->isBlockBuilder()) { - return $this->blockEdit($id); // block-editor.blade.php -} else { - return view('document-templates.edit'); // 레거시 -} -``` - -### 5.2 양식 마스터 (document_templates) - -| 컬럼 | 타입 | 설명 | -|------|------|------| -| `name` | VARCHAR | 양식명 (예: "제품검사 성적서") | -| `category` | VARCHAR | 분류 (common_codes 기반) | -| `title` | VARCHAR NULL | 문서 제목 템플릿 | -| `company_name` | VARCHAR NULL | 회사명 | -| `company_address` | VARCHAR NULL | 회사 주소 | -| `company_contact` | VARCHAR NULL | 연락처 | -| `footer_remark_label` | VARCHAR NULL | 비고란 라벨 | -| `footer_judgement_label` | VARCHAR NULL | 판정란 라벨 | -| `footer_judgement_options` | JSON NULL | 판정 선택지 (적합/부적합) | -| `builder_type` | VARCHAR NULL | `block` 또는 NULL | -| `schema` | JSON NULL | 블록 빌더 JSON 스키마 | -| `page_config` | JSON NULL | 페이지 설정 (A4, 여백 등) | -| `is_active` | BOOLEAN | 활성 여부 | - -### 5.3 레거시 빌더 구성 요소 - -#### 결재선 (document_template_approval_lines) - -``` -step 1: 작성 (작성자 본인) -step 2: 검토 (팀장) -step 3: 승인 (부장) -``` - -| 컬럼 | 설명 | -|------|------| -| `name` | 라벨 (작성, 검토, 승인) | -| `dept` | 부서 | -| `role` | 역할 | -| `sort_order` | 순서 | - -#### 기본필드 (document_template_basic_fields) - -문서 상단의 고정 필드 영역. - -| 컬럼 | 설명 | -|------|------| -| `label` | 필드 라벨 (품명, LOT NO, 납기일 등) | -| `field_key` | 식별자 (EAV 저장 시 사용) | -| `field_type` | 입력 타입 (text, date, number, item_search) | -| `default_value` | 기본값 | -| `sort_order` | 순서 | - -**EAV 저장 시 field_key 패턴:** - -``` -bf_1 → 기본필드 ID 1 (예: 품명) -bf_2 → 기본필드 ID 2 (예: LOT NO) -bf_3 → 기본필드 ID 3 (예: 납기일) -``` - -#### 섹션 (document_template_sections) - -검사 기준서의 섹션 단위. - -| 컬럼 | 설명 | -|------|------| -| `title` | 섹션 제목 (예: "겉모양 검사", "치수 검사") | -| `image_path` | 도해 이미지 경로 (검사 부위 도면) | -| `sort_order` | 순서 | - -#### 검사항목 (document_template_section_items) - -각 섹션 내의 개별 검사항목. - -| 컬럼 | 타입 | 설명 | -|------|------|------| -| `category` | VARCHAR | 구분 (겉모양, 치수, 재질) | -| `item` | VARCHAR | 검사항목명 | -| `standard` | VARCHAR | 검사기준 (100mm ±5mm) | -| `tolerance` | JSON NULL | 허용오차 (min/max) | -| `standard_criteria` | VARCHAR NULL | 판정기준 | -| `method` | VARCHAR | 검사방법 (육안, 측정) | -| `measurement_type` | VARCHAR NULL | 측정 유형 | -| `frequency_n` | INT NULL | 검사건수 N | -| `frequency_c` | INT NULL | 합격건수 C | -| `frequency` | VARCHAR NULL | 검사빈도 텍스트 | -| `field_values` | JSON NULL | 확장 필드 (마이그레이션 없이 추가) | - -#### 테이블 컬럼 (document_template_columns) - -검사 데이터 테이블의 컬럼 정의. - -| 컬럼 | 타입 | 설명 | -|------|------|------| -| `label` | VARCHAR | 컬럼 라벨 | -| `width` | INT NULL | 너비 (px) | -| `column_type` | VARCHAR | `text`, `check`, `complex`, `measurement`, `select` | -| `group_name` | VARCHAR NULL | 상단 병합 헤더명 | -| `sub_labels` | JSON NULL | complex 타입 하위 라벨 | -| `sort_order` | INT | 순서 | - -**컬럼 타입 상세:** - -| 타입 | 설명 | 예시 | -|------|------|------| -| `text` | 단순 텍스트 입력 | 비고, 메모 | -| `check` | 체크박스 (합격/부적합) | 외관 검사 합격 여부 | -| `complex` | 여러 서브필드 조합 | 측정값 + 단위 + 판정 | -| `measurement` | 수치 입력 | 길이: 100.5mm | -| `select` | 드롭다운 선택 | 판정: 합격/불합격/보류 | - -#### 외부 연결 (document_template_links) - -템플릿에서 외부 테이블 데이터를 참조하기 위한 정의. - -| 컬럼 | 설명 | -|------|------| -| `link_key` | 연결 식별자 | -| `label` | 화면 라벨 | -| `link_type` | `single` (1개 선택) / `multiple` (다중 선택) | -| `source_table` | 소스 테이블 (`items`, `processes`, `users`) | -| `search_params` | API 검색 추가 조건 (JSON) | -| `display_fields` | 표시 필드 (title, subtitle) | -| `is_required` | 필수 여부 | - -### 5.4 블록 빌더 구조 - -**페이지 설정 (page_config):** - -```json -{ - "size": "A4", - "orientation": "portrait", - "margin": { - "top": 20, - "right": 15, - "bottom": 20, - "left": 15 - } -} -``` - -**스키마 (schema):** - -블록 배열로 레이아웃 정의. 드래그앤드롭으로 편집. - -```json -{ - "blocks": [ - { "type": "text", "x": 0, "y": 0, "width": 100, "content": "검사 성적서" }, - { "type": "table", "x": 0, "y": 50, "columns": [...], "rows": [...] }, - { "type": "image", "x": 200, "y": 100, "src": "..." } - ] -} -``` - -**블록 빌더 UI (3패널):** - -``` -┌──────────┬────────────────────┬──────────┐ -│ 블록 │ │ 속성 │ -│ 팔레트 │ A4 캔버스 │ 패널 │ -│ │ │ │ -│ [텍스트] │ ┌──────────────┐ │ 너비: _ │ -│ [이미지] │ │ 드래그앤드롭 │ │ 높이: _ │ -│ [표] │ │ 블록 배치 │ │ 색상: _ │ -│ [선] │ │ │ │ 폰트: _ │ -│ [도형] │ └──────────────┘ │ │ -└──────────┴────────────────────┴──────────┘ -``` - ---- - -## 6. EAV 데이터 저장 패턴 - -### 6.1 핵심 개념 - -하나의 `document_data` 테이블에 **모든 양식의 모든 필드값**을 저장. 양식이 다르면 field_key가 다르고, 같은 양식이라도 섹션/행이 다르면 section_id/row_index로 구분. - -### 6.2 저장 구조 - -``` -document_data 레코드 예시: - -기본필드 (상단 고정 영역): -┌─────────────┬────────────┬───────────┬───────────┬───────────┬─────────────┐ -│ document_id │ section_id │ column_id │ row_index │ field_key │ field_value │ -├─────────────┼────────────┼───────────┼───────────┼───────────┼─────────────┤ -│ 42 │ NULL │ NULL │ 0 │ bf_1 │ 블라인드A │ ← 품명 -│ 42 │ NULL │ NULL │ 0 │ bf_2 │ LOT-2026-001│ ← LOT NO -│ 42 │ NULL │ NULL │ 0 │ bf_3 │ 2026-03-15 │ ← 납기일 -├─────────────┼────────────┼───────────┼───────────┼───────────┼─────────────┤ - -테이블 데이터 (섹션별 검사 결과): -│ 42 │ 10 │ 20 │ 0 │ col_20 │ 합격 │ ← 섹션10, 컬럼20, 1행 -│ 42 │ 10 │ 20 │ 1 │ col_20 │ 부적합 │ ← 섹션10, 컬럼20, 2행 -│ 42 │ 10 │ 21 │ 0 │ col_21 │ 100.5 │ ← 섹션10, 컬럼21, 1행 -└─────────────┴────────────┴───────────┴───────────┴───────────┴─────────────┘ -``` - -### 6.3 field_key 네이밍 규칙 - -| 접두사 | 의미 | 예시 | -|--------|------|------| -| `bf_` | 기본필드 (BasicField) | `bf_1`, `bf_2` | -| `cf_` | 섹션필드 (SectionField) | `cf_5`, `cf_6` | -| `col_` | 컬럼 데이터 | `col_20`, `col_21` | - -### 6.4 데이터 조회 패턴 - -```php -// 기본필드 값 조회 -$data = DocumentData::where('document_id', $id) - ->whereNull('section_id') - ->get() - ->keyBy('field_key'); - -$productName = $data['bf_1']->field_value; - -// 섹션별 테이블 데이터 조회 -$rows = DocumentData::where('document_id', $id) - ->where('section_id', $sectionId) - ->get() - ->groupBy('row_index'); -``` - ---- - -## 7. 결재 워크플로우 - -### 7.1 상태 전이 - -``` -DRAFT (작성중) - │ - ├── submit() → PENDING (결재중) - │ │ - │ ├── approve() [step 1] → 다음 step 대기 - │ ├── approve() [step 2] → 다음 step 대기 - │ ├── approve() [마지막] → APPROVED (승인) - │ │ - │ └── reject() → REJECTED (반려) - │ │ - │ └── edit → submit() → PENDING (재요청) - │ - └── cancel() → CANCELLED (취소) -``` - -### 7.2 상태값 및 라벨 - -| 코드 | 라벨 | 색상 | 편집 가능 | -|------|------|------|----------| -| `DRAFT` | 작성중 | gray | 예 | -| `PENDING` | 결재중 | yellow | 아니오 | -| `APPROVED` | 승인 | green | 아니오 | -| `REJECTED` | 반려 | red | 예 (수정 후 재요청) | -| `CANCELLED` | 취소 | gray | 아니오 | - -### 7.3 결재 단계 (Approval) - -``` -DocumentTemplateApprovalLine (양식 정의) - ↓ (문서 생성 시 복사) -DocumentApproval (문서별 결재 레코드) - -step 1: 작성 → PENDING → 결재자 승인 → APPROVED -step 2: 검토 → PENDING → 결재자 승인 → APPROVED -step 3: 승인 → PENDING → 결재자 승인 → APPROVED → 문서 전체 APPROVED -``` - -### 7.4 결재 판단 메서드 - -```php -// Document 모델 -canEdit() // DRAFT 또는 REJECTED -canSubmit() // DRAFT 또는 REJECTED -canApprove() // PENDING (현재 결재자만) -canCancel() // DRAFT 또는 PENDING (작성자만) -``` - ---- - -## 8. 자동 데이터 매핑 - -### 8.1 개요 - -문서 작성/수정 시, 연결된 작업지시서(work_order)/수주(order) 데이터에서 기본필드를 **자동으로 채움**. 사용자 입력 부담을 줄이고 데이터 정확성을 보장. - -### 8.2 검사 성적서 매핑 (field_key 기반) - -| field_key | 라벨 | 소스 | -|-----------|------|------| -| `product_name` | 품명 | `workOrderItem.item_name` | -| `specification` | 규격 | `workOrderItem.specification` | -| `lot_no` | LOT NO | `order.order_no` | -| `lot_size` | LOT 크기 | `"N 개소"` (개소 수 기반) | -| `client` | 발주처 | `order.client_name` | -| `site_name` | 현장명 | `workOrder.project_name` | -| `inspection_date` | 검사일 | `workOrderItem.options.inspection_data.inspected_at` | -| `inspector` | 검사자 | 검사자 이름 | - -### 8.3 작업일지 매핑 (label 기반) - -| label 포함 문자열 | 소스 | -|------------------|------| -| `발주처` | `order.client_name` | -| `현장명` | `workOrder.project_name` | -| `작업일자` | `now()` | -| `LOT NO`, `LOT` | `order.order_no` | -| `납기일`, `납기` | `order.delivery_date` | -| `작업지시번호` | `workOrder.work_order_no` | -| `수주일` | `order.received_at` 또는 `order.created_at` | - -### 8.4 자동 매핑 흐름 - -``` -문서 작성/수정 페이지 로드 - ↓ -DocumentController::edit() - ↓ -resolveAndBackfillBasicFields($template, $document) - ↓ -linkable_type 확인 (work_order? order?) - ↓ -field_key 또는 label 매칭 - ↓ -DB에 값이 없으면 → 소스 데이터에서 resolve - ↓ -뷰에 자동 채움된 값 전달 -``` - ---- - -## 9. 자재 LOT 추적 - -### 9.1 개요 - -검사 성적서에서 해당 작업지시의 **투입 자재 LOT 이력**을 조회. `stock_transactions` 테이블의 OUT(투입)/IN(취소) 트랜잭션을 상쇄하여 순수 투입량을 계산. - -### 9.2 추적 구조 - -``` -work_orders (작업지시) - │ - ├── stock_transactions (재고 트랜잭션) - │ ├── OUT (투입): qty < 0 - │ └── IN (취소/반납): qty > 0 - │ → 순수 투입량 = ABS(SUM(qty)) where qty < 0 - │ - └── work_order_material_inputs (개소별 투입자재) - └── stock_lots (LOT 정보) JOIN -``` - -### 9.3 표시 내용 - -| 항목 | 설명 | -|------|------| -| 자재명 | 투입된 원자재/부자재 이름 | -| LOT 번호 | 자재의 LOT 식별 번호 | -| 투입 수량 | OUT 트랜잭션 합계 (절대값) | -| 투입일 | 트랜잭션 일시 | - ---- - -## 10. 화면별 상세 - -### 10.1 문서 목록 (/documents) - -**필터 항목:** - -| 필터 | 타입 | 설명 | -|------|------|------| -| 검색 | text | 문서번호 또는 제목 | -| 상태 | dropdown | DRAFT, PENDING, APPROVED, REJECTED, CANCELLED, 휴지통(admin) | -| 양식분류 | dropdown | category | -| 템플릿 | dropdown | template_id | -| 날짜 범위 | date | created_at (from ~ to) | - -**목록 테이블 컬럼:** - -``` -문서번호 | 제목 | 양식 | 상태 | 작성자 | 작성일 | 결재현황 -``` - -### 10.2 문서 작성/수정 (/documents/create, /documents/{id}/edit) - -**폼 구성:** - -``` -┌──────────────────────────────────────────────┐ -│ 템플릿 선택 (읽기전용) │ -│ 제목 (필수) │ -├──────────────────────────────────────────────┤ -│ 기본 필드 (template.basicFields) │ -│ ┌─────────────────┬─────────────────┐ │ -│ │ 품명: [자동채움] │ LOT NO: [자동] │ │ -│ │ 납기일: [날짜] │ 발주처: [자동] │ │ -│ └─────────────────┴─────────────────┘ │ -├──────────────────────────────────────────────┤ -│ 섹션 1: 겉모양 검사 │ -│ ┌──────────────────────────────────────┐ │ -│ │ 도해 이미지 (있으면) │ │ -│ ├──────┬──────┬──────┬──────┬──────┤ │ -│ │ 구분 │ 항목 │ 기준 │ 결과1│ 결과2│ │ -│ ├──────┼──────┼──────┼──────┼──────┤ │ -│ │ 치수 │ 길이 │±5mm │ [ ] │ [ ] │ │ -│ │ 외관 │ 흠집 │ 없음 │ [✓] │ [✓] │ │ -│ ├──────┴──────┴──────┴──────┴──────┤ │ -│ │ [+ 행 추가] [행 삭제] │ │ -│ └──────────────────────────────────────┘ │ -├──────────────────────────────────────────────┤ -│ 외부 연결 (template.links) │ -│ 품목 선택: [검색 드롭다운] │ -├──────────────────────────────────────────────┤ -│ 첨부파일 │ -│ [일반 문서] [서명 이미지] [검사 사진] [참고 자료] │ -├──────────────────────────────────────────────┤ -│ [임시저장] [결재 요청] │ -└──────────────────────────────────────────────┘ -``` - -### 10.3 문서 상세 (/documents/{id}) - -**읽기 전용 표시:** - -``` -┌──────────────────────────────────────────────┐ -│ 문서번호: DOC-260306-001 상태: [🟢 승인] │ -│ 제목: 블라인드A 검사 성적서 │ -├──────────────────────────────────────────────┤ -│ 기본 필드 (읽기 전용) │ -├──────────────────────────────────────────────┤ -│ 검사 데이터 테이블 (읽기 전용) │ -├──────────────────────────────────────────────┤ -│ 결재 현황 │ -│ ┌────────┬────────┬────────┐ │ -│ │ 작성 │ 검토 │ 승인 │ │ -│ │ 홍길동 │ 김과장 │ 박부장 │ │ -│ │ ✓승인 │ ✓승인 │ ●대기 │ │ -│ └────────┴────────┴────────┘ │ -├──────────────────────────────────────────────┤ -│ 자재 투입 LOT (작업지시 연결 시) │ -│ ┌────────┬──────────┬──────┬──────┐ │ -│ │ 자재명 │ LOT 번호 │ 수량 │ 투입일│ │ -│ └────────┴──────────┴──────┴──────┘ │ -├──────────────────────────────────────────────┤ -│ 첨부파일 목록 │ -├──────────────────────────────────────────────┤ -│ [수정] [인쇄] [결재 승인] [결재 반려] │ -└──────────────────────────────────────────────┘ -``` - -### 10.4 인쇄 (/documents/{id}/print) - -성적서 형식의 인쇄 전용 화면. `window.print()` 호출. 작업지시 관련 자재(work_order_items) 데이터 포함. - -### 10.5 양식 목록 (/document-templates) - -**필터:** -- 검색: 양식명, 제목, 분류 -- 카테고리: common_codes 기반 + 기존 데이터 폴백 -- 활성 상태: 활성 / 비활성 / 휴지통(admin) - -**HTMX**: 필터 변경 시 테이블 영역만 부분 로드 - ---- - -## 11. 첨부파일 유형 - -| 유형 | 코드 | 용도 | 예시 | -|------|------|------|------| -| 일반 문서 | `general` | PDF, 엑셀 등 | 규격서, 보고서 | -| 서명 이미지 | `signature` | 검사 완료 서명 | 검사자 서명 사진 | -| 검사 사진 | `image` | 검사 증빙 사진 | 불량 부위 촬영 | -| 참고 자료 | `reference` | 참고용 문서 | KS 규격, 작업 지침 | - ---- - -## 12. API 연동 (MNG → API) - -MNG 뷰에서 데이터 저장/삭제는 **API 서버를 호출**하여 처리. GET 요청(뷰 렌더링)은 MNG 컨트롤러가 직접 처리. - -| 작업 | MNG (GET 요청) | API (POST/PUT/DELETE) | -|------|---------------|----------------------| -| 목록 조회 | `DocumentController::index()` | `GET /v1/documents` | -| 상세 조회 | `DocumentController::show()` | `GET /v1/documents/{id}` | -| 생성 | 폼 표시만 | `POST /v1/documents` | -| 수정 | 폼 표시만 | `PATCH /v1/documents/{id}` | -| 삭제 | - | `DELETE /v1/documents/{id}` | -| 결재 요청 | - | `POST /v1/documents/{id}/submit` | -| 승인 | - | `POST /v1/documents/{id}/approve` | -| 반려 | - | `POST /v1/documents/{id}/reject` | - ---- - -## 13. 카테고리 해결 로직 - -양식 카테고리는 **common_codes 테이블**에서 조회하되, 없으면 **기존 데이터에서 추출**하여 폴백. - -```php -// DocumentTemplateController::getCategories() -$categories = CommonCode::where('group', 'document_category') - ->orderBy('sort_order') - ->get(); - -if ($categories->isEmpty()) { - // 폴백: 기존 템플릿의 category 값에서 중복 제거 - $categories = DocumentTemplate::distinct('category') - ->pluck('category') - ->filter(); -} -``` - ---- - -## 14. 검사항목 확장 (field_values JSON) - -`document_template_section_items.field_values` JSON 컬럼으로 마이그레이션 없이 새 필드를 추가할 수 있다. - -```json -{ - "custom_field_1": "추가 기준값", - "min_value": 95.0, - "max_value": 105.0, - "unit": "mm" -} -``` - -> options JSON 컬럼 정책(`docs/standards/options-column-policy.md`) 준용 - ---- - -## 15. HTMX 전체 페이지 로드 규칙 - -문서관리 페이지들은 JavaScript를 사용하므로 HTMX 부분 로드 시 스크립트 미실행 문제가 있다. 컨트롤러에서 HX-Request 감지 시 **HX-Redirect로 전체 페이지 리로드 강제**. - -```php -if ($request->header('HX-Request')) { - return response('', 200)->header('HX-Redirect', route('documents.index')); -} -``` - ---- - -## 관련 문서 - -- [README.md](README.md) — API 엔드포인트, 모델 요약, FormRequest -- [DB 스키마 — 문서/전자서명](../../system/database/documents.md) — 테이블 상세 -- [게시판 시스템](../boards/README.md) — 유사한 EAV 패턴 참고 -- [결재관리 시스템](../approvals/README.md) — 별도 결재 시스템 (문서관리와 독립) - ---- - -**최종 업데이트**: 2026-03-06 diff --git a/sam/docs/features/documents/mng-document-template.md b/sam/docs/features/documents/mng-document-template.md deleted file mode 100644 index 5570865..0000000 --- a/sam/docs/features/documents/mng-document-template.md +++ /dev/null @@ -1,826 +0,0 @@ -# MNG 문서양식관리 (Document Template Management) - -> **작성일**: 2026-03-06 -> **상태**: 운영 중 -> **라우트**: `/document-templates` -> **관련**: [README.md](README.md) | [MNG 문서관리](mng-document-system.md) - ---- - -## 1. 개요 - -문서관리 시스템에서 사용하는 **서식(Template)**을 생성, 편집, 복제, 관리하는 기능. 검사 성적서, 작업지시서 등 다양한 문서 양식을 정의하며, 2가지 빌더 타입을 지원한다. - -| 빌더 | builder_type | UI 명칭 | 설명 | -|------|-------------|---------|------| -| **Legacy Builder** | `legacy` 또는 null | 새 양식 | 탭 기반 폼 UI (순수 JavaScript) | -| **Block Builder** | `block` | 양식 디자이너 | WYSIWYG 캔버스 편집기 (Alpine.js + SortableJS) | - -> **명칭 변경 이력**: Block Builder의 UI 표시 명칭이 '블록 빌더' → '양식 디자이너'로 변경됨 (2026-02-28) - -**핵심 기능:** -- 결재선, 기본필드, 검사 기준서, 테이블 컬럼 정의 -- EAV 데이터 구조의 서식 스키마 관리 -- 양식 복제 (연결품목 제외) -- 프리셋 자동 제안 (카테고리별) -- 소프트 삭제 + 휴지통 관리 (슈퍼어드민) - ---- - -## 2. 라우트 - -### 2.1 웹 라우트 (페이지) - -``` -GET /document-templates → index (목록) -GET /document-templates/create → create (Legacy 신규 생성) -GET /document-templates/block-create → blockCreate (양식 디자이너 신규 생성) -GET /document-templates/{id}/edit → edit (Legacy 편집) -GET /document-templates/{id}/block-edit → blockEdit (양식 디자이너 편집) -``` - -### 2.2 API 라우트 (CRUD + 기능) - -``` -Prefix: /api/admin/document-templates (HQ 관리자 전용) - -GET / → index (HTMX 테이블) -POST / → store (생성) -GET /{id} → show (상세 조회) -PUT /{id} → update (수정) -DELETE /{id} → destroy (소프트 삭제) -DELETE /{id}/force → forceDestroy (영구삭제, 슈퍼어드민) -POST /{id}/restore → restore (복원, 슈퍼어드민) -POST /{id}/toggle-active → toggleActive (활성 토글) -POST /{id}/duplicate → duplicate (복제) -POST /upload-image → uploadImage (이미지 업로드) -GET /admin/common-codes/{group} → getCommonCodes (공통코드 조회) -``` - ---- - -## 3. 모델 구조 - -### 3.1 모델 관계도 - -``` -DocumentTemplate (서식 마스터) -├── 1:N DocumentTemplateApprovalLine (결재선) -├── 1:N DocumentTemplateBasicField (기본필드) -├── 1:N DocumentTemplateSection (섹션/기준서) -│ └── 1:N DocumentTemplateSectionItem (섹션 항목) -├── 1:N DocumentTemplateSectionField (섹션 필드) -├── 1:N DocumentTemplateColumn (테이블 컬럼) -└── 1:N DocumentTemplateLink (연결 설정) - └── 1:N DocumentTemplateLinkValue (연결 값) -``` - -### 3.2 DocumentTemplate 핵심 필드 - -```php -// 기본 정보 -builder_type // 'legacy' | 'block' -name // 양식명 -category // 분류명 -title // 문서 제목 - -// 회사 정보 -company_name // 회사명 -company_address // 회사 주소 -company_contact // 회사 연락처 - -// 하단 설정 -footer_remark_label // 비고 라벨 -footer_judgement_label // 판정 라벨 -footer_judgement_options // array - 판정 선택지 - -// Block Builder 전용 -schema // array - 블록 스키마 (JSON) -page_config // array - 페이지 설정 (A4/A3, 여백 등) - -// 연결 (레거시) -linked_item_ids // array - 연결 품목 ID 목록 -linked_process_id // int - 연결 공정 ID - -// 상태 -is_active // boolean - 활성 여부 -deleted_at // timestamp - 소프트 삭제 -deleted_by // int - 삭제자 -``` - -**Helper 메서드:** - -```php -isBlockBuilder(): bool // builder_type === 'block' -isLegacyBuilder(): bool // builder_type !== 'block' -``` - -### 3.3 DocumentTemplateApprovalLine (결재선) - -| 필드 | 타입 | 설명 | -|------|------|------| -| `template_id` | FK | 서식 ID | -| `name` | string | 결재자 이름/직책 | -| `department` | string | 부서 | -| `role` | string | 역할 (작성/검토/승인) | -| `sort_order` | int | 순서 | - -### 3.4 DocumentTemplateBasicField (기본필드) - -| 필드 | 타입 | 설명 | -|------|------|------| -| `template_id` | FK | 서식 ID | -| `field_key` | string | 필드 키 (bf_ 접두사) | -| `label` | string | 라벨 | -| `field_type` | string | text, date, select 등 | -| `default_value` | string | 기본값 | -| `is_required` | boolean | 필수 여부 | -| `sort_order` | int | 순서 | -| `options` | array | 선택지 (select 타입) | - -### 3.5 DocumentTemplateSection (섹션/검사 기준서) - -| 필드 | 타입 | 설명 | -|------|------|------| -| `template_id` | FK | 서식 ID | -| `title` | string | 섹션 제목 | -| `image_path` | string | 섹션 이미지 경로 | -| `sort_order` | int | 순서 | - -**하위 관계:** - -``` -Section 1:N SectionItem - ├── category // 카테고리 (그룹핑) - ├── name // 항목명 - ├── standard // 기준 - ├── tolerance_type // 공차 유형 (symmetric/asymmetric/range/limit) - ├── tolerance_plus // +공차 - ├── tolerance_minus // -공차 - ├── reference_value // 기준값 - ├── method // 검사방법 - ├── measurement_type // 측정유형 - └── frequency // 검사주기 -``` - -### 3.6 DocumentTemplateColumn (테이블 컬럼) - -| 필드 | 타입 | 설명 | -|------|------|------| -| `template_id` | FK | 서식 ID | -| `label` | string | 컬럼 라벨 | -| `group_name` | string | 그룹명 (다단계 "/" 구분) | -| `width` | int | 컬럼 너비 | -| `column_type` | string | text, check, complex, select, measurement | -| `sub_labels` | array | complex 타입 하위 라벨 | -| `sort_order` | int | 순서 | - -### 3.7 DocumentTemplateLink (연결 설정) - -| 필드 | 타입 | 설명 | -|------|------|------| -| `template_id` | FK | 서식 ID | -| `link_key` | string | 연결 키 | -| `label` | string | 라벨 | -| `link_type` | string | `single` / `multiple` | -| `source_table` | string | `items` / `processes` / `users` | -| `search_params` | array | 검색 파라미터 | -| `display_fields` | array | 표시 필드 | -| `is_required` | boolean | 필수 여부 | -| `sort_order` | int | 순서 | - -**하위 관계:** - -``` -Link 1:N LinkValue - ├── link_id // FK → Link - ├── linkable_id // 연결 엔티티 ID - └── (source_table에 따라 items/processes/users 참조) -``` - -**레거시 호환 처리:** - -```php -// 신규 links가 있으면 사용 -if ($template->links->isNotEmpty()) { - // template_links + link_values 사용 -} - -// 레거시만 있으면 가상 엔트리 생성 -if (!empty($template->linked_item_ids)) { - return [['link_key' => 'items', 'values' => [...]]] -} -``` - ---- - -## 4. 컨트롤러 상세 - -### 4.1 DocumentTemplateController (웹) - -| 메서드 | 동작 | -|--------|------| -| `index()` | HTMX 요청 → HX-Redirect 반환 (전체 페이지 로드 강제) | -| `create()` | Legacy 신규 생성 폼 렌더링 | -| `edit($id)` | Legacy 편집. 양식 디자이너 타입이면 `blockEdit`으로 자동 리다이렉트 | -| `blockCreate()` | 양식 디자이너 신규 생성 (빈 캔버스) | -| `blockEdit($id)` | 양식 디자이너 편집 (스키마 로드) | - -**공통 데이터 준비:** - -```php -// 현재 테넌트 조회 -$tenantId = getCurrentTenant(); // 세션의 selected_tenant_id - -// 카테고리 목록 = common_codes + 기존 템플릿 카테고리 -$categories = getCategories(); - -// 기본필드 키 옵션 -$basicFieldKeys = getBasicFieldKeys(); // common_codes 'doc_template_basic_field' -``` - -### 4.2 DocumentTemplateApiController (API) - -#### `index()` — HTMX 테이블 조회 - -| 파라미터 | 타입 | 설명 | -|---------|------|------| -| `search` | string | 양식명/분류 검색 | -| `category` | string | 분류 필터 | -| `is_active` | string | `1` / `0` / `TRASHED` (휴지통) | - -```php -// 휴지통 모드 (슈퍼어드민 전용) -if ($isActive === 'TRASHED') { - $query->onlyTrashed(); -} -``` - -#### `store()` / `update()` — 생성/수정 - -``` -요청 데이터 - ↓ -검증 (직접 validate, FormRequest 미사용) - ↓ -연결품목 중복 검증 (checkLinkedItemDuplicates) - ↓ -DB::transaction 시작 - ↓ -Template 생성/수정 - ↓ -saveRelations() — 관계 데이터 upsert - ↓ -DB::transaction 완료 - ↓ -JSON 응답 -``` - -#### `duplicate()` — 양식 복제 - -```php -$source = DocumentTemplate::with([...all relationships...]); - -$newTemplate = DocumentTemplate::create([ - ...원본 데이터, - 'name' => request('name', '원본 (복사)'), - 'is_active' => false, // 비활성으로 생성 - 'linked_item_ids' => null, // 연결품목 제외 - 'linked_process_id' => null, // 연결공정 제외 -]); - -// 각 관계 데이터 복사 (approvalLines, basicFields, sections, columns...) -// linkValues는 복사 안 함 (동일 분류 내 중복 방지) -``` - -#### `forceDestroy()` — 영구삭제 - -```php -// 사전 검사: 참조하는 문서 존재 여부 -$documentCount = Document::withTrashed() - ->where('template_id', $id) - ->count(); - -if ($documentCount > 0) { - return 422; // "이 양식을 사용한 문서 {count}건이 있어 삭제 불가" -} -``` - -#### `uploadImage()` — 이미지 업로드 - -``` -요청 (multipart) - ↓ -ApiTokenService::exchangeToken($userId, $tenantId) - ↓ -API /files/upload 호출 (Bearer 토큰) - ↓ -응답: file_path (1/temp/2026/02/xxx.jpg) - ↓ -최종 URL: http://api.sam.kr/storage/tenants/{file_path} -``` - ---- - -## 5. 저장 메커니즘 (saveRelations) - -### 5.1 upsert 전략 - -| 관계 | 방식 | 이유 | -|------|------|------| -| approvalLines | 전체 삭제 → 재생성 | ID 참조 없음 | -| basicFields | 전체 삭제 → 재생성 | ID 참조 없음 | -| **sections** | **ID 보존 upsert** | document_data가 section_id 참조 | -| **sectionItems** | **ID 보존 upsert** | section 하위 항목 | -| **columns** | **ID 보존 upsert** | document_data가 column_id 참조 | -| sectionFields | 전체 삭제 → 재생성 | ID 참조 없음 | -| links + linkValues | 전체 삭제 → 재생성 | ID 참조 없음 | - -### 5.2 ID 보존 upsert 로직 - -```php -// 1. 요청 ID 수집 -$incomingIds = collect($data['sections'])->pluck('id')->filter(); - -// 2. 요청에 없는 항목 삭제 -$template->sections() - ->whereNotIn('id', $incomingIds) - ->each(function($s) { - $s->items()->delete(); - $s->delete(); - }); - -// 3. 각 항목 upsert -foreach ($data['sections'] as $section) { - if (!empty($section['id']) && $existing = $template->sections()->find($section['id'])) { - $existing->update($sectionData); // 기존: update - } else { - DocumentTemplateSection::create([...]); // 신규: create - } -} -``` - -> **ID 보존이 필수인 이유**: `document_data` 테이블이 `section_id`, `column_id`를 FK로 참조한다. 양식 수정 시 ID가 변경되면 기존 문서 데이터와의 매핑이 깨진다. - ---- - -## 6. 화면 구성 - -### 6.1 목록 화면 (`index.blade.php`) - -``` -┌─────────────────────────────────────────────────┐ -│ 문서양식관리 │ -│ [+ 새 양식] [+ 양식 디자이너] │ -├─────────────────────────────────────────────────┤ -│ 필터: [검색어] [분류 ▼] [활성/비활성/휴지통 ▼] │ -├─────────────────────────────────────────────────┤ -│ # │ 양식명 │ 분류 │ 활성 │ 수정일 │ 액션 │ -│ 1 │ FQC... │ 검사 │ ✅ │ 03-06 │ 편집 복제 삭제 │ -│ 2 │ 수입... │ 검사 │ ✅ │ 03-05 │ 편집 복제 삭제 │ -│ ...│ │ │ │ │ │ -└─────────────────────────────────────────────────┘ -``` - -**HTMX 테이블 로드:** - -```html -
-
-``` - -**액션 버튼:** -- **편집**: 새 양식 → `/document-templates/{id}/edit`, 양식 디자이너 → `/document-templates/{id}/block-edit` -- **복제**: `duplicateTemplate(id)` — 이름 입력 모달 후 POST -- **삭제**: `confirmDelete(id)` — 확인 후 DELETE -- **미리보기**: `previewTemplate(id)` — 모달 표시 -- **활성 토글**: `toggleActive(id)` — POST toggle-active -- **복원/영구삭제**: 휴지통 모드에서만 표시 (슈퍼어드민) - -### 6.2 Legacy Builder 편집 화면 (`edit.blade.php`) - -**4개 탭 구조:** - -``` -┌─────────────────────────────────────────────────────┐ -│ [기본정보] [기본필드] [검사 기준서] [테이블 컬럼] │ -├─────────────────────────────────────────────────────┤ -│ │ -│ (각 탭 콘텐츠) │ -│ │ -├─────────────────────────────────────────────────────┤ -│ [미리보기] [저장] [취소] │ -└─────────────────────────────────────────────────────┘ -``` - -#### 탭 1: 기본정보 - -| 필드 | 설명 | -|------|------| -| 양식명 | 서식 이름 (필수) | -| 제목 | 문서 제목 | -| 분류 | 카테고리 (common_codes + 기존값) | -| 회사명 | 문서 헤더 회사명 | -| 회사 주소/연락처 | 문서 헤더 | -| 활성 | 체크박스 | -| 결재선 | 동적 행 추가/삭제 (이름, 부서, 역할) | - -#### 탭 2: 기본필드 - -| 항목 | 설명 | -|------|------| -| 필드 키 | `bf_` 접두사 (common_codes에서 선택) | -| 라벨 | 표시 라벨 | -| 필드 타입 | text, date, select 등 | -| 기본값 | 문서 생성 시 자동 입력 | -| 필수 여부 | 체크박스 | - -#### 탭 3: 검사 기준서 - -``` -┌──────────────────────────────────────────────────┐ -│ 섹션 1: [제목 입력] [이미지 업로드] [+ 항목 추가] │ -│ ┌──────────────────────────────────────────────┐ │ -│ │ 카테고리 │ 항목 │ 기준 │ 공차 │ 기준값 │ ... │ │ -│ │ 외관 │ 색상 │ 기준 │ ±0.5 │ 5.0 │ ... │ │ -│ │ 외관 │ 흠집 │ 무 │ │ │ ... │ │ -│ └──────────────────────────────────────────────┘ │ -│ │ -│ 섹션 2: [제목 입력] [이미지 업로드] [+ 항목 추가] │ -│ ... │ -│ [+ 섹션 추가] │ -└──────────────────────────────────────────────────┘ -``` - -**공차 유형:** - -| 유형 | 입력 | 표시 예 | -|------|------|--------| -| `symmetric` | ± 값 | ±0.5 | -| `asymmetric` | +값, -값 | +0.3 / -0.2 | -| `range` | 최소~최대 | 4.5 ~ 5.5 | -| `limit` | 상한 또는 하한 | ≤ 10 | - -#### 탭 4: 테이블 컬럼 - -| 항목 | 설명 | -|------|------| -| 라벨 | 컬럼 헤더 | -| 그룹명 | 다단계 그룹 ("/" 구분) | -| 너비 | 컬럼 너비 (px 또는 %) | -| 컬럼 타입 | text, check, complex, select, measurement | -| 하위 라벨 | complex 타입 시 sub_labels | - -**자동 컬럼 생성:** - -``` -[기준서에서 자동 생성] 버튼 클릭 - ↓ -검사 기준서 섹션의 항목들을 분석 - ↓ -카테고리 그룹별 컬럼 자동 생성 - ↓ -measurement_type에 따라 컬럼 타입 결정 -``` - -### 6.3 양식 디자이너 편집 화면 (`block-editor.blade.php`) - -**3패널 레이아웃:** - -``` -┌──────────┬──────────────────────────┬───────────┐ -│ 팔레트 │ 캔버스 │ 속성 패널 │ -│ (220px) │ (flex: 1) │ (300px) │ -│ │ │ │ -│ 기본: │ ┌──────────────────────┐ │ 선택 블록: │ -│ □ 제목 │ │ [제목 블록] │ │ │ -│ □ 문단 │ │ [문단 블록] │ │ 제목: ... │ -│ □ 테이블 │ │ [테이블 블록] │ │ 크기: ... │ -│ □ 컬럼 │ │ [입력 필드 블록] │ │ 정렬: ... │ -│ □ 구분선 │ │ │ │ │ -│ □ 여백 │ └──────────────────────┘ │ │ -│ │ │ │ -│ 폼: │ │ │ -│ □ 텍스트 │ │ │ -│ □ 숫자 │ │ │ -│ □ 날짜 │ │ │ -│ □ 선택 │ │ │ -│ □ 체크 │ │ │ -│ □ 텍스트영역│ │ │ -│ □ 서명 │ │ │ -└──────────┴──────────────────────────┴───────────┘ -``` - -**블록 타입 (15개):** - -| 분류 | 타입 | 설명 | -|------|------|------| -| 기본 | `heading` | 제목 (h1~h6) | -| 기본 | `paragraph` | 문단 텍스트 | -| 기본 | `table` | 테이블 (행/열 편집) | -| 기본 | `columns` | 다단 컬럼 레이아웃 | -| 기본 | `divider` | 구분선 | -| 기본 | `spacer` | 여백 | -| 폼 | `text_field` | 텍스트 입력 | -| 폼 | `number_field` | 숫자 입력 | -| 폼 | `date_field` | 날짜 입력 | -| 폼 | `select_field` | 선택 드롭다운 | -| 폼 | `checkbox_field` | 체크박스 | -| 폼 | `textarea_field` | 긴 텍스트 입력 | -| 폼 | `signature_field` | 서명 영역 | - -**Alpine.js 상태 관리:** - -```javascript -blockEditor(initialSchema, templateId) { - blocks: [], // 블록 배열 - selectedBlockId: null, // 현재 선택 블록 - history: [], // Undo/Redo 스택 (최대 50) - historyIndex: -1, - pageConfig: { // 페이지 설정 - size: 'A4', // A4 / A3 - orientation: 'portrait', // portrait / landscape - margins: { top, right, bottom, left } - }, - templateName: '', - category: '' -} -``` - -**키보드 단축키:** - -| 단축키 | 기능 | -|--------|------| -| `Ctrl+Z` / `Cmd+Z` | Undo | -| `Ctrl+Shift+Z` / `Cmd+Shift+Z` | Redo | -| `Ctrl+S` / `Cmd+S` | 저장 | - -**SortableJS:** -- 캔버스 내 블록 드래그-앤-드롭 정렬 -- 팔레트에서 캔버스로 블록 추가 - ---- - -## 7. 미리보기 시스템 - -### 7.1 Legacy Builder 미리보기 - -```javascript -buildDocumentPreviewHtml(data) -├── 결재란 테이블 (역할별 칸) -├── 기본필드 (2열 15:35:15:35 비율) -├── 섹션별 이미지 (title + image 또는 placeholder) -├── 검사 데이터 테이블 -│ ├── 다단계 그룹 헤더 (group_name "/" 구분) -│ ├── sub_labels (complex 컬럼) -│ ├── 항목 행 (카테고리 그룹핑) -│ └── 측정치 셀 (measurement_type별 렌더) -└── 비고/종합판정 섹션 -``` - -### 7.2 양식 디자이너 미리보기 - -```javascript -buildBlockPreviewHtml(data) -├── 블록 타입별 HTML 렌더링 -├── 폼 필드 placeholder 표시 -└── A4/A3 레이아웃 시뮬레이션 -``` - -### 7.3 이미지 URL 처리 - -```javascript -_previewImageUrl(imagePath) -├── http(s):// 시작 → 그대로 사용 -├── /^\d+\// 패턴 → API tenant storage URL 생성 -│ → http://api.sam.kr/storage/tenants/{imagePath} -└── 기타 → MNG local storage (/storage/{imagePath}) -``` - ---- - -## 8. 분류(Category) 관리 - -### 8.1 소스 (우선순위) - -1. **common_codes** (code_group = `document_category`, is_active = true) - - tenant_id가 있는 것 우선 (테넌트 전용) - - tenant_id가 null인 것도 포함 (공통) - - code 기준 중복 제거 (테넌트 우선) -2. **기존 템플릿의 category** (common_codes에 없는 값) - - 기존 이름 그대로 추가 - -### 8.2 연동 공통코드 그룹 - -| 그룹 | 용도 | -|------|------| -| `document_category` | 문서 분류 | -| `doc_template_basic_field` | 기본필드 키 옵션 | -| `doc_inspection_method` | 검사방법 | -| `doc_measurement_type` | 측정유형 | - ---- - -## 9. 프리셋 시스템 - -### 9.1 테이블 - -``` -document_template_field_presets -├── name // 프리셋 이름 -├── category // 대상 카테고리 -├── description // 설명 -└── field_definitions // array - 필드 정의 목록 - [{ field_key, label, field_type, options, ... }] -``` - -### 9.2 동작 - -``` -분류(Category) 변경 - ↓ -매칭 프리셋 검색 - ↓ -기존 section_fields가 비어있으면 - ↓ -"'{category}' 카테고리에 맞는 프리셋을 적용할까요?" 확인 - ↓ -승인 시 field_definitions 자동 적용 -``` - -> **주의**: 초기 로드 시에는 제안하지 않음. 분류 변경 시에만 제안. - ---- - -## 10. 연결품목 중복 검증 - -### 10.1 규칙 - -같은 category 내 서로 다른 템플릿이 동일한 items를 연결할 수 없다. - -### 10.2 검증 로직 - -```php -checkLinkedItemDuplicates($templateId, $category, $itemIds) - -// 1. 같은 category의 다른 템플릿 조회 -$otherTemplates = DocumentTemplate::where('category', $category) - ->where('id', '!=', $templateId) - ->get(); - -// 2. 각 템플릿의 연결품목 수집 -foreach ($otherTemplates as $other) { - // 레거시: linked_item_ids (JSON 배열) - // 신규: template_links → linkValues (source_table = 'items') - $existingItemIds = ...; -} - -// 3. 교집합 검사 -$duplicates = array_intersect($itemIds, $existingItemIds); -if (!empty($duplicates)) { - return 422; // 중복 항목 목록과 함께 오류 반환 -} -``` - ---- - -## 11. JavaScript 상태 관리 (Legacy Builder) - -### 11.1 templateState 객체 - -```javascript -const templateState = { - // 기본정보 - id, name, category, title, - company_name, company_address, company_contact, - footer_remark_label, footer_judgement_label, - footer_judgement_options, - is_active, - - // 관계 데이터 - approval_lines: [], // 결재선 - basic_fields: [], // 기본필드 - sections: [], // 섹션 + items - columns: [], // 테이블 컬럼 - section_fields: [], // 섹션 필드 - template_links: [], // 연결 설정 + values -}; -``` - -### 11.2 저장 흐름 - -``` -사용자 입력 (Blade 폼) - ↓ -templateState 객체 갱신 - ↓ -saveTemplate() 호출 - ↓ -fetch POST/PUT /api/admin/document-templates - ↓ -DocumentTemplateApiController::store/update() - ↓ -검증 → 중복 검사 → DB 트랜잭션 → saveRelations() - ↓ -JSON 응답 - ↓ -showToast() 메시지 - ↓ -htmx.trigger('#template-table', 'filterSubmit') → 테이블 새로고침 -``` - ---- - -## 12. 양식 디자이너(Block Builder) vs 새 양식(Legacy Builder) 비교 - -| 항목 | 양식 디자이너 | 새 양식 | -|------|:------------:|:-------------:| -| builder_type | `block` | `legacy` 또는 null | -| 편집 UI | WYSIWYG 캔버스 (Alpine.js) | 탭 폼 (순수 JavaScript) | -| 데이터 저장 | `schema` JSON 컬럼 | 관계 테이블 (7개) | -| Undo/Redo | 히스토리 스택 (최대 50) | 불가 | -| 블록 타입 | 15개 (기본 6 + 폼 7 + 기타 2) | N/A | -| 드래그-앤-드롭 | SortableJS | 불가 | -| 페이지 설정 | A4/A3, 여백, 방향 | 없음 | -| 복제 | 스키마 JSON 복사 | 각 관계 데이터 개별 복사 | -| 미리보기 함수 | `buildBlockPreviewHtml()` | `buildDocumentPreviewHtml()` | -| 적합 용도 | 자유 레이아웃 문서 | 정형화된 검사 성적서 | - ---- - -## 13. 권한 및 보안 - -### 13.1 미들웨어 - -- **웹 라우트**: 일반 인증 (auth) -- **API 라우트**: HQ 관리자 미들웨어 (`admin` prefix) - -### 13.2 슈퍼어드민 전용 기능 - -| 기능 | 엔드포인트 | -|------|-----------| -| 영구삭제 | `DELETE /{id}/force` | -| 복원 | `POST /{id}/restore` | -| 휴지통 조회 | `GET /?is_active=TRASHED` | - -### 13.3 삭제 보호 - -- 소프트 삭제: `deleted_at` + `deleted_by` 기록 -- 영구삭제 전 참조 문서 검사 (Document 테이블) -- 참조 문서가 있으면 영구삭제 불가 (422 응답) - ---- - -## 14. API 프로젝트 연동 - -### 14.1 API 서비스 - -```php -// DocumentTemplateService (API) -list(array $params): LengthAwarePaginator - // 필터: is_active, category, search - -show(int $id): DocumentTemplate - // 전체 관계 로드 (approvalLines, basicFields, sections, columns...) -``` - -### 14.2 API 엔드포인트 - -``` -GET /v1/document-templates → index (목록) -GET /v1/document-templates/{id} → show (상세) -``` - -> API는 **읽기 전용**. 서식 생성/수정은 MNG에서만 수행. - ---- - -## 15. 주요 파일 경로 - -| 기능 | 경로 | -|------|------| -| 웹 컨트롤러 | `mng/app/Http/Controllers/DocumentTemplateController.php` | -| API 컨트롤러 | `mng/app/Http/Controllers/Api/Admin/DocumentTemplateApiController.php` | -| 모델 (8개) | `mng/app/Models/DocumentTemplate*.php` | -| 뷰 - 목록 | `mng/resources/views/document-templates/index.blade.php` | -| 뷰 - Legacy 편집 | `mng/resources/views/document-templates/edit.blade.php` | -| 뷰 - 양식 디자이너 | `mng/resources/views/document-templates/block-editor.blade.php` | -| 뷰 - 테이블 | `mng/resources/views/document-templates/partials/table.blade.php` | -| 뷰 - 미리보기 | `mng/resources/views/document-templates/partials/preview-modal.blade.php` | -| API 서비스 | `api/app/Services/DocumentTemplateService.php` | -| API 모델 | `api/app/Models/Documents/DocumentTemplate*.php` | - ---- - -## 관련 문서 - -- [README.md](README.md) — 문서관리 시스템 개요 (API 중심) -- [MNG 문서관리](mng-document-system.md) — 문서 생성/편집/결재 (서식을 사용하는 측) -- [DB 스키마 — 문서](../../system/database/documents.md) - ---- - -**최종 업데이트**: 2026-03-06 diff --git a/sam/docs/features/planning/README.md b/sam/docs/features/planning/README.md deleted file mode 100644 index ef681d0..0000000 --- a/sam/docs/features/planning/README.md +++ /dev/null @@ -1,129 +0,0 @@ -# 주일기업 기획 메뉴 - -> **작성일**: 2026-03-06 -> **상태**: 운영 중 -> **프로젝트**: SAM MNG (관리자 웹) -> **라우트 접두사**: `/juil` - ---- - -## 1. 개요 - -### 1.1 목적 - -블라인드/스크린 제조업체의 현장 관리를 위한 기획 도구 모음. 견적부터 공사, 준공까지의 업무 흐름과 현장 기록(사진대지), 회의 기록(STT/AI 요약)을 제공한다. - -### 1.2 문서 구조 - -| 문서 | 설명 | -|------|------| -| **README.md** (이 문서) | 전체 개요, 메뉴 구조, 아키텍처 | -| [construction-photos.md](construction-photos.md) | 공사현장 사진대지 기술 명세 | -| [meeting-minutes.md](meeting-minutes.md) | 회의록 작성 기술 명세 (STT/AI 통합) | -| [planning-views.md](planning-views.md) | 견적/프로젝트/워크플로우 화면 명세 | - -### 1.3 하위 메뉴 구조 - -``` -주일기업 기획 -├── 견적/입찰/공사관리 /juil/estimate -├── 프로젝트관리/기성청구 /juil/project -├── 업무 Workflow /juil/workflow -├── 공사현장 사진대지 /juil/construction-photos -└── 회의록 작성 /juil/meeting-minutes -``` - ---- - -## 2. 아키텍처 - -### 2.1 기술 스택 - -| 계층 | 기술 | 설명 | -|------|------|------| -| 뷰 | Blade + React (인라인) + Babel | 브라우저 트랜스파일 React 컴포넌트 | -| API | Laravel Controller + Service | JSON API (AJAX) | -| 모델 | Eloquent ORM | Multi-tenant (BelongsToTenant) | -| 파일 저장 | Google Cloud Storage | 사진, 오디오 파일 | -| AI | Gemini API (Vertex AI) | 요약, 화자 분리 | -| STT | Google Speech-to-Text V1/V2 + Web Speech API | 음성 인식 | - -### 2.2 프로젝트 파일 구조 - -``` -mng/ -├── app/Http/Controllers/ -│ ├── PlanningController.php ← 견적/프로젝트/워크플로우 -│ ├── ConstructionSitePhotoController.php ← 사진대지 CRUD + 파일 관리 -│ └── MeetingMinuteController.php ← 회의록 CRUD + AI 기능 -├── app/Services/ -│ ├── ConstructionSitePhotoService.php ← 사진대지 비즈니스 로직 -│ └── MeetingMinuteService.php ← 회의록 + AI 통합 로직 -├── app/Models/ -│ ├── ConstructionSitePhoto.php ← 사진대지 모델 -│ ├── ConstructionSitePhotoRow.php ← 사진 행 모델 -│ ├── MeetingMinute.php ← 회의록 모델 -│ └── MeetingMinuteSegment.php ← 회의 세그먼트 모델 -└── resources/views/juil/ - ├── estimate.blade.php ← 견적/입찰/공사관리 - ├── project.blade.php ← 프로젝트관리/기성청구 - ├── workflow.blade.php ← 업무 Workflow - ├── construction-photos.blade.php ← 사진대지 SPA - └── meeting-minutes.blade.php ← 회의록 SPA -``` - -### 2.3 기능별 구현 현황 - -| 기능 | 구현 방식 | 백엔드 | DB | -|------|----------|--------|-----| -| 견적/입찰/공사관리 | React 뷰 (목데이터) | PlanningController (뷰 반환만) | 없음 | -| 프로젝트관리/기성청구 | React 뷰 (목데이터) | PlanningController (뷰 반환만) | 없음 | -| 업무 Workflow | React 뷰 (정적 데이터) | PlanningController (뷰 반환만) | 없음 | -| 공사현장 사진대지 | React SPA + API | Controller + Service | 2 테이블 | -| 회의록 작성 | React SPA + API | Controller + Service + AI | 2 테이블 | - ---- - -## 3. 외부 서비스 의존성 - -| 서비스 | 용도 | 추적 | -|--------|------|------| -| **Google Cloud Storage** | 사진/오디오 파일 저장 | `AiTokenHelper::saveGcsStorageUsage()` | -| **Google Speech-to-Text V2 (Chirp2)** | 자동 화자 분리 (최우선) | `AiTokenHelper::saveSttUsage()` | -| **Google Speech-to-Text V1** | 화자 분리 (V2 실패 시 폴백) | `AiTokenHelper::saveSttUsage()` | -| **Gemini API (Vertex AI)** | 요약 생성 + 화자 재분배 | `AiTokenHelper::saveGeminiUsage()` | -| **Web Speech API** | 브라우저 음성 입력 (현장명/설명) | `logSttUsage()` | - -### 3.1 도메인 용어 힌트 (STT 정확도 향상) - -``` -블라인드, 스크린, 롤스크린, 허니콤, 버티컬, -원단, 바텀레일, 헤드레일, 브라켓, -주일, 경동, 주일블라인드, 경동블라인드, -수주, 발주, 납기, 출하, 재고, 원가, 단가, -SAM, ERP, MES -``` - ---- - -## 4. HTMX 전체 페이지 로드 규칙 - -모든 `/juil/*` 페이지는 React 인라인 컴포넌트를 사용하므로, HTMX 부분 로드 시 스크립트가 실행되지 않는다. 각 컨트롤러 메서드에서 HTMX 요청 감지 시 **HX-Redirect로 전체 페이지 리로드를 강제**한다. - -```php -if ($request->header('HX-Request')) { - return response('', 200)->header('HX-Redirect', route('juil.estimate')); -} -``` - ---- - -## 5. 관련 문서 - -- [공사현장 사진대지](construction-photos.md) — GCS 파일 관리, 행 구조, 음성 입력 -- [회의록 작성](meeting-minutes.md) — STT/화자분리/AI 요약, 오디오 녹음 -- [견적/프로젝트/워크플로우](planning-views.md) — React 뷰 구성, 업무 프로세스 정의 - ---- - -**최종 업데이트**: 2026-03-06 diff --git a/sam/docs/features/planning/construction-photos.md b/sam/docs/features/planning/construction-photos.md deleted file mode 100644 index 0a85ffb..0000000 --- a/sam/docs/features/planning/construction-photos.md +++ /dev/null @@ -1,275 +0,0 @@ -# 공사현장 사진대지 - -> **작성일**: 2026-03-06 -> **상태**: 운영 중 -> **라우트**: `/juil/construction-photos` -> **관련**: [README.md](README.md) | [회의록](meeting-minutes.md) | [뷰 화면](planning-views.md) - ---- - -## 1. 개요 - -건설/시공 현장의 작업 과정을 **작업전/작업중/작업후** 3단계 사진으로 기록하고 관리하는 기능. Google Cloud Storage에 사진을 저장하며, 음성 입력(Web Speech API)으로 현장명과 설명을 입력할 수 있다. - ---- - -## 2. 라우트 - -``` -/juil/construction-photos -├── GET / → index (목록 페이지) -├── GET /list → list (JSON 목록) -├── POST / → store (새 사진대지 등록) -├── POST /log-stt-usage → logSttUsage (STT 시간 기록) -├── GET /{id} → show (상세 조회) -├── PUT /{id} → update (메타데이터 수정) -├── DELETE /{id} → destroy (삭제) -├── POST /{id}/rows → addRow (행 추가) -├── DELETE /{id}/rows/{rowId} → deleteRow (행 삭제) -├── POST /{id}/rows/{rowId}/upload → uploadPhoto (사진 업로드) -├── DELETE /{id}/rows/{rowId}/photo/{type} → deletePhoto (사진 삭제) -└── GET /{id}/rows/{rowId}/download/{type} → downloadPhoto (다운로드) -``` - ---- - -## 3. 데이터베이스 - -### 3.1 construction_site_photos (사진대지) - -| 컬럼 | 타입 | 설명 | -|------|------|------| -| `id` | BIGINT PK | | -| `tenant_id` | BIGINT FK | 테넌트 격리 | -| `user_id` | BIGINT FK | 등록자 | -| `site_name` | VARCHAR(200) | 현장명 (필수) | -| `work_date` | DATE | 작업일자 (필수) | -| `description` | TEXT NULL | 설명 | -| `deleted_at` | TIMESTAMP NULL | 소프트 삭제 | - -**인덱스**: `tenant_id`, `user_id`, `(tenant_id, work_date)` - -### 3.2 construction_site_photo_rows (사진 행) - -각 사진대지는 1개 이상의 행을 가지며, 각 행에 3개 타입(before/during/after) 사진 저장. - -| 컬럼 | 타입 | 설명 | -|------|------|------| -| `id` | BIGINT PK | | -| `construction_site_photo_id` | BIGINT FK | 부모 (cascade delete) | -| `sort_order` | INT | 정렬 순서 (0부터) | -| `before_photo_path` | VARCHAR(500) NULL | 작업전 GCS 경로 | -| `before_photo_gcs_uri` | VARCHAR(500) NULL | 작업전 GCS URI | -| `before_photo_size` | INT UNSIGNED NULL | 작업전 파일크기 (bytes) | -| `during_photo_path` | VARCHAR(500) NULL | 작업중 GCS 경로 | -| `during_photo_gcs_uri` | VARCHAR(500) NULL | 작업중 GCS URI | -| `during_photo_size` | INT UNSIGNED NULL | 작업중 파일크기 (bytes) | -| `after_photo_path` | VARCHAR(500) NULL | 작업후 GCS 경로 | -| `after_photo_gcs_uri` | VARCHAR(500) NULL | 작업후 GCS URI | -| `after_photo_size` | INT UNSIGNED NULL | 작업후 파일크기 (bytes) | - -### 3.3 테이블 관계 - -``` -construction_site_photos - │ 1:N - ▼ -construction_site_photo_rows (sort_order ASC) - ├── before_photo_* (작업전) - ├── during_photo_* (작업중) - └── after_photo_* (작업후) -``` - ---- - -## 4. API 명세 - -### 4.1 목록 조회 - -``` -GET /juil/construction-photos/list -``` - -| 파라미터 | 타입 | 설명 | -|---------|------|------| -| `search` | string | 현장명 검색 | -| `date_from` | date | 시작일 | -| `date_to` | date | 종료일 | -| `per_page` | int | 페이지당 건수 | - -### 4.2 생성 - -``` -POST /juil/construction-photos -``` - -| 필드 | 규칙 | 설명 | -|------|------|------| -| `site_name` | required, max:200 | 현장명 | -| `work_date` | required, date | 작업일자 | -| `description` | nullable, max:2000 | 설명 | - -> 생성 시 빈 행 1개 자동 추가 - -### 4.3 사진 업로드 - -``` -POST /juil/construction-photos/{id}/rows/{rowId}/upload -``` - -| 필드 | 규칙 | 설명 | -|------|------|------| -| `type` | required, in:before,during,after | 사진 타입 | -| `photo` | required, image, mimes:jpeg,jpg,png,webp, max:10240 | 최대 10MB | - -### 4.4 사진 다운로드 - -``` -GET /juil/construction-photos/{id}/rows/{rowId}/download/{type}?inline=1 -``` - -| 파라미터 | 설명 | -|---------|------| -| `inline=1` | 브라우저 표시 (미지정 시 다운로드) | - ---- - -## 5. GCS 저장 구조 - -### 5.1 경로 패턴 - -``` -construction-site-photos/{tenant_id}/{photo_id}/{row_id}_{timestamp}_{type}.{ext} -``` - -**예시:** - -``` -construction-site-photos/1/42/15_1709723456_before.jpg -construction-site-photos/1/42/15_1709723456_during.jpg -construction-site-photos/1/42/15_1709723456_after.png -``` - -### 5.2 업로드 흐름 - -``` -클라이언트 (Canvas 이미지 압축: 1920px, quality 80%) - ↓ -FormData (multipart) 전송 - ↓ -컨트롤러: uploadPhoto() - ↓ -서비스: uploadPhoto() - ├── 기존 사진 있으면 GCS에서 삭제 - ├── GCS에 업로드 - ├── DB에 path + uri + size 저장 - └── AiTokenHelper::saveGcsStorageUsage() 호출 - ↓ -응답: { success, data: Photo with rows } -``` - -### 5.3 삭제 흐름 - -``` -사진 삭제: GCS 파일 삭제 → DB 필드 null -행 삭제: 행 내 모든 사진 GCS 삭제 → 행 삭제 → sort_order 재정렬 -사진대지 삭제: 모든 행의 모든 사진 GCS 삭제 → soft delete -``` - ---- - -## 6. 음성 입력 (Web Speech API) - -### 6.1 VoiceInputButton 컴포넌트 - -현장명, 설명 필드에 음성으로 텍스트 입력 가능. - -```javascript -// Web Speech Recognition 설정 -recognition.lang = 'ko-KR'; -recognition.continuous = true; -recognition.interimResults = true; -recognition.maxAlternatives = 1; -``` - -### 6.2 인식 상태 - -| 상태 | 표시 | 설명 | -|------|------|------| -| interim (미확정) | 이탤릭 + 회색 | 인식 중간 결과, 2초 후 소실 | -| final (확정) | 일반체 + 진한색 | 확정 텍스트, 영구 저장 | - -### 6.3 사용량 추적 - -``` -STT 사용 종료 시: -duration = Math.max(1, (Date.now() - startTime) / 1000) - ↓ -POST /juil/construction-photos/log-stt-usage - body: { duration_seconds } - ↓ -AiTokenHelper::saveSttUsage('공사현장사진대지-음성입력', seconds) -``` - ---- - -## 7. UI 구성 (React) - -### 7.1 사진 타입별 색상 - -| 타입 | 라벨 | 배경색 | 뱃지색 | -|------|------|--------|--------| -| `before` | 작업전 | `bg-blue-50` | `bg-blue-100 text-blue-800` | -| `during` | 작업중 | `bg-yellow-50` | `bg-yellow-100 text-yellow-800` | -| `after` | 작업후 | `bg-green-50` | `bg-green-100 text-green-800` | - -### 7.2 행 관리 - -- **행 추가**: sort_order 자동 계산 (마지막 + 1) -- **행 삭제**: 최소 1개 행 유지 필수 -- **행별 사진**: 각 행에 3개 타입 사진 독립 업로드/삭제 - ---- - -## 8. 모델 메서드 - -### 8.1 ConstructionSitePhoto - -```php -user() # BelongsTo User (등록자) -rows() # HasMany Row (sort_order ASC) -getPhotoCount(): int # 전체 사진 개수 (모든 행의 사진 합계) -``` - -### 8.2 ConstructionSitePhotoRow - -```php -constructionSitePhoto() # BelongsTo 부모 -hasPhoto(string $type): bool # 특정 타입 사진 존재 여부 -getPhotoCount(): int # 이 행의 사진 개수 (0~3) -``` - -### 8.3 ConstructionSitePhotoService - -```php -getList(array $filters) # 검색/필터 목록 (페이지네이션) -create(array $data) # 생성 + 빈 행 1개 자동 추가 -update(ConstructionSitePhoto, array $data) # 메타데이터만 수정 -delete(ConstructionSitePhoto) # GCS 전체 삭제 → soft delete -uploadPhoto(Row, UploadedFile, string $type) # GCS 업로드 + DB 기록 -deletePhotoByType(Row, string $type) # 특정 타입 GCS 삭제 -addRow(ConstructionSitePhoto) # 행 추가 (sort_order 자동) -deleteRow(Row) # 행 내 GCS 삭제 → 행 삭제 → 재정렬 -``` - ---- - -## 관련 문서 - -- [README.md](README.md) — 기획 메뉴 전체 개요 -- [회의록 작성](meeting-minutes.md) — STT/AI 통합 회의 기록 -- [견적/프로젝트/워크플로우](planning-views.md) — 화면 명세 - ---- - -**최종 업데이트**: 2026-03-06 diff --git a/sam/docs/features/planning/meeting-minutes.md b/sam/docs/features/planning/meeting-minutes.md deleted file mode 100644 index 09d089a..0000000 --- a/sam/docs/features/planning/meeting-minutes.md +++ /dev/null @@ -1,456 +0,0 @@ -# 회의록 작성 - -> **작성일**: 2026-03-06 -> **상태**: 운영 중 -> **라우트**: `/juil/meeting-minutes` -> **관련**: [README.md](README.md) | [사진대지](construction-photos.md) | [뷰 화면](planning-views.md) - ---- - -## 1. 개요 - -음성으로 회의 내용을 기록하고, **Google STT(화자 분리)** + **Gemini AI(요약/결정사항/액션아이템)** 로 자동 정리하는 회의록 시스템. 브라우저 MediaRecorder로 녹음하고, GCS에 오디오를 저장하며, 세그먼트(화자별 발화)를 관리한다. - ---- - -## 2. 라우트 - -``` -/juil/meeting-minutes -├── GET / → index (목록 페이지) -├── GET /list → list (JSON 목록) -├── POST / → store (새 회의록 생성) -├── POST /log-stt-usage → logSttUsage (STT 시간 기록) -├── GET /{id} → show (상세 조회 + segments) -├── PUT /{id} → update (메타데이터 수정) -├── DELETE /{id} → destroy (삭제) -├── POST /{id}/segments → saveSegments (세그먼트 저장) -├── POST /{id}/upload-audio → uploadAudio (오디오 업로드) -├── POST /{id}/summarize → summarize (AI 요약 생성) -├── POST /{id}/diarize → diarize (자동 화자 분리) -└── GET /{id}/download-audio → downloadAudio (오디오 다운로드) -``` - ---- - -## 3. 데이터베이스 - -### 3.1 meeting_minutes (회의록) - -| 컬럼 | 타입 | 설명 | -|------|------|------| -| `id` | BIGINT PK | | -| `tenant_id` | BIGINT FK | 테넌트 격리 | -| `user_id` | BIGINT FK | 작성자 | -| `title` | VARCHAR(300) | 제목 (기본: "무제 회의록") | -| `folder` | VARCHAR(100) NULL | 폴더 분류 | -| `participants` | JSON NULL | 참여자 목록 배열 | -| `meeting_date` | DATE | 회의 날짜 | -| `meeting_time` | TIME NULL | 회의 시작 시간 | -| `duration_seconds` | INT UNSIGNED | 녹음 총 시간(초) | -| `audio_file_path` | VARCHAR(500) NULL | 오디오 GCS 경로 | -| `audio_gcs_uri` | VARCHAR(500) NULL | 오디오 GCS URI | -| `audio_file_size` | BIGINT UNSIGNED NULL | 오디오 파일 크기 (bytes) | -| `full_transcript` | LONGTEXT NULL | 전체 트랜스크립트 | -| `summary` | LONGTEXT NULL | AI 요약 | -| `decisions` | JSON NULL | 결정사항 배열 | -| `action_items` | JSON NULL | 액션아이템 배열 | -| `status` | VARCHAR(20) | 상태 (5가지) | -| `stt_language` | VARCHAR(10) | STT 언어 (기본: ko-KR) | -| `deleted_at` | TIMESTAMP NULL | 소프트 삭제 | - -**인덱스**: `tenant_id`, `user_id`, `(tenant_id, meeting_date)`, `status` - -### 3.2 meeting_minute_segments (세그먼트) - -| 컬럼 | 타입 | 설명 | -|------|------|------| -| `id` | BIGINT PK | | -| `meeting_minute_id` | BIGINT FK | 회의록 (cascade delete) | -| `segment_order` | INT UNSIGNED | 순서 | -| `speaker_name` | VARCHAR(100) | 화자 이름 (기본: "화자 1") | -| `speaker_label` | VARCHAR(20) NULL | 화자 라벨/번호 | -| `text` | TEXT | 발화 텍스트 | -| `start_time_ms` | INT UNSIGNED | 시작 시간 (ms, 기본: 0) | -| `end_time_ms` | INT UNSIGNED NULL | 종료 시간 (ms) | -| `is_manual_speaker` | BOOLEAN | 수동 화자 전환 여부 (기본: true) | - -**인덱스**: `meeting_minute_id`, `(meeting_minute_id, segment_order)` - -### 3.3 테이블 관계 - -``` -meeting_minutes - │ 1:N - ▼ -meeting_minute_segments (segment_order ASC) - ├── speaker_name (화자명) - ├── text (발화 내용) - └── start_time_ms / end_time_ms (타임스탬프) -``` - ---- - -## 4. 상태 관리 - -### 4.1 상태값 - -| 상태 | 코드 | 색상 | 설명 | -|------|------|------|------| -| 초안 | `DRAFT` | 회색 | 생성 직후, 편집 가능 | -| 녹음중 | `RECORDING` | 빨강 | (클라이언트 상태) | -| 처리중 | `PROCESSING` | 노랑 | AI 요약/화자분리 처리 중 | -| 완료 | `COMPLETED` | 초록 | AI 처리 완료 | -| 실패 | `FAILED` | 빨강 | AI 처리 실패 | - -### 4.2 상태 전이 - -``` -DRAFT - ↓ [오디오 업로드, 세그먼트 추가] -DRAFT (계속 편집) - ↓ [summarize() 호출] -PROCESSING - ↓ -COMPLETED (성공) 또는 FAILED (실패) - -DRAFT - ↓ [diarize() 호출 → 화자 분리] -DRAFT (세그먼트 갱신, 상태 유지) -``` - ---- - -## 5. API 명세 - -### 5.1 목록 조회 - -``` -GET /juil/meeting-minutes/list -``` - -| 파라미터 | 타입 | 설명 | -|---------|------|------| -| `search` | string | 제목 검색 | -| `date_from` | date | 시작일 | -| `date_to` | date | 종료일 | -| `status` | string | 상태 필터 | -| `per_page` | int | 페이지당 건수 | - -### 5.2 생성 - -``` -POST /juil/meeting-minutes -``` - -| 필드 | 규칙 | 설명 | -|------|------|------| -| `title` | nullable, max:300 | 제목 (미입력 시 "무제 회의록") | -| `folder` | nullable, max:100 | 폴더 분류 | -| `participants` | nullable, array | 참여자 목록 | -| `meeting_date` | required, date | 회의 날짜 | -| `meeting_time` | nullable | 회의 시간 | -| `stt_language` | nullable, max:10 | STT 언어 (기본: ko-KR) | - -### 5.3 세그먼트 저장 - -``` -POST /juil/meeting-minutes/{id}/segments -``` - -```json -{ - "segments": [ - { - "speaker_name": "김과장", - "speaker_label": "1", - "text": "블라인드 납기일 확인 필요합니다.", - "start_time_ms": 0, - "end_time_ms": 5000, - "is_manual_speaker": true - } - ] -} -``` - -> **전처리**: 빈 텍스트 필터링, 언더스코어 노이즈 제거, 다중 공백 정규화 -> **자동 생성**: `full_transcript` = `[화자명] 발화텍스트\n...` 형식 - -### 5.4 오디오 업로드 - -``` -POST /juil/meeting-minutes/{id}/upload-audio -``` - -| 필드 | 규칙 | 설명 | -|------|------|------| -| `audio` | required, file | webm/mp3 등 | -| `duration_seconds` | required, integer, min:1 | 녹음 시간(초) | - -### 5.5 AI 요약 생성 - -``` -POST /juil/meeting-minutes/{id}/summarize -``` - -**요청**: 없음 (서버에서 `full_transcript` 사용) - -**응답 예시:** - -```json -{ - "success": true, - "message": "AI 요약이 완료되었습니다.", - "data": { - "summary": "블라인드 납품 일정과 현장 설치 계획을 논의했습니다...", - "decisions": [ - "납품일을 3월 15일로 확정", - "현장 실측은 3월 10일 진행" - ], - "action_items": [ - { - "assignee": "김과장", - "task": "거래처에 납기 확인 연락", - "deadline": "2026-03-08" - } - ], - "status": "COMPLETED" - } -} -``` - -### 5.6 자동 화자 분리 - -``` -POST /juil/meeting-minutes/{id}/diarize -``` - -| 필드 | 설명 | 기본값 | -|------|------|--------| -| `min_speakers` | 최소 화자 수 | 2 | -| `max_speakers` | 최대 화자 수 | 6 | - -**응답:** - -```json -{ - "success": true, - "message": "자동 화자 분리가 완료되었습니다. (3명 감지)", - "data": { /* Meeting with segments */ }, - "speaker_count": 3 -} -``` - ---- - -## 6. AI 통합 상세 - -### 6.1 화자 분리 (Diarization) 3단계 폴백 - -``` -[1단계] Google STT V2 (Chirp2) ← 최우선 - │ speechToTextWithDiarizationAuto() - │ 최신 모델, 높은 정확도 - │ 도메인 용어 힌트 포함 - │ - ↓ (실패 시) -[2단계] Google STT V1 (latest_long) ← 폴백 - │ 안정적이지만 약간 덜 정확 - │ - ↓ (1명만 인식 시) -[3단계] Gemini AI 화자 재분배 - splitSpeakersWithGemini() - 대화 맥락/호칭/질답 패턴/어투 변화 분석 - 2명 이상으로 재분배 -``` - -### 6.2 요약 생성 (Gemini API) - -``` -입력: full_transcript (전체 트랜스크립트) - ↓ -Gemini API 호출 - ├── 모드 1: Vertex AI (projectId, region, JWT) - └── 모드 2: Google AI Studio (API key) ← 폴백 - │ - │ Temperature: 0.3 (결정적) - │ Max tokens: 4096 - ↓ -출력 JSON: -{ - "summary": "3-5문장 요약", - "decisions": ["결정사항 1", "..."], - "action_items": [ - { "assignee": "담당자", "task": "할일", "deadline": "기한" } - ], - "keywords": ["키워드1", "..."] -} -``` - -### 6.3 Gemini 화자 재분배 - -Google STT가 1명만 인식할 때 Gemini로 대화 맥락 분석: - -``` -입력: 단일 화자 트랜스크립트 + 예상 화자 수 - ↓ -Gemini 프롬프트: - - 대화 맥락 분석 (호칭, 질답, 어투 변화) - - 지정된 수의 화자로 분리 - ↓ -출력: 화자별 세그먼트 배열 - → DB 세그먼트 교체 -``` - ---- - -## 7. 오디오 관리 (GCS) - -### 7.1 GCS 경로 패턴 - -``` -meeting-minutes/{tenant_id}/{meeting_id}/{timestamp}.webm -``` - -### 7.2 녹음 흐름 - -``` -브라우저 MediaRecorder API - ├── navigator.mediaDevices.getUserMedia({ audio: true }) - ├── new MediaRecorder(stream) - ├── recorder.ondataavailable → webm 블롭 수집 - └── 녹음 종료 → FormData로 업로드 - ↓ -POST /{id}/upload-audio - ├── GCS 업로드 - ├── DB: audio_file_path, audio_gcs_uri, audio_file_size, duration_seconds - └── AiTokenHelper::saveGcsStorageUsage() -``` - -### 7.3 다운로드 - -``` -GET /{id}/download-audio - → GCS에서 파일 콘텐츠 다운로드 - → Content-Disposition: attachment; filename="{title}.webm" -``` - ---- - -## 8. 세그먼트 처리 로직 - -### 8.1 저장 시 전처리 - -```php -// 1. 빈 텍스트 필터링 -trim($segment['text']) !== '' - -// 2. 언더스코어 노이즈 제거 -str_replace('_', '', $text) - -// 3. 다중 공백 정규화 -preg_replace('/\s{2,}/', ' ', $text) -``` - -### 8.2 전체 트랜스크립트 자동 생성 - -``` -[김과장] 블라인드 납기일 확인 필요합니다. -[박부장] 3월 15일로 확정합시다. -[김과장] 네, 거래처에 연락하겠습니다. -``` - -### 8.3 화자 분리 결과 세그먼트 변환 - -``` -Google STT 결과 → MeetingMinuteSegment 변환: -{ - segment_order: 순서, - speaker_name: "화자 N", - speaker_label: "N", - text: 발화 텍스트, - start_time_ms: 시작시간, - end_time_ms: 종료시간, - is_manual_speaker: false // 자동 분리 -} -``` - ---- - -## 9. UI 구성 (React) - -### 9.1 화자 색상 - -| 화자 | 배경색 | 뱃지색 | -|------|--------|--------| -| 화자 1 | `bg-blue-50` | `bg-blue-100 text-blue-800` | -| 화자 2 | `bg-green-50` | `bg-green-100 text-green-800` | -| 화자 3 | `bg-purple-50` | `bg-purple-100 text-purple-800` | -| 화자 4 | `bg-orange-50` | `bg-orange-100 text-orange-800` | - -### 9.2 지원 언어 - -| 코드 | 라벨 | -|------|------| -| `ko-KR` | 한국어 | -| `en-US` | English | -| `ja-JP` | 日本語 | -| `zh-CN` | 中文 | - ---- - -## 10. 사용량 추적 - -| 추적 항목 | 레이블 | Helper | -|----------|--------|--------| -| Web Speech API 사용 | `회의록-음성인식` | `AiTokenHelper::saveSttUsage()` | -| Google STT V1 화자 분리 | `회의록-화자분리` | `AiTokenHelper::saveSttUsage()` | -| Google STT V2 화자 분리 | `회의록-화자분리(Chirp2)` | `AiTokenHelper::saveSttUsage()` | -| GCS 오디오 저장 | `회의록-GCS저장` | `AiTokenHelper::saveGcsStorageUsage()` | -| Gemini 요약/분리 | `회의록-AI요약` | `AiTokenHelper::saveGeminiUsage()` | - ---- - -## 11. 모델 메서드 - -### 11.1 MeetingMinute - -```php -user() # BelongsTo User -segments() # HasMany Segment (segment_order ASC) -getFormattedDurationAttribute() # "H:MM:SS" 또는 "MM:SS" -``` - -**Cast**: `participants`, `decisions`, `action_items` → array, `meeting_date` → date - -### 11.2 MeetingMinuteService - -```php -# CRUD -getList(array $filters) # 검색/필터 목록 -create(array $data) # 생성 (DRAFT) -update(MeetingMinute, array $data) # 수정 -delete(MeetingMinute) # GCS 삭제 → soft delete - -# 세그먼트 -saveSegments(MeetingMinute, array $segments) # 전처리 + 저장 + 트랜스크립트 생성 -uploadAudio(MeetingMinute, UploadedFile, int $seconds) # GCS 업로드 -logSttUsage(int $seconds) # STT 사용량 기록 - -# AI -generateSummary(MeetingMinute) # Gemini 요약 생성 -processDiarization(MeetingMinute, int $min, int $max) # 3단계 화자 분리 -splitSpeakersWithGemini(string $text, int $expected) # Gemini 화자 재분배 -``` - ---- - -## 관련 문서 - -- [README.md](README.md) — 기획 메뉴 전체 개요 -- [공사현장 사진대지](construction-photos.md) — GCS 파일 관리, 음성 입력 -- [견적/프로젝트/워크플로우](planning-views.md) — 화면 명세 - ---- - -**최종 업데이트**: 2026-03-06 diff --git a/sam/docs/features/planning/planning-views.md b/sam/docs/features/planning/planning-views.md deleted file mode 100644 index 4b087ac..0000000 --- a/sam/docs/features/planning/planning-views.md +++ /dev/null @@ -1,222 +0,0 @@ -# 견적/프로젝트/워크플로우 화면 명세 - -> **작성일**: 2026-03-06 -> **상태**: 뷰 구현 완료 (목데이터 기반, API 미연동) -> **라우트**: `/juil/estimate`, `/juil/project`, `/juil/workflow` -> **관련**: [README.md](README.md) | [사진대지](construction-photos.md) | [회의록](meeting-minutes.md) - ---- - -## 1. 개요 - -3개 화면 모두 **React 인라인 컴포넌트**(Babel 브라우저 트랜스파일)로 구현. 현재는 정적/목데이터 기반이며, 향후 API 연동 예정. PlanningController에서 뷰만 반환한다. - ---- - -## 2. 견적/입찰/공사관리 (/juil/estimate) - -### 2.1 개요 - -블라인드/스크린 설치 프로젝트의 견적서 작성, 입찰 관리, 공사 진행 현황을 한 화면에서 관리. - -### 2.2 데이터 구조 (initialEstimates) - -```javascript -{ - id: "string", - name: "프로젝트명", - client: "고객사명", - status: "견적중|입찰|계약|공사중|준공", - amount: number, // 금액 - startDate: "YYYY-MM-DD", - endDate: "YYYY-MM-DD", - manager: "담당자명", - items: [ // 품목 내역 - { name: "품목명", quantity: number, unitPrice: number } - ] -} -``` - -### 2.3 공사관리 정보 (initialConstructionData) - -```javascript -{ - id: "string", - estimateId: "string", // 연결 견적 - siteName: "현장명", - address: "현장 주소", - progress: number, // 진행률 (0~100) - workers: number, // 투입 인원 - safetyChecks: [ // 안전점검 - { date: "YYYY-MM-DD", result: "합격|불합격", inspector: "점검자" } - ] -} -``` - -### 2.4 상태별 배지 색상 - -| 상태 | 색상 | -|------|------| -| 견적중 | 파랑 | -| 입찰 | 보라 | -| 계약 | 초록 | -| 공사중 | 주황 | -| 준공 | 회색 | - -### 2.5 SAM 연계 - -- 견적서 작성 시 SAM 견적 시스템(`features/quotes/`) 데이터 활용 가능 -- 향후 `/juil/estimate` ↔ SAM 견적 API 연동 계획 - ---- - -## 3. 프로젝트관리/기성청구 (/juil/project) - -### 3.1 개요 - -계약된 프로젝트의 현장 관리, 발주/청구/인건비 상태 추적, 기성 청구 관리. - -### 3.2 데이터 구조 (initialProjects) - -```javascript -{ - id: "string", - name: "프로젝트명", - client: "발주처", - contractAmount: number, // 계약금액 - status: "진행중|완료|보류", - sites: [ // 현장 목록 - { - name: "현장명", - address: "주소", - progress: number // 진행률 - } - ], - orders: [ // 발주 내역 - { - vendor: "거래처", - amount: number, - status: "발주|납품|정산" - } - ], - claims: [ // 기성 청구 - { - round: number, // 차수 - amount: number, // 청구금액 - claimDate: "YYYY-MM-DD", - status: "청구|승인|입금" - } - ], - laborCosts: [ // 인건비 - { - month: "YYYY-MM", - amount: number, - workers: number - } - ] -} -``` - -### 3.3 금액 포맷 함수 - -```javascript -fmt(amount) // 1,234,567 (쉼표 포맷) -fmtBillion(amount) // 12.3억 (억 단위 축약) -``` - ---- - -## 4. 업무 Workflow (/juil/workflow) - -### 4.1 개요 - -블라인드/스크린 사업의 전체 업무 프로세스를 단계별로 시각화. 각 프로세스에 담당 부서, 산출물, 서브스텝을 정의. - -### 4.2 프로세스 데이터 구조 - -```javascript -{ - id: "S1-1", // 프로세스 ID - phase: "영업", // Phase 명 - name: "정보 수집", // 프로세스 이름 - icon: "icon-name", // 아이콘 - dept: "영업팀", // 담당 부서 - color: "#3B82F6", // 테마 색상 - description: "프로세스 설명", - documents: [ // 산출물 목록 - "현장조사서", "고객요구사항서" - ], - subSteps: [ // 상세 서브스텝 - { - name: "서브스텝명", - description: "상세 설명", - responsible: "담당자/팀", - output: "산출물" - } - ] -} -``` - -### 4.3 업무 Phase 목록 - -| Phase | ID 범위 | 설명 | -|-------|---------|------| -| **영업** | S1-1 ~ S1-4 | 정보 수집 → 현장 실측 → 고객 미팅 → 프로젝트 검토 | -| **견적서 작성** | S2-1 ~ S2-4 | 물량 산출 → 단가 산정 → 견적가 산출 → 견적서 작성/검토 | -| **입찰** | S3-* | 입찰 준비 → 제출 → 결과 확인 | -| **계약** | S4-* | 계약 협상 → 계약 체결 | -| **공사** | S5-* | 자재 발주 → 시공 → 현장 관리 | -| **준공** | S6-* | 검수 → 하자보수 → 준공 정산 | - -### 4.4 SAM 연계 포인트 - -```javascript -// 견적서 작성 Phase에서 SAM 견적 화면으로 연결 -{ samLink: '/juil/estimate', label: '견적서 작성 바로가기' } -``` - ---- - -## 5. 공통 특징 - -### 5.1 HTMX 전체 페이지 로드 - -3개 화면 모두 React 컴포넌트 사용하므로 HTMX 부분 로드 불가: - -```php -// PlanningController의 모든 메서드 -if ($request->header('HX-Request')) { - return response('', 200)->header('HX-Redirect', route('juil.xxx')); -} -return view('juil.xxx'); -``` - -### 5.2 현재 구현 상태 - -| 항목 | 상태 | -|------|------| -| UI 화면 | 구현 완료 (React 인라인) | -| 목데이터 | 블레이드에 하드코딩 | -| API 연동 | 미연동 (향후 계획) | -| DB 테이블 | 미생성 (향후 계획) | -| CRUD 기능 | 뷰 조회만 (생성/수정/삭제 미구현) | - -### 5.3 향후 개발 방향 - -1. 견적/프로젝트 DB 테이블 설계 (API 프로젝트) -2. API 엔드포인트 구현 -3. React 컴포넌트 API 연동 -4. SAM 견적 시스템과 데이터 동기화 - ---- - -## 관련 문서 - -- [README.md](README.md) — 기획 메뉴 전체 개요 -- [공사현장 사진대지](construction-photos.md) — GCS 파일 관리, 음성 입력 -- [회의록 작성](meeting-minutes.md) — STT/AI 통합 회의 기록 -- [견적 시스템](../quotes/README.md) — SAM 견적 관리 (BOM, 10단계 로직) - ---- - -**최종 업데이트**: 2026-03-06 diff --git a/sam/docs/features/rd/README.md b/sam/docs/features/rd/README.md deleted file mode 100644 index 1483160..0000000 --- a/sam/docs/features/rd/README.md +++ /dev/null @@ -1,110 +0,0 @@ -# R&D 메뉴 - -> **작성일**: 2026-03-08 -> **상태**: 운영 중 -> **프로젝트**: SAM MNG (관리자 웹) -> **라우트 접두사**: `/rd` - ---- - -## 1. 개요 - -### 1.1 목적 - -R&D 메뉴는 SAM 플랫폼의 **연구개발 및 내부 도구** 모음이다. AI 견적, 조직도 관리, 기획디자인(스토리보드 에디터), 안전점검 등 실험적이거나 내부 운영 목적의 기능을 제공한다. - -### 1.2 문서 구조 - -| 문서 | 설명 | -|------|------| -| **README.md** (이 문서) | 전체 개요, 메뉴 구조, 컨트롤러 매핑 | -| [planning-design.md](planning-design.md) | 기획디자인 스토리보드 에디터 기술 명세 | -| [design-insight.md](design-insight.md) | 디자인 인사이트 UI/UX 연구 도구 (100종 패턴, AI 프롬프트) | - -### 1.3 하위 메뉴 구조 - -``` -R&D -├── 대시보드 /rd -├── 조직도 관리 /rd/org-chart -├── 중대재해처벌법 점검 /rd/safety-audit -├── AI 견적 /rd/ai-quotation -│ ├── 목록 /rd/ai-quotation -│ ├── 생성 /rd/ai-quotation/create -│ ├── 상세 /rd/ai-quotation/{id} -│ ├── 편집 /rd/ai-quotation/{id}/edit -│ └── 문서 /rd/ai-quotation/{id}/document -├── 기획디자인 /rd/planning-design -└── 디자인 인사이트 /rd/design-insight -``` - ---- - -## 2. 아키텍처 - -### 2.1 기술 스택 - -| 계층 | 기술 | 설명 | -|------|------|------| -| 뷰 | Blade + Alpine.js | 반응형 SPA (서버 렌더링 없음) | -| 컨트롤러 | `RdController` | 모든 R&D 라우트 처리 | -| 서비스 | `AiQuotationService` | AI 견적 비즈니스 로직 | -| 모델 | `AiQuotation`, `Employee`, `Department`, `Tenant` | Multi-tenant | -| 저장 | localStorage (기획디자인), DB (견적/조직도) | 용도별 분리 | - -### 2.2 컨트롤러 구조 - -**파일**: `app/Http/Controllers/RdController.php` - -| 메서드 | 라우트 | 설명 | -|--------|--------|------| -| `index()` | `GET /rd` | R&D 대시보드 | -| `orgChart()` | `GET /rd/org-chart` | 조직도 관리 | -| `orgChartAssign()` | `POST /rd/org-chart/assign` | 직원 부서 배치 | -| `orgChartUnassign()` | `POST /rd/org-chart/unassign` | 직원 부서 해제 | -| `orgChartReorder()` | `POST /rd/org-chart/reorder` | 직원 순서/이동 | -| `orgChartReorderDepts()` | `POST /rd/org-chart/reorder-depts` | 부서 순서 변경 | -| `orgChartToggleHide()` | `POST /rd/org-chart/toggle-hide` | 부서 숨기기/표시 | -| `safetyAudit()` | `GET /rd/safety-audit` | 중대재해처벌법 점검 | -| `quotations()` | `GET /rd/ai-quotation` | AI 견적 목록 | -| `createQuotation()` | `GET /rd/ai-quotation/create` | AI 견적 생성 폼 | -| `showQuotation()` | `GET /rd/ai-quotation/{id}` | AI 견적 상세 | -| `editQuotation()` | `GET /rd/ai-quotation/{id}/edit` | AI 견적 편집 | -| `documentQuotation()` | `GET /rd/ai-quotation/{id}/document` | AI 견적 문서 | -| `planningDesign()` | `GET /rd/planning-design` | 기획디자인 | -| `designInsight()` | `GET /rd/design-insight` | 디자인 인사이트 | - -### 2.3 HTMX 전체 페이지 로드 규칙 - -모든 `/rd/*` 페이지는 Alpine.js 또는 React 컴포넌트를 사용하므로, HTMX 부분 로드 시 스크립트가 실행되지 않는다. 각 메서드에서 `HX-Request` 감지 시 `HX-Redirect`로 전체 페이지 로드를 강제한다. - -```php -if ($request->header('HX-Request')) { - return response('', 200)->header('HX-Redirect', route('rd.planning-design')); -} -``` - ---- - -## 3. 기능별 구현 현황 - -| 기능 | 구현 방식 | 백엔드 | DB | 상태 | -|------|----------|--------|-----|------| -| R&D 대시보드 | Blade | AiQuotationService | ai_quotations | 운영 중 | -| 조직도 관리 | Blade + Alpine.js | RdController (직접 쿼리) | employees, departments | 운영 중 | -| 중대재해처벌법 점검 | Blade (정적) | 없음 | 없음 | 운영 중 | -| AI 견적 | Blade + Alpine.js | AiQuotationService | ai_quotations | 운영 중 | -| **기획디자인** | **Blade + Alpine.js (SPA)** | **없음 (localStorage)** | **없음** | **운영 중** | -| **디자인 인사이트** | **Blade + Alpine.js (SPA)** | **없음 (localStorage)** | **없음** | **운영 중** | - ---- - -## 4. 관련 문서 - -- [기획디자인 스토리보드 에디터](planning-design.md) — 블록 에디터, 서식, 인쇄, 내보내기 -- [디자인 인사이트](design-insight.md) — UI/UX 연구 도구 (100종 패턴, AI 프롬프트 복사) -- [조직도 관리 기술문서](../../projects/org-chart/) — 조직도 시스템 상세 (별도 프로젝트 문서) - ---- - -**최종 업데이트**: 2026-03-08 diff --git a/sam/docs/features/rd/design-insight.md b/sam/docs/features/rd/design-insight.md deleted file mode 100644 index 683d02f..0000000 --- a/sam/docs/features/rd/design-insight.md +++ /dev/null @@ -1,246 +0,0 @@ -# 디자인 인사이트 — UI/UX 연구 도구 - -> **작성일**: 2026-03-08 -> **상태**: 운영 중 -> **라우트**: `GET /rd/design-insight` -> **뷰**: `resources/views/rd/design-insight/index.blade.php` - ---- - -## 1. 개요 - -### 1.1 목적 - -디자인 인사이트는 UI/UX 패턴을 **수집·분석·비교**하는 연구 도구이다. 외부 서비스의 UI 레퍼런스를 카드 형태로 정리하고, CSS 와이어프레임 미리보기와 AI 프롬프트 생성 기능으로 디자인 의사결정을 지원한다. - -### 1.2 핵심 기능 - -| 기능 | 설명 | -|------|------| -| 카드 관리 | 레퍼런스/분석/패턴/Before-After 4종 카드 CRUD | -| 프로젝트 관리 | 다중 프로젝트, localStorage 저장 | -| CSS 와이어프레임 | 100종 UI 패턴의 순수 CSS 미니 와이어프레임 | -| 프리셋 템플릿 | 인기 UI 패턴 100종 원클릭 불러오기 | -| AI 프롬프트 복사 | 카드 정보를 AI용 구조화 프롬프트로 변환·복사 | -| 3종 뷰 | 보드(카테고리별)/갤러리(그리드)/리스트 뷰 | -| JSON 내보내기/가져오기 | 프로젝트 데이터 백업/복원 | - ---- - -## 2. 아키텍처 - -### 2.1 기술 스택 - -| 계층 | 기술 | 설명 | -|------|------|------| -| 뷰 | Blade + Alpine.js | 단일 파일 SPA | -| 컨트롤러 | `RdController::designInsight()` | HX-Redirect 패턴 | -| 저장 | localStorage | `di_projects`, `di_current` 키 사용 | -| 백엔드 | 없음 | 서버 API 호출 없이 클라이언트 단독 동작 | -| 스타일 | 커스텀 CSS 변수 | `--di-*` 접두사 (Tailwind 미사용) | - -### 2.2 데이터 구조 - -```json -{ - "id": "di_1709000000_abc123", - "title": "프로젝트명", - "cards": [ - { - "id": "di_1709000001_def456", - "type": "pattern", - "title": "KPI 대시보드", - "category": "dashboard", - "rating": 5, - "tags": ["대시보드", "KPI", "통계"], - "memo": "레퍼런스 설명", - "guidelines": "디자인 가이드라인", - "usedIn": ["Stripe", "Shopify"], - "components": [ - { "name": "KPI 요약 카드", "required": true }, - { "name": "필터 영역", "required": false } - ], - "image": null, - "createdAt": "2026-03-08T00:00:00.000Z" - } - ], - "createdAt": "2026-03-08T00:00:00.000Z", - "updatedAt": "2026-03-08T00:00:00.000Z" -} -``` - ---- - -## 3. 카드 유형 (4종) - -| 코드 | 라벨 | 용도 | -|------|------|------| -| `reference` | 레퍼런스 | 외부 서비스 UI 스크린샷 수집 | -| `analysis` | 분석 | CRAP 원칙 등 UX 분석 (8가지 디자인 원칙 평가) | -| `pattern` | 패턴 | 재사용 가능한 UI 패턴 정의 | -| `comparison` | Before/After | 개선 전후 비교 (이미지 2장) | - ---- - -## 4. 카테고리 (8종) - -| 코드 | 라벨 | 아이콘 | -|------|------|--------| -| `dashboard` | 대시보드 | 📊 | -| `list` | 목록 | 📋 | -| `form` | 상세/폼 | 📝 | -| `modal` | 모달/팝업 | 💬 | -| `navigation` | 네비게이션 | 🧭 | -| `auth` | 로그인 | 🔐 | -| `report` | 보고서 | 📄 | -| `etc` | 기타 | 📎 | - ---- - -## 5. CSS 와이어프레임 시스템 - -### 5.1 동작 원리 - -`getWireframe(card)` 함수가 카드의 `title`과 `tags`를 키워드 매칭하여 해당 패턴에 맞는 순수 CSS/HTML 미니 와이어프레임을 반환한다. - -```javascript -getWireframe(card) { - const t = (card.title || '').toLowerCase(); - const tags = (card.tags || []).join(' ').toLowerCase(); - const key = t + ' ' + tags; - - if (key.includes('kpi') || key.includes('대시보드') && key.includes('통계')) return `...`; - // ... 100종 패턴 매칭 - return `기본 와이어프레임 (매칭 안 됨)`; -} -``` - -### 5.2 프리셋 100종 분포 - -| 카테고리 | 패턴 수 | 대표 패턴 | -|---------|---------|----------| -| 대시보드 | 10 | KPI, 실시간 모니터링, 게이지/미터, 히트맵, 퍼널 | -| 목록 | 10 | 데이터 테이블, 칸반 보드, 마스터-디테일, 피벗 테이블 | -| 상세/폼 | 16 | 프로필, 설정, 위지윅 에디터, 멀티스텝 폼, 태그 입력 | -| 모달/팝업 | 10 | 확인 다이얼로그, 라이트박스, 바텀시트, 컨텍스트 메뉴 | -| 네비게이션 | 10 | 사이드바, 탭, 브레드크럼, FAB, 앵커 스크롤 | -| 로그인 | 8 | 로그인 폼, 회원가입, 비밀번호 재설정, RBAC, API 키 | -| 보고서 | 9 | 인쇄용 보고서, 간트 차트, 조직도, 워터폴, 리포트 빌더 | -| 기타 | 27 | 댓글, 에러 페이지, FAQ, 캐러셀, 파일 매니저 등 | - ---- - -## 6. AI 프롬프트 복사 기능 - -### 6.1 목적 - -카드에 정리된 UI 패턴 정보를 **AI가 이해할 수 있는 구조화된 마크다운 프롬프트**로 변환하여 클립보드에 복사한다. 복사한 프롬프트를 AI(Claude, ChatGPT 등)에 붙여넣으면 해당 스타일로 코드를 생성할 수 있다. - -### 6.2 UI 위치 - -카드 상세 모달 상단, **편집** 버튼 왼쪽에 보라색 `✨ AI 프롬프트` 버튼으로 배치. - -### 6.3 프롬프트 구조 - -`copyAiPrompt(card)` 함수가 카드 데이터를 다음 구조로 변환한다: - -```markdown -## UI 패턴 구현 요청 - -아래 UI/UX 패턴 레퍼런스를 참고하여, 동일한 스타일과 구조로 코드를 작성해 주세요. - ---- - -### 패턴 정보 -- **패턴명**: {title} -- **카테고리**: {category label} -- **완성도 평점**: ★★★☆☆ ({rating}/5) -- **키워드**: {tags} - -### 레퍼런스 설명 -{memo} - -### 실제 사용처 (벤치마킹 대상) -- {usedIn[0]} -- {usedIn[1]} - -### 필수 구성 요소 - -**필수 (반드시 포함)**: -- ✅ {required component} - -**선택 (권장)**: -- ○ {optional component} - -### 디자인 가이드라인 -{guidelines} - -### 개선 제안 -{suggestion} - -### 기대 효과 -{effect} - ---- - -### 구현 요구사항 - -1. **기술 스택**: HTML + Tailwind CSS (또는 프로젝트에 맞는 프레임워크) -2. **반응형**: 모바일/태블릿/데스크톱 대응 -3. **접근성**: 시맨틱 태그, ARIA 라벨, 키보드 네비게이션 -4. **인터랙션**: hover, focus, active 상태 포함 -5. **위 구성 요소를 모두 포함**하되, 실제 서비스처럼 자연스러운 더미 데이터 사용 -6. **위 가이드라인을 충실히 반영**하여 UX 완성도를 높일 것 -``` - -### 6.4 포함 필드 매핑 - -| 카드 필드 | 프롬프트 섹션 | 조건 | -|----------|-------------|------| -| `title` | 패턴 정보 > 패턴명 | 항상 | -| `category` | 패턴 정보 > 카테고리 | 항상 (라벨로 변환) | -| `rating` | 패턴 정보 > 평점 | 항상 (별점으로 변환) | -| `tags` | 패턴 정보 > 키워드 | 태그가 있을 때만 | -| `memo` | 레퍼런스 설명 | 값이 있을 때만 | -| `usedIn` | 실제 사용처 | 배열이 비어있지 않을 때만 | -| `components` | 필수 구성 요소 | 배열이 비어있지 않을 때만 | -| `guidelines` | 디자인 가이드라인 | 값이 있을 때만 | -| `suggestion` | 개선 제안 | 값이 있을 때만 | -| `effect` | 기대 효과 | 값이 있을 때만 | -| `principles` | UX 원칙 | `type === 'analysis'`일 때만 | - ---- - -## 7. 뷰 모드 (3종) - -| 모드 | 설명 | 정렬 | -|------|------|------| -| `board` | 카테고리별 컬럼 그룹핑 | 카테고리 → 생성순 | -| `gallery` | 그리드 갤러리 (와이어프레임 강조) | 필터 순 | -| `list` | 테이블형 리스트 | 필터 순 | - ---- - -## 8. 파일 구조 - -``` -resources/views/rd/design-insight/ -└── index.blade.php # 단일 파일 SPA (~6,200줄) - ├── - - - -

제목

-

본문 내용

- - -``` - -### 3.2 슬라이드 크기 (body width/height) - -| 용도 | body 크기 | 변환 스크립트 layout | -|------|----------|---------------------| -| **16:9 가로형** (발표용) | `width: 720pt; height: 405pt;` | `width: 10, height: 5.625` | -| **9:16 세로형** (브로셔) | `width: 405pt; height: 720pt;` | `width: 5.625, height: 10` | -| **4:3 가로형** (구형) | `width: 720pt; height: 540pt;` | `width: 10, height: 7.5` | - -> **중요**: HTML의 body 크기와 변환 스크립트의 layout 크기가 일치해야 한다. 불일치 시 에러 발생. - -### 3.3 필수 규칙 - -#### 텍스트 줄바꿈 방지 (가장 중요) - -브라우저와 PowerPoint의 폰트 렌더링 차이로, HTML에서 한 줄인 텍스트가 PPTX에서 두 줄로 넘어가는 문제가 발생한다. - -```html - -

이 텍스트는 한 줄입니다

- - -

이 텍스트는 한 줄입니다

- - -

- 여러 줄로 의도된 텍스트입니다.
- 이 경우 nowrap을 넣지 않는다. -

-``` - -#### 적용 대상 - -- 뱃지 텍스트 (01, UC-01 등) -- 카드 제목, 태그, 짧은 라벨 -- 푸터 텍스트 -- 단일행 `

` 태그 전부 - -#### 이미지 경로 - -```html - - - - - -``` - -#### 스타일 작성 - -```html - -

- - -``` - -### 3.4 사용 가능한 CSS 속성 - -| 속성 | 지원 | 비고 | -|------|:----:|------| -| background (색상) | ✅ | 단색, rgba 모두 지원 | -| background (그라데이션) | ✅ | linear-gradient 지원 | -| border | ✅ | 색상, 두께, radius | -| border-radius | ✅ | px, pt 단위 | -| font-size, font-weight | ✅ | pt 단위 권장 | -| color | ✅ | hex, rgba | -| padding, margin | ✅ | pt 단위 권장 | -| display: flex | ✅ | gap, align-items 등 | -| white-space: nowrap | ✅ | 줄바꿈 방지 (필수) | -| opacity | ✅ | | -| box-shadow | ⚠️ | 부분 지원 | -| transform | ❌ | 미지원 | -| animation | ❌ | 미지원 | - ---- - -## 4. 변환 스크립트 작성법 - -### 4.1 기본 구조 (복사해서 사용) - -```javascript -const path = require('path'); - -// ① 패키지 경로 설정 (이 두 줄은 항상 동일) -module.paths.unshift( - path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/node_modules') -); -const PptxGenJS = require('pptxgenjs'); -const html2pptx = require( - path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/html2pptx.js') -); - -async function main() { - const pres = new PptxGenJS(); - - // ② 레이아웃 설정 (HTML body 크기와 일치해야 함) - pres.defineLayout({ name: 'CUSTOM', width: 10, height: 5.625 }); - pres.layout = 'CUSTOM'; - - // ③ HTML 파일 변환 - await html2pptx('/절대경로/slides/slide-01.html', pres); - - // ④ PPTX 출력 - await pres.writeFile({ fileName: '/절대경로/output.pptx' }); - console.log('완료!'); -} - -main().catch(console.error); -``` - -### 4.2 실전 예시: 여러 슬라이드 변환 - -```javascript -const path = require('path'); -module.paths.unshift( - path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/node_modules') -); -const PptxGenJS = require('pptxgenjs'); -const html2pptx = require( - path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/html2pptx.js') -); - -async function main() { - const pres = new PptxGenJS(); - - // 16:9 가로형 - pres.defineLayout({ name: 'CUSTOM_16x9', width: 10, height: 5.625 }); - pres.layout = 'CUSTOM_16x9'; - - const slidesDir = path.join(__dirname, 'slides'); - - // 변환할 HTML 파일 목록 - const slides = [ - 'slide-01.html', - 'slide-02.html', - 'slide-03.html', - ]; - - for (const file of slides) { - console.log(`Converting ${file} ...`); - try { - await html2pptx(path.join(slidesDir, file), pres); - } catch (err) { - console.error(`Error: ${err.message}`); - } - } - - const outputPath = path.join(__dirname, 'my-presentation.pptx'); - await pres.writeFile({ fileName: outputPath }); - console.log(`\nPPTX created: ${outputPath}`); -} - -main().catch(console.error); -``` - -### 4.3 실전 예시: 번호 기반 자동 변환 (18슬라이드) - -```javascript -// slide-01.html ~ slide-18.html 자동 변환 -const totalSlides = 18; -for (let i = 1; i <= totalSlides; i++) { - const num = String(i).padStart(2, '0'); - const htmlFile = path.join(slidesDir, `slide-${num}.html`); - await html2pptx(htmlFile, pres); -} -``` - ---- - -## 5. 실행 방법 - -### 5.1 터미널에서 직접 실행 - -```bash -# 해당 폴더로 이동 후 실행 -cd /home/aweso/sam/docs/brochure -node convert-2page.cjs - -# 또는 절대 경로로 실행 -node /home/aweso/sam/docs/brochure/convert-2page.cjs -``` - -### 5.2 실행 결과 - -``` -Converting brochure-2page-front.html ... -Converting brochure-2page-back.html ... - -PPTX created: /home/aweso/sam/docs/brochure/sam-brochure-2page.pptx -``` - -> 에러가 나면 HTML body 크기와 layout 설정 불일치가 가장 흔한 원인이다. - ---- - -## 6. 프로젝트 내 기존 사용 사례 - -| 경로 | 슬라이드 수 | 레이아웃 | 용도 | -|------|:-----------:|:--------:|------| -| `docs/usecase/` | 18장 | 16:9 가로 | 방화셔터 제안서 | -| `docs/usecase/brochure/` | 1장 / 2장 | 9:16 세로 | 방화셔터 브로셔 | -| `docs/brochure/` | 1장 / 2장 | 9:16 세로 | SAM 범용 브로셔 | -| `docs/plans/slides/` | N장 | 16:9 가로 | 배포 계획 발표 | -| `docs/rules/slides/` | N장 | 16:9 가로 | 정책 규칙 문서 | - ---- - -## 7. 폴더 구조 권장 패턴 - -새 PPTX를 만들 때 아래 구조를 따른다: - -``` -docs/my-document/ -├── slides/ ← HTML 슬라이드 파일들 -│ ├── slide-01.html -│ ├── slide-02.html -│ └── slide-03.html -├── convert.cjs ← 변환 스크립트 -└── my-document.pptx ← 생성된 PPTX (node convert.cjs 실행 후) -``` - ---- - -## 8. 문제 해결 - -| 증상 | 원인 | 해결 | -|------|------|------| -| `Error: dimensions don't match` | HTML body 크기 ≠ layout 설정 | body의 width/height와 `defineLayout` 값 맞추기 | -| 텍스트가 PPTX에서 줄바꿈됨 | `white-space: nowrap` 미적용 | 단일행 `

` 태그에 nowrap 추가 | -| 이미지 안 보임 | 상대 경로 사용 | 절대 경로(`/home/aweso/...`)로 변경 | -| `Cannot find module 'pptxgenjs'` | module.paths 설정 누락 | 스크립트 상단 2줄(module.paths.unshift) 확인 | -| `Cannot find module 'playwright'` | Playwright 미설치 | `cd ~/.claude/skills/pptx-skill/scripts && npx playwright install chromium` | -| PPTX는 생성되지만 빈 슬라이드 | HTML 내용 없음 | HTML 파일을 브라우저로 열어 확인 | - ---- - -## 9. 빠른 시작 (3분 가이드) - -### Step 1: 폴더 만들기 - -```bash -mkdir -p /home/aweso/sam/docs/my-pptx/slides -``` - -### Step 2: HTML 슬라이드 만들기 - -`slides/slide-01.html` 파일 생성: - -```html - - - - - - - -

MY COMPANY

-

발표 제목을 여기에

-

부제목 또는 설명

- - -``` - -### Step 3: 변환 스크립트 만들기 - -`convert.cjs` 파일 생성: - -```javascript -const path = require('path'); -module.paths.unshift(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/node_modules')); -const PptxGenJS = require('pptxgenjs'); -const html2pptx = require(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/html2pptx.js')); - -async function main() { - const pres = new PptxGenJS(); - pres.defineLayout({ name: 'CUSTOM_16x9', width: 10, height: 5.625 }); - pres.layout = 'CUSTOM_16x9'; - - await html2pptx(path.join(__dirname, 'slides', 'slide-01.html'), pres); - - await pres.writeFile({ fileName: path.join(__dirname, 'my-presentation.pptx') }); - console.log('완료!'); -} -main().catch(console.error); -``` - -### Step 4: 실행 - -```bash -cd /home/aweso/sam/docs/my-pptx -node convert.cjs -# → my-presentation.pptx 생성됨 -``` - ---- - -**최종 업데이트**: 2026-03-01 diff --git a/sam/docs/guides/server-how-it-works.md b/sam/docs/guides/server-how-it-works.md deleted file mode 100644 index 974693b..0000000 --- a/sam/docs/guides/server-how-it-works.md +++ /dev/null @@ -1,247 +0,0 @@ -# SAM 서버 동작 원리 초보자 가이드 - -> **작성일**: 2026-02-22 -> **대상**: SAM 프로젝트에 새로 합류한 개발자 - ---- - -## 1. 개요 - -### 1.1 이 문서의 목적 - -SAM 시스템에서 **웹 요청이 어떤 경로로 흐르는지**, **git push 후 서버에서 무슨 일이 일어나는지**를 설명한다. -설정값 나열이 아닌, **"왜 이런 구조인가"**에 초점을 맞춘다. - -### 1.2 SAM 전체 구조 - -``` -브라우저 → Nginx (SSL 종료, 도메인별 라우팅) - │ - ┌────┬───┴───┬─────┬─────┐ - ▼ ▼ ▼ ▼ ▼ - MNG API React Sales 5130 ← 5개 서비스 - (PHP)(PHP) (Node) (PHP) (PHP7.3) - └────┴───┬───┴─────┴─────┘ - ▼ - MySQL 8.0 ← 단일 DB 공유 -``` - ---- - -## 2. 웹 요청의 여정: URL에서 화면까지 - -### 2.1 전체 흐름 - -`https://mng.sam.kr/orders` 접속 시: - -``` -브라우저 →① Nginx →② PHP-FPM →③ Laravel →④ MySQL - │ -브라우저 ←────────────────────────────── ⑤ 응답 -``` - -### 2.2 Step 1: 브라우저 → Nginx - -Nginx는 **도메인 이름**을 보고 어떤 서비스로 보낼지 결정한다. - -- `mng.sam.kr` → MNG 컨테이너의 PHP-FPM (포트 9000) -- `api.sam.kr` → API 컨테이너의 PHP-FPM (포트 9000) -- `dev.sam.kr` → React 컨테이너의 Node.js (포트 3000) - -또한 HTTP(80) 요청을 HTTPS(443)로 리다이렉트하고, SSL 인증서를 처리한다. -이를 **SSL 종료**(SSL Termination)라 한다. 내부 통신은 암호화 없이 빠르게 진행된다. - -### 2.3 Step 2: Nginx → PHP-FPM - -Nginx는 PHP 코드를 직접 실행하지 못한다. 대신 **FastCGI 프로토콜**로 PHP-FPM에 요청을 전달한다. - -``` -Nginx: "이 PHP 파일을 실행해줘" → fastcgi_pass mng:9000 -PHP-FPM: "결과 HTML이야" → Nginx → 브라우저 -``` - -PHP-FPM은 여러 **워커 프로세스**를 미리 만들어 두고, 요청이 오면 빈 워커에 할당한다. -MNG의 경우 최대 20개 워커(`pm.max_children = 20`)가 동시에 요청을 처리할 수 있다. - -### 2.4 Step 3: PHP-FPM → Laravel - -PHP-FPM이 실행하는 진입점은 `public/index.php`다. 여기서 Laravel 프레임워크가 시작된다. - -``` -public/index.php - → Bootstrap (설정 로드, 서비스 등록) - → 미들웨어 (인증, 권한, 로깅) - → 라우터 (URL → 컨트롤러 매핑) - → 컨트롤러 (비즈니스 로직) - → 뷰 렌더링 (Blade 템플릿 → HTML) -``` - -### 2.5 Step 4: Laravel → MySQL - -컨트롤러에서 Eloquent ORM으로 DB를 조회한다. 예를 들어: - -```php -// 코드: Order::where('status', 'active')->get(); -// 실제 SQL: SELECT * FROM orders WHERE status = 'active' AND tenant_id = 1; -``` - -`tenant_id`는 글로벌 스코프로 자동 추가되어, 다른 테넌트의 데이터가 섞이지 않는다. - -### 2.6 Step 5: 응답이 돌아오는 길 - -MySQL → Laravel(HTML 생성) → PHP-FPM → Nginx → 브라우저 순으로 돌아온다. -MNG는 HTMX를 사용하므로, 이후 상호작용은 **HTML 조각**(partial)만 주고받아 페이지 전체를 새로고침하지 않는다. - ---- - -## 3. 각 구성 요소의 역할 - -| 구성 요소 | 역할 | 비유 | -|-----------|------|------| -| **Nginx** | 리버스 프록시, SSL, 정적 파일 | 안내 데스크 | -| **PHP-FPM** | PHP 워커 풀 관리 | 창구 직원 팀 | -| **Laravel** | MVC, 라우팅, 비즈니스 로직 | 업무 매뉴얼 | -| **MySQL** | 데이터 저장/조회 | 서류 보관실 | -| **Supervisor** | 프로세스 감시, 자동 재시작 | 관리 감독관 | - -### 3.1 Supervisor가 관리하는 프로세스 - -각 컨테이너 안에서 Supervisor가 여러 프로세스를 관리한다. - -**API 컨테이너** (`sam-api-1`): -- `php-fpm` — PHP 요청 처리 -- `nginx` — 컨테이너 내부 웹서버 -- `queue-worker` — 백그라운드 작업 (이메일, 알림 등) -- `scheduler` — 60초마다 예약 작업 실행 (`schedule:run`) - -**MNG 컨테이너** (`sam-mng-1`): -- `php-fpm`, `nginx` — 위와 동일 -- `queue-worker` x2 — 2개 워커가 병렬 처리 - ---- - -## 4. 로컬 환경 vs 서버 환경 - -### 4.1 비교 - -``` -[로컬 - Docker] [서버 - Bare-metal] -┌───────────────┐ ┌───────────────┐ -│ sam-nginx-1 │ │ Nginx │ -├───────────────┤ ├───────────────┤ -│ sam-mng-1 │ │ MNG (직접) │ -│ sam-api-1 │ │ API (직접) │ -├───────────────┤ ├───────────────┤ -│ sam-mysql-1 │ │ MySQL (직접) │ -└───────────────┘ └───────────────┘ - 네트워크: samnet 네트워크: localhost -``` - -### 4.2 핵심 차이 - -| 항목 | 로컬 (Docker) | 서버 (Bare-metal) | -|------|--------------|-------------------| -| **DB 접속** | `DB_HOST=sam-mysql-1` | `DB_HOST=127.0.0.1` | -| **코드 반영** | 볼륨 마운트 (실시간) | `git pull` 필요 | -| **명령 실행** | `docker exec sam-api-1 php artisan ...` | `php artisan ...` | - ---- - -## 5. "git push하면 무슨 일이 일어나는가?" - -### 5.1 배포 흐름 다이어그램 - -``` -개발자 PC (WSL) Gitea 서버 운영 서버 -┌──────────┐ push ┌──────────┐ pull ┌──────────┐ -│ 코드 수정 │ ──────────→ │ 원격 │ ←───────── │ 서버에서 │ -│ git add │ │ 저장소 │ │ 수동 pull │ -│ git commit│ └──────────┘ └──────────┘ -└──────────┘ -``` - -> **주의**: 자동 배포(CI/CD)가 없다. 서버에서 **수동으로 `git pull`** 해야 반영된다. - -### 5.2 PHP 앱 배포 (MNG, API) - -```bash -# 서버에서 실행하는 명령 (개발팀장이 수행) -cd /home/webservice/api -git pull # ① 최신 코드 받기 -composer install # ② 패키지 의존성 동기화 -php artisan migrate # ③ DB 구조 변경 적용 -php artisan config:clear # ④ 설정 캐시 초기화 -``` - -**각 명령이 필요한 이유**: - -| 명령 | 왜 필요한가 | -|------|------------| -| `git pull` | 코드를 최신 상태로 동기화 | -| `composer install` | 새로 추가된 PHP 패키지 설치 (`composer.json` 변경 시) | -| `php artisan migrate` | 새 테이블/컬럼 생성 등 DB 스키마 적용 (API만) | -| `php artisan config:clear` | `.env` 또는 `config/` 변경 시 캐시된 설정 갱신 | - -### 5.3 React 앱 배포 (Next.js) - -서버 스펙(2코어, 3.8GB RAM)으로는 Next.js 빌드가 메모리 부족으로 실패한다. -따라서 **로컬에서 빌드 → 결과물을 서버에 업로드**하는 방식을 사용한다. - -```bash -# deploy.sh가 수행하는 5단계 -① 로컬에서 npm run build # standalone 빌드 -② tar.gz로 압축 # .next/standalone + static + public -③ scp로 서버 업로드 # 압축 파일 전송 -④ 서버에서 압축 해제 + 시작 # node server.js (포트 3001) -⑤ 로컬 정리 # 임시 파일 삭제 -``` - ---- - -## 6. SAM 도메인별 요청 경로 - -### 6.1 도메인 → 서비스 매핑 - -| 도메인 | 서비스 | 기술 스택 | 응답 형태 | -|--------|--------|-----------|-----------| -| `mng.sam.kr` | MNG | Laravel + Blade + HTMX | HTML (서버 렌더링) | -| `api.sam.kr` | API | Laravel | JSON | -| `dev.sam.kr` | React | Next.js | HTML (SSR/CSR) | -| `sales.sam.kr` | Sales | Laravel | HTML | -| `5130.sam.kr` | 5130 | PHP 7.3 (레거시) | HTML | - -### 6.2 서비스별 요청 흐름 - -**MNG** (관리자 화면 — Blade + HTMX): -``` -브라우저 → Nginx(:443) → MNG PHP-FPM(:9000) → Laravel → Blade HTML -이후 HTMX가 HTML 조각을 Ajax로 교체 (전체 새로고침 없음) -``` - -**API** (REST API — JSON 응답): -``` -React/외부 → Nginx(:443) → API PHP-FPM(:9000) → Laravel → JSON -인증: Bearer 토큰 (Authorization 헤더) -``` - -**React** (Next.js — SSR + CSR): -``` -브라우저 → Nginx(:443) → Node.js(:3000) → SSR HTML -이후 React 하이드레이션 → CSR (클라이언트 렌더링) -API 호출 시 → Next.js API Route 프록시 → api.sam.kr -``` - ---- - -## 관련 문서 - -| 문서 | 설명 | -|------|------| -| [docker-setup.md](../specs/docker-setup.md) | Docker 환경 설정값 상세 | -| [system-overview.md](../architecture/system-overview.md) | 시스템 아키텍처 레퍼런스 | -| [production-deployment-plan.md](../plans/production-deployment-plan.md) | 운영 배포 계획 | -| [dev-commands.md](../quickstart/dev-commands.md) | 개발 명령어 모음 | - ---- - -**최종 업데이트**: 2026-02-22 diff --git a/sam/docs/guides/table-design-guide.md b/sam/docs/guides/table-design-guide.md deleted file mode 100644 index a920f08..0000000 --- a/sam/docs/guides/table-design-guide.md +++ /dev/null @@ -1,486 +0,0 @@ -# SAM 테이블 설계 가이드 — 비전문가용 - -> **작성일**: 2026-03-02 -> **대상 독자**: 개발자, 기획자, 관리자 — 데이터베이스를 잘 모르는 분도 읽을 수 있습니다 -> **관련 정책**: `standards/options-column-policy.md` (개발자 전용 상세 규칙) - ---- - -## 1. 이 문서는 왜 필요한가? - -SAM은 **여러 회사가 하나의 시스템을 공유**하는 구조입니다. -A회사, B회사, C회사가 모두 같은 프로그램을 쓰지만, 각 회사가 필요한 정보는 다릅니다. - -이 문서는 SAM에서 **데이터를 어떻게 저장하는지**, 그 설계 철학을 누구나 이해할 수 있도록 설명합니다. - ---- - -## 2. 기본 개념: 데이터베이스 테이블이란? - -데이터베이스 테이블은 **엑셀 시트**와 같습니다. - -``` -"주문" 테이블 (= 엑셀 시트) - - 열(컬럼) → 주문번호 │ 고객명 │ 금액 │ 상태 - ───────────────────────────────────────────────────────── - 행(레코드) 1 → ORD-001 │ 김철수 │ 500,000 │ 완료 - 행(레코드) 2 → ORD-002 │ 이영희 │ 300,000 │ 진행중 - 행(레코드) 3 → ORD-003 │ 박민수 │ 800,000 │ 대기 -``` - -- **열(컬럼)** = 정보의 종류 (주문번호, 고객명, 금액...) -- **행(레코드)** = 실제 데이터 한 건 (주문 1건) - ---- - -## 3. 문제: 회사마다 필요한 정보가 다르다 - -SAM은 여러 회사가 같은 테이블을 공유합니다. - -``` -같은 "주문" 테이블을 쓰는데... - - 🏭 A회사 (블라인드 제조) - → "절곡 각도", "날개 수" 정보가 필요해요 - - 🏭 B회사 (스크린 제조) - → "메시 밀도", "소재 종류" 정보가 필요해요 - - 🏭 C회사 (셔터 제조) - → "날개 간격", "색상 코드" 정보가 필요해요 -``` - ---- - -### 3.1 전통적인 해결 방법 (SAM은 이렇게 안 합니다) - -필요할 때마다 엑셀에 열을 추가하는 것처럼, 테이블에 컬럼을 추가합니다. - -``` -"주문" 테이블 — 전통적 방식 - - 주문번호 │ 고객명 │ 금액 │ 절곡각도 │ 날개수 │ 메시밀도 │ 소재 │ 날개간격 │ 색상코드 - ───────────────────────────────────────────────────────────────────────────────── - ORD-001 │ 김철수 │ 50만 │ 45도 │ 12개 │ (빈칸) │ (빈칸) │ (빈칸) │ (빈칸) ← A회사 - ORD-002 │ 이영희 │ 30만 │ (빈칸) │ (빈칸)│ 18 │ 폴리 │ (빈칸) │ (빈칸) ← B회사 - ORD-003 │ 박민수 │ 80만 │ (빈칸) │ (빈칸)│ (빈칸) │ (빈칸) │ 25mm │ #FF0000 ← C회사 -``` - -**문제점:** - -- 회사가 100개면? 열이 수백 개로 늘어남 -- 각 회사는 자기 것 빼고 전부 빈칸 -- 새 회사가 들어올 때마다 시스템 전체를 수정해야 함 -- 열 추가 = 시스템 중단 위험이 있는 작업 - ---- - -### 3.2 SAM의 해결 방법: "메모칸(options)" 하나로 통합 - -**핵심 열만 남기고**, 나머지는 **메모칸 하나**에 자유롭게 적습니다. - -``` -"주문" 테이블 — SAM 방식 - - 주문번호 │ 고객명 │ 금액 │ 상태 │ options (메모칸) - ──────────────────────────────────────────────────────────────────────── - ORD-001 │ 김철수 │ 50만 │ 완료 │ {"절곡각도": 45, "날개수": 12} ← A회사 - ORD-002 │ 이영희 │ 30만 │ 진행 │ {"메시밀도": 18, "소재": "폴리에스터"} ← B회사 - ORD-003 │ 박민수 │ 80만 │ 대기 │ {"날개간격": 25, "색상코드": "#FF0000"} ← C회사 - ORD-004 │ 최지은 │ 40만 │ 대기 │ null ← 메모 없음 -``` - -**`options`** = JSON이라는 형식의 메모칸. `{ }` 안에 자유롭게 정보를 넣을 수 있습니다. - ---- - -## 4. 어떤 정보를 열(컬럼)로 만들고, 어떤 정보를 메모칸(options)에 넣나? - -이것이 SAM 테이블 설계의 **가장 중요한 판단 기준**입니다. - -### 4.1 판단 흐름 (5가지 질문) - -새로운 정보를 저장해야 할 때, 아래 질문에 답합니다. - -``` -질문 1. 이 정보로 다른 테이블의 데이터를 연결(참조)하나? - 예: 고객ID로 고객 테이블을 찾는다 - → YES: 일반 컬럼 - -질문 2. 이 정보로 자주 검색(필터)하나? - 예: "완료" 상태인 주문만 보여줘 - → YES: 일반 컬럼 - -질문 3. 이 정보로 정렬하나? - 예: 최신 주문부터 보여줘 - → YES: 일반 컬럼 - -질문 4. 이 정보가 절대 중복되면 안 되나? - 예: 주문번호는 세상에 하나뿐이어야 한다 - → YES: 일반 컬럼 - -질문 5. 이 정보로 합계/평균을 계산하나? - 예: 이번 달 매출 합계 - → YES: 일반 컬럼 - -질문 1~5 전부 NO → options 메모칸에 저장 -``` - -### 4.2 실생활 예시로 비교 - -#### 예시 1: "주문" 테이블 - -| 정보 | 어디에 저장? | 이유 | -|------|:-----------:|------| -| 주문번호 | **일반 컬럼** | 중복 불가 + 검색 필수 | -| 고객 ID | **일반 컬럼** | 고객 테이블과 연결 | -| 금액 | **일반 컬럼** | 합계 계산 필요 | -| 상태 (진행/완료) | **일반 컬럼** | 필터(검색) 필수 | -| 생성일 | **일반 컬럼** | 정렬 필요 | -| 배송지 주소 | **options** | 부가 정보, 검색 안 함 | -| 수신자 이름 | **options** | 부가 정보 | -| 수신자 연락처 | **options** | 부가 정보 | -| 특이사항 메모 | **options** | 있어도 되고 없어도 됨 | - -**실제 SAM 코드에서 주문(Order) 테이블:** - -``` -일반 컬럼: id, tenant_id, order_number, client_id, total_amount, status, created_at -options: {"shipping_cost_code":"착불", "receiver":"홍길동", - "receiver_contact":"010-1234-5678", - "shipping_address":"서울 강남구 역삼동 123"} -``` - -#### 예시 2: "입고검사" 테이블 - -| 정보 | 어디에 저장? | 이유 | -|------|:-----------:|------| -| 품목 ID | **일반 컬럼** | 품목 테이블과 연결 | -| 수량 | **일반 컬럼** | 합계 계산 | -| 입고일 | **일반 컬럼** | 정렬 + 검색 | -| 제조사 | **options** | 모든 입고에 있지는 않음 | -| 검사 결과 (합격/불합격) | **options** | 검사를 안 하는 회사도 있음 | -| 검사일 | **options** | 선택적 정보 | - -**실제 SAM 코드에서 입고(Receiving) 테이블:** - -``` -일반 컬럼: id, tenant_id, item_id, quantity, received_at, status -options: {"manufacturer":"삼성전자", - "inspection_status":"합격", - "inspection_date":"2026-03-01"} -``` - -> 검사 결과가 options에 있는 이유: **모든 회사가 입고검사를 하는 것은 아닙니다.** -> A회사는 검사를 하고, B회사는 안 합니다. 이걸 일반 컬럼으로 만들면 B회사에겐 항상 빈칸입니다. - -#### 예시 3: "공정" 테이블 - -| 정보 | 어디에 저장? | 이유 | -|------|:-----------:|------| -| 공정 코드 | **일반 컬럼** | 중복 불가 + 검색 | -| 공정명 | **일반 컬럼** | 검색 + 표시 | -| 담당 부서 | **일반 컬럼** | 필터 | -| 작업일지 필요 여부 | **options** | 회사별로 다름 | -| 검사 필요 여부 | **options** | 회사별로 다름 | - -``` -일반 컬럼: id, tenant_id, process_code, process_name, department -options: {"needs_work_log": true, "needs_inspection": false} -``` - ---- - -## 5. 메모칸(options)의 실제 모습: JSON이란? - -`options`에 저장되는 데이터 형식은 **JSON**입니다. -JSON은 프로그래밍 세계의 "구조화된 메모장"이라고 생각하면 됩니다. - -### 5.1 JSON 기본 문법 - -``` -{ ← 시작 - "키": "값", ← 문자(텍스트) - "이름": "홍길동", - "나이": 30, ← 숫자 (따옴표 없음) - "합격": true, ← 참/거짓 (따옴표 없음) - "메모": null ← 값 없음 -} ← 끝 -``` - -### 5.2 중첩(nested) — 메모 안의 메모 - -``` -{ - "배송": { ← 배송 관련 정보를 묶음 - "주소": "서울 강남구 역삼동", - "수신자": "홍길동", - "연락처": "010-1234-5678" - }, - "검사": { ← 검사 관련 정보를 묶음 - "결과": "합격", - "검사일": "2026-03-01", - "검사자ID": 5 - } -} -``` - -### 5.3 목록(배열) — 여러 개를 나열 - -``` -{ - "선택지": [ ← 대괄호 [ ] = 목록 - {"label": "블라인드", "value": "blind"}, - {"label": "스크린", "value": "screen"}, - {"label": "셔터", "value": "shutter"} - ] -} -``` - -> 이 형태는 드롭다운 메뉴의 선택지 목록을 저장할 때 사용합니다. - ---- - -## 6. 멀티테넌시란? — 여러 회사가 하나의 시스템을 쓰는 구조 - -### 6.1 개념 - -``` -┌──────────────────────────────────────────────┐ -│ SAM 시스템 (하나의 프로그램) │ -│ │ -│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ -│ │ A회사 │ │ B회사 │ │ C회사 │ │ -│ │ tenant=1 │ │ tenant=2 │ │ tenant=3 │ │ -│ │ │ │ │ │ │ │ -│ │ 블라인드 │ │ 스크린 │ │ 셔터 │ │ -│ │ 제조 │ │ 제조 │ │ 제조 │ │ -│ └──────────┘ └──────────┘ └──────────┘ │ -│ │ -│ 같은 테이블을 쓰지만, │ -│ tenant_id로 데이터가 완전히 분리됨 │ -└──────────────────────────────────────────────┘ -``` - -### 6.2 tenant_id = 회사 식별 번호 - -모든 테이블의 모든 행에 `tenant_id`(회사 번호)가 붙어 있습니다. - -``` -"주문" 테이블 - - id │ tenant_id │ 주문번호 │ 금액 │ options - ─────────────────────────────────────────────────────────── - 1 │ 1 │ ORD-001 │ 50만 │ {"절곡각도": 45} ← A회사 데이터 - 2 │ 1 │ ORD-002 │ 30만 │ {"절곡각도": 90} ← A회사 데이터 - 3 │ 2 │ ORD-001 │ 80만 │ {"메시밀도": 18} ← B회사 데이터 - 4 │ 3 │ ORD-001 │ 40만 │ {"날개간격": 25} ← C회사 데이터 -``` - -**A회사가 로그인하면** → 시스템이 자동으로 `tenant_id = 1`인 데이터만 보여줌 -**B회사가 로그인하면** → 시스템이 자동으로 `tenant_id = 2`인 데이터만 보여줌 - -> A회사는 B회사의 데이터를 절대 볼 수 없습니다. 시스템이 자동으로 차단합니다. - -### 6.3 options + tenant_id = 강력한 조합 - -이 두 가지가 합쳐지면: - -``` -같은 테이블, 같은 컬럼 구조인데 - ✅ 회사마다 다른 데이터 (tenant_id로 분리) - ✅ 회사마다 다른 속성 (options로 유연하게) - ✅ 시스템 수정 없이 확장 가능 -``` - ---- - -## 7. SAM 테이블의 표준 구조 - -SAM에서 새 테이블을 만들면 항상 이 구조를 따릅니다. - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ SAM 표준 테이블 구조 │ -│ │ -│ ① 식별자 │ -│ id — 자동 생성 번호 (1, 2, 3...) │ -│ tenant_id — 어느 회사의 데이터인지 │ -│ │ -│ ② 핵심 정보 (검색/정렬/연결에 쓰는 것만) │ -│ code — 코드 (중복 불가) │ -│ status — 상태 (검색용) │ -│ is_active — 사용 여부 │ -│ sort_order — 표시 순서 │ -│ (+ FK 컬럼들) — 다른 테이블 연결 │ -│ │ -│ ③ 메모칸 │ -│ options — 나머지 전부 (JSON) │ -│ │ -│ ④ 감사 기록 (자동) │ -│ created_by — 누가 만들었나 │ -│ updated_by — 누가 수정했나 │ -│ deleted_by — 누가 삭제했나 │ -│ created_at — 언제 만들었나 │ -│ updated_at — 언제 수정했나 │ -│ deleted_at — 언제 삭제했나 (휴지통 개념) │ -└─────────────────────────────────────────────────────────────────┘ -``` - -### 영역별 설명 - -| 영역 | 역할 | 비유 | -|------|------|------| -| ① 식별자 | "이 데이터가 누구 것인지" 구분 | 우편물의 받는 사람 + 주소 | -| ② 핵심 정보 | 검색, 정렬, 집계에 꼭 필요한 정보 | 엑셀의 고정 열 | -| ③ options | 회사마다 다른 부가 정보 | 엑셀의 "비고" 칸 (자유 서식) | -| ④ 감사 기록 | 언제 누가 뭘 했는지 자동 추적 | CCTV 기록 | - ---- - -## 8. 실제 SAM에서 options를 쓰는 테이블들 (22개) - -현재 SAM에서 options 메모칸을 사용하는 주요 테이블입니다. - -| 테이블 | 한글명 | options에 저장하는 정보 예시 | -|--------|--------|--------------------------| -| `orders` | 주문 | 배송지, 수신자, 연락처, 담당자 | -| `quotes` | 견적 | 견적 요약, 비용 항목, 가격 조정 | -| `receivings` | 입고 | 제조사, 검사 결과, 검사일 | -| `work_orders` | 작업지시 | 절곡 정보 (bending_info) | -| `work_order_items` | 작업지시 항목 | 작업 결과, 양품/불량 수량, LOT번호 | -| `processes` | 공정 | 작업일지 필요 여부, 검사 필요 여부 | -| `order_nodes` | 주문 노드 | 위치, 구역, 층, 실 (트리 구조) | -| `products` | 제품 | 동적 옵션 (라벨, 값, 단위) | -| `items` | 품목 | 품목별 동적 속성 | -| `materials` | 자재 | 자재 추가 속성 | -| `menus` | 메뉴 | 섹션, 메뉴 타입, 필요 권한 | -| `users` | 사용자 | 개인 설정/환경설정 | -| `tenants` | 회사(테넌트) | 회사 규모, 업종 | -| `document_template_section_fields` | 문서 양식 필드 | 선택지 목록, API 경로 | -| `item_fields` | 품목 필드 정의 | 필드별 세부 설정 | - ---- - -## 9. 자주 묻는 질문 (FAQ) - -### Q1. options에 넣으면 검색이 안 되나요? - -**아닙니다.** MySQL 8.0은 JSON 내부도 검색할 수 있습니다. - -``` -일반 컬럼 검색: "상태가 '완료'인 주문 찾아줘" → 매우 빠름 -options 검색: "제조사가 '삼성'인 입고 찾아줘" → 가능하지만 조금 느림 -``` - -다만, **매일 수천 번 검색하는 정보**라면 일반 컬럼으로 승격하는 것이 맞습니다. -가끔 검색하는 정보라면 options로 충분합니다. - -### Q2. options에 아무 정보나 마음대로 넣을 수 있나요? - -기술적으로는 가능하지만, 개발팀 내부에서 **어떤 키를 쓸지 미리 약속**합니다. - -``` -✅ 약속된 키: {"manufacturer": "삼성", "inspection_status": "합격"} -❌ 멋대로: {"asdf": 123, "temp_data": "???"} -``` - -코드에서 상수로 정의하여 일관성을 유지합니다. - -### Q3. 전통적 방식보다 뭐가 좋은 건가요? - -| 비교 항목 | 전통적 방식 (열 추가) | SAM 방식 (options JSON) | -|----------|:------------------:|:---------------------:| -| 새 정보 추가 시 | 시스템 수정 필요 | 코드만 변경 | -| 다른 회사에 영향 | 있음 (전체 구조 변경) | 없음 | -| 빈칸(null) 낭비 | 많음 | 없음 | -| 검색 속도 | 빠름 | 조금 느림 (충분히 실용적) | -| 유연성 | 낮음 | 높음 | -| 시스템 중단 위험 | 있음 (대형 테이블 수정 시) | 없음 | - -### Q4. 그럼 모든 정보를 options에 넣으면 되지 않나요? - -**아닙니다.** 핵심 정보는 반드시 일반 컬럼으로 만들어야 합니다. - -``` -❌ 나쁜 예: 모든 것을 options에 - - id │ tenant_id │ options - ────────────────────────────────────────────────────────────── - 1 │ 1 │ {"주문번호":"ORD-001", "금액":500000, "상태":"완료", ...} - - → 주문번호 검색 느림, 금액 합계 계산 불가, 중복 방지 불가 -``` - -``` -✅ 좋은 예: 핵심은 컬럼, 부가는 options - - id │ tenant_id │ order_number │ amount │ status │ options - ────────────────────────────────────────────────────────────── - 1 │ 1 │ ORD-001 │ 500000 │ 완료 │ {"배송지":"서울..."} - - → 검색 빠름, 합계 가능, 중복 방지 가능, 부가 정보도 유연 -``` - -### Q5. options 데이터는 화면에서 어떻게 보이나요? - -사용자 화면에서는 options 안에 있는지, 일반 컬럼인지 **구분할 수 없습니다**. -프로그램이 자동으로 꺼내서 보여줍니다. - -``` -화면에 보이는 모습: - - ┌─────────────────────────────────┐ - │ 입고 상세 정보 │ - │ │ - │ 품목: SUS304 스틸 │ ← 일반 컬럼 - │ 수량: 100개 │ ← 일반 컬럼 - │ 입고일: 2026-03-01 │ ← 일반 컬럼 - │ 제조사: 삼성전자 │ ← options에서 꺼냄 - │ 검사결과: 합격 │ ← options에서 꺼냄 - │ 검사일: 2026-03-01 │ ← options에서 꺼냄 - └─────────────────────────────────┘ - - 사용자는 어디에 저장되어 있는지 알 필요 없음! -``` - ---- - -## 10. 한 장 요약 - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ │ -│ SAM 테이블 설계 = "핵심만 컬럼, 나머진 메모칸(options)" │ -│ │ -│ ┌──────────────────────────────────────────────────────────┐ │ -│ │ tenant_id → 어느 회사 것인지 (자동 격리) │ │ -│ │ 핵심 컬럼들 → 검색/정렬/연결/집계에 쓰는 필수 정보 │ │ -│ │ options → 나머지 전부 (회사마다 다른 부가 정보) │ │ -│ │ 감사 컬럼들 → 누가/언제 만들고/수정하고/삭제했는지 │ │ -│ └──────────────────────────────────────────────────────────┘ │ -│ │ -│ 이렇게 하면: │ -│ ✅ 회사 추가해도 테이블 구조 안 바꿈 │ -│ ✅ 새 정보 추가해도 시스템 수정 최소화 │ -│ ✅ 회사마다 다른 정보를 유연하게 저장 │ -│ ✅ 데이터 보안 (회사 간 완전 분리) │ -│ │ -└─────────────────────────────────────────────────────────────────┘ -``` - ---- - -## 관련 문서 - -| 문서 | 설명 | 대상 | -|------|------|------| -| [options-column-policy.md](../standards/options-column-policy.md) | 개발자용 상세 정책 (코드 규칙, 마이그레이션 패턴) | 개발자 | -| [database/README.md](../system/database/README.md) | DB 스키마 전체 현황 (220개 모델) | 개발자 | -| [PROJECT_DEVELOPMENT_POLICY.md](PROJECT_DEVELOPMENT_POLICY.md) | 개발 공통 정책 (테이블 생성 절차) | 개발자 | -| [system/overview.md](../system/overview.md) | SAM 시스템 전체 아키텍처 | 전체 | - ---- - -**최종 업데이트**: 2026-03-02 diff --git a/sam/docs/plans/SAM_General_Rule_Storyboard_D1.0.md b/sam/docs/plans/SAM_General_Rule_Storyboard_D1.0.md deleted file mode 100644 index ae23c7b..0000000 --- a/sam/docs/plans/SAM_General_Rule_Storyboard_D1.0.md +++ /dev/null @@ -1,737 +0,0 @@ -# SAM General Rule Storyboard D1.0 - -> **작성일**: 2026-01-16 -> **버전**: D1.0 -> **원본**: `SAM_General_Rule_Storyboard_D1.0_260116.pdf` (43페이지) -> **상태**: PC 섹션 정리 완료 - ---- - -## 1. 문서 이력 - -| 날짜 | 버전 | 주요 내용 | 세부 내용 | -|------|------|----------|----------| -| 2026-01-15 | D0.9 | 초안 | General Rule - PC, 태블릿, 모바일 UIUX 공통 작성 | -| 2026-01-16 | D1.0 | 작성 | PC 섹션 정리 33p | - ---- - -## 2. 인터랙션 (Interaction) - -> **페이지**: 4 - -사용자 입력 제스처 및 적용 여부를 정의한다. - -| Type | 제스처/마크 | 설명 | 적용 | -|------|-----------|------|------| -| Tap | 탭 | 일정영역을 사용자가 터치한다. | Yes | -| Touch & Hold | 터치 앤 홀드 | 화면을 터치한 후 계속 누르고 있는 상태. 해당영역 혹은 개체가 홀드된다. | No | -| Double Tap | 더블 탭 | 일정영역을 두 번 터치한다. 두 번 터치 시 액션이 실행된다. | No | -| Drag & Drop | 드래그 앤 드롭 | 터치 혹은 홀드 상태에서 오브젝트를 이동하여 원하는 위치에 배치시킨다. | Yes | -| Scroll Up | 스크롤 업 | 아래에서 위로 누르는 동작을 유지하면서 이동하였다가 뗀다. | Yes | -| Scroll Down | 스크롤 다운 | 위에서 아래로 누르는 동작을 유지하면서 이동하였다가 뗀다. | Yes | -| Swipe Left | 스와이프 레프트 | 오른쪽에서 왼쪽으로 누르는 동작을 유지하면서 이동하였다가 뗀다. | Yes | -| Swipe Right | 스와이프 라이트 | 왼쪽에서 오른쪽으로 누르는 동작을 유지하면서 이동하였다가 뗀다. | Yes | -| Pinch Zoom out | 핀치 줌 아웃 | 오브젝트 또는 화면을 축소한다. | Yes | -| Pinch Zoom in | 핀치 줌 인 | 오브젝트 혹은 화면을 확대한다. | Yes | - ---- - -## 3. 반응형 웹 (Responsive Web) - -> **페이지**: 5 - -### 3.1 브레이크 포인트 - -| 디바이스 | 브레이크 포인트 | Tailwind 접두사 | -|---------|---------------|----------------| -| 모바일 | < 640px | 기본 | -| 태블릿 | 768px ~ 1280px | `md` | -| 데스크탑 | 1280px+ | `lg` | -| 대형 모니터 | 1920px+ | `xl` | - -### 3.2 레이아웃 구성 - -**PC Web 레이아웃**: -1. Contents 영역 -2. Footer 영역 - -**Mobile Web 레이아웃**: -1. Contents 영역 -2. Footer 영역 - ---- - -## 4. 화면 템플릿 (Screen Template) - -> **페이지**: 6 - -모바일 웹 화면 구조를 정의한다. - -| 영역 | 코드 | 설명 | -|------|------|------| -| Status bar | A | 안테나, 통화, 배터리 등 시스템 OS 관리 영역. 모든 페이지 상단에 존재 | -| Browser 영역 | B | 브라우저 기능 영역 | -| Title 영역 | C | 텍스트 또는 기능 버튼으로 구현됨. 텍스트는 기본 가운데 정렬 | -| Content 영역 | D | 컨텐츠 내용 표시. 컨텐츠 길이가 길어질 경우 스크롤 제공 | -| Browser bar 영역 | E | 브라우저 유틸 바 영역 | -| Keypad 영역 | F | 키보드 입력할 때 활성화. 모든 페이지 위에 덮어쓰기 구현 | - ---- - -## 5. 메시지 (Notifications) - -> **페이지**: 7 - -| 유형 | 설명 | -|------|------| -| 알림 Alert | 사용자에게 상황을 알려주기 위한 팝업. `[확인]` 버튼 제공 | -| 확인 Alert | 사용자에게 확인이 필요할 경우 제공되는 팝업. `[취소]` `[확인]` 버튼 제공 | -| 토스트 메시지 | 단순 Notify. 2~3초 후 페이지 내에서 Fade out | - ---- - -## 6. GNB, LNB, 푸터 - -> **페이지**: 8 - -PC 화면의 전체 레이아웃 구조를 정의한다. - -### 6.1 구성 요소 - -| 번호 | 영역 | 설명 | -|------|------|------| -| 01 | 메뉴 버튼 | 클릭: 메뉴 영역(06) 축소/확장 토글. 디폴트: 메뉴 영역 확장 상태 | -| 02 | SAM 로고 버튼 | 클릭: 대시보드 화면으로 이동 | -| 03 | 알림 버튼 | 클릭: 알림 팝업 표시 | -| 04 | 개인 정보 버튼 | 항목: 디폴트 이미지, 이름, 직급. 클릭: 마이페이지 팝업 표시 | -| 05 | 회사 로고 | 회사정보 화면에서 등록한 로고 표시. 회사 변경 선택 시 해당 로고 변경 | -| 06 | 메뉴 영역 | 메뉴 클릭: 하위 메뉴 있을 경우 하단에 표시, 없을 경우 해당 메뉴 화면으로 이동. 목록 길 경우 해당 영역 내 스크롤 처리 | -| 07 | MES 메뉴 영역 | 영업관리, 판매관리, 구매관리 등 해당하는 MES 메뉴 영역 표시 | -| 08 | 푸터 영역 | 모든 화면 하단 공통 표시 | -| 09 | SAM AI 채팅 버튼 | 클릭: SAM AI 채팅 팝업 표시 | - -### 6.2 메뉴 목록 - -- 대시보드 -- MES 메뉴 -- 인사관리 -- 전자결재 -- 게시판 -- 회계관리 -- 기준정보 -- 보고서 및 분석 -- 계정정보 -- 회사정보 -- 구독관리 -- 결제내역 -- 고객센터 - -### 6.3 푸터 내용 - -``` -(C) 2025 SAM. All right reserved. -Codebridge X -상호: 코드 브릿지 엑스 대표: 이경호 사업자등록번호: 123-45-12345 -주소: 서울특별시 강서구 양천로 583 우림블루나인 B동 1602호 (우: 07547) -팩스: 02-123-1234 통신판매업신고번호: 제 2019-서울강서-0001호 -서비스이용문의: 02-1234-1234 이메일: cs@a.com -서비스 이용약관 | 개인정보 취급방침 -``` - ---- - -## 7. 메뉴, 페이지, 섹션, 항목 영역 - -> **페이지**: 9 - -### 7.1 영역 구분 - -| 번호 | 영역 | 설명 | -|------|------|------| -| 01 | 메뉴 영역 | 축소 상태 | -| 02 | 페이지 영역 | - | -| 03 | 섹션 영역 | - | -| 04 | 항목 영역 | - | - -### 7.2 텍스트 오버플로우 처리 - -텍스트가 영역보다 길 경우 "텍스트+..." 형태로 표시한다. - ---- - -## 8. 메뉴 목록 (3Depth) - -> **페이지**: 10 - -### 8.1 메뉴 계층 구조 - -| 번호 | 레벨 | 설명 | -|------|------|------| -| 01 | 대메뉴 | 1Depth 메뉴 | -| 02 | 중메뉴 | 2Depth 메뉴 (대메뉴 클릭 시 하단에 표시) | -| 03 | 소메뉴 | 3Depth 메뉴 (중메뉴 클릭 시 하단에 표시) | - -**메뉴 확장 예시**: -``` -대시보드 -MES 메뉴 -인사관리 -전자결재 - - 중메뉴명 - - 중메뉴명 - · 소메뉴명 - · 소메뉴명 - - 중메뉴명 - - 중메뉴명 - - 중메뉴명 -게시판 -... -``` - ---- - -## 9. 알림 팝업 - -> **페이지**: 11 -> **경로**: 메인 > 알림 팝업 - -### 9.1 구성 요소 - -| 번호 | 항목 | 설명 | -|------|------|------| -| 01 | 알림 목록 | 각 디폴트 썸네일, 종류(공지사항, 안내), 제목/내용, 전송일시 표시. 클릭: 해당 상세 화면으로 이동. 최신순 10개까지 표시 | -| 02 | New 아이콘 | 새 알림일 경우 New 아이콘 표시. 해당 알림 클릭 시 사라짐 | -| 02-1 | 붉은 점 아이콘 | 새 알림이 있을 경우 표시. 해당 알림 모두 클릭 시 사라짐 | - ---- - -## 10. 마이페이지 팝업 - -> **페이지**: 12 -> **경로**: 메인 > 마이페이지 팝업 - -### 10.1 구성 요소 - -| 번호 | 항목 | 설명 | -|------|------|------| -| 01 | 계정 아이디 (이메일) | 이메일 주소 표시 (예: `name@company.com`) | -| 02 | 회사 셀렉트 박스 | 종류: 회사명 목록 (해당 계정이 생성한 회사(테넌트) 목록 표시). 정렬: 등록순. 한 회사만 소유중일 경우에는 해당 영역 숨김 | -| 03 | 로그아웃 버튼 | 클릭: "정말 로그아웃하시겠습니까?" 로그아웃 확인 Alert 표시. 확인 버튼 클릭시 로그아웃 처리 | - ---- - -## 11. 셀렉트 박스 - -> **페이지**: 13 - -### 11.1 기본 셀렉트 박스 - -| 번호 | 항목 | 설명 | -|------|------|------| -| 01 | 셀렉트 박스 | 클릭: 하단에 종류 목록 표시 | -| 02 | 종류 목록 | 목록 중 하나만 선택 가능 | - -### 11.2 다중 선택 셀렉트 박스 - -| 번호 | 항목 | 설명 | -|------|------|------| -| 03 | 다중 선택 셀렉트 박스 | 선택된 첫번째 항목명 + 추가 수 표시. 텍스트 영역 부족할 경우 `항목..+3` 형태로 표시 | -| 04 | 다중 선택 종류 목록 | 목록 중 복수 선택 가능. 전체 선택 시 전체 선택/해제 토글 | - -### 11.3 검색 셀렉트 박스 - -| 번호 | 항목 | 설명 | -|------|------|------| -| 05 | 검색 영역 | 검색어 입력 후 엔터 또는 검색 아이콘 클릭 시 검색 상태로 전환되며 검색 결과 표시 | -| 05-3 | 삭제 버튼 | 클릭: 검색어 삭제 처리, 전체 종류 목록 표시 | - -### 11.4 셀렉트 박스 유형 정리 - -| 유형 | 단일 선택 | 다중 선택 | 검색 | 검색+다중 선택 | -|------|----------|----------|------|--------------| -| 선택 방식 | 하나만 | 복수 | 하나만 | 복수 | -| 검색 기능 | X | X | O | O | -| 전체 선택 | X | O | X | O | - ---- - -## 12. 가이드 메시지 - -> **페이지**: 14 - -상황에 따라 입력 필드 하단 또는 Alert에 가이드 메시지를 표시한다. - -### 12.1 표시 규칙 - -| 번호 | 항목 | 설명 | -|------|------|------| -| 01 | 가이드 메시지 표시 위치 | 입력 필드 하단에 표시 | -| - | 긍정 메시지 | 녹색으로 표시 | -| 01-1 | 부정 메시지 | 붉은색으로 표시 | - ---- - -## 13. 태블릿/모바일 헤더 - -> **페이지**: 15 - -### 13.1 동작 규칙 - -| 번호 | 항목 | 설명 | -|------|------|------| -| 01 | 태블릿/모바일 헤더 | 하단으로 스크롤 시 숨김. 역스크롤 시 표시 | - -### 13.2 적용 화면 - -- TABLET 가로 목록 -- TABLET 세로 목록 -- MOBILE 가로 목록 -- MOBILE 세로 목록 - ---- - -## 14. 태블릿/모바일 바텀 버튼 영역 - -> **페이지**: 16 - -### 14.1 동작 규칙 - -| 번호 | 항목 | 설명 | -|------|------|------| -| 01 | 태블릿/모바일 바텀 버튼 영역 | 최하단 바텀에 플로팅 표시. 하단으로 스크롤 시 숨김. 역스크롤 시 표시 | - -### 14.2 버튼 예시 - -- `[수정]` `[삭제]` - ---- - -## 15. 공지 팝업 - -> **페이지**: 17 - -### 15.1 구성 - -| 항목 | 설명 | -|------|------| -| 대상 | 전체, 설정 부서 | -| 내용 | 설정 기간동안 대상에게 팝업 표시 | - -### 15.2 구성 요소 - -| 번호 | 항목 | 설명 | -|------|------|------| -| 01 | 팝업 내용 영역 | 이미지, 텍스트 | -| 02 | 1일간 이 창을 열지 않음 체크박스 | 클릭: 체크 설정/해제 토글. 디폴트: 체크 해제 상태. 체크 설정 시 1일 동안 팝업 미표시 (자정 기준) | - ---- - -## 16. 목록 화면 - 4단계 반응형 - -> **페이지**: 18~25 - -PC, TABLET, MOBILE 환경에서 목록 화면의 4단계 반응형 표시를 정의한다. - -### 16.1 반응형 단계 개요 - -| 단계 | 디바이스 | 화면명 | -|------|---------|--------| -| 1단계 | PC | PC_목록 | -| 2단계 | TABLET 가로 | TABLET_가로_목록 | -| 3단계 | TABLET 세로 / MOBILE 가로 | TABLET_세로_목록, MOBILE_가로_목록 | -| 4단계 | MOBILE 세로 | MOBILE_세로_목록 | - -### 16.2 PC_목록 (1단계) - -> **페이지**: 19 - -| 번호 | 항목 | 설명 | -|------|------|------| -| 01 | 헤더 영역 | 항목 클릭: 값이 국문/영문/숫자일 경우 오름/내림차순으로 토글 | -| 02 | 정렬 아이콘 | 현재 칼럼으로 정렬 상태일 경우에만 표시 | - -**목록 테이블 예시 칼럼**: - -| 칼럼 | 설명 | -|------|------| -| 시공번호 | 고유 식별 번호 | -| 거래처 | 회사명 | -| 현장명 | 현장 이름 | -| 공사PM | 담당 PM | -| 작업반장 | 작업반장 이름 | -| 작업자 | 작업자 수 | -| 시공투입일 | 시공 투입 날짜 | -| 시공완료일 | 시공 완료 날짜 | -| 상태 | 시공대기, 시공진행, 시공완료 | - -### 16.3 TABLET_가로_목록 (2단계) - -> **페이지**: 20 - -- PC와 동일한 테이블 구조 -- 사이드 메뉴가 아이콘 축소 상태로 변경 - -### 16.4 TABLET_세로_목록 (3단계) - -> **페이지**: 21~22 - -- 테이블 대신 카드형 목록으로 전환 -- 각 카드에 시공번호와 상태 표시 -- 카드 클릭 시 확장되어 상세 정보 표시 - -**확장 시 표시 항목**: - -| 필드 | 예시 값 | -|------|---------| -| 거래처 | 회사명 | -| 현장명 | 현장명 | -| 공사PM | 홍길동 | -| 작업반장 | 홍길동 | -| 작업자 | 3 | -| 시공투입일 | 2026-01-01 | -| 시공완료일 | 2026-01-01 | - -### 16.5 MOBILE_가로_목록 (3단계) - -> **페이지**: 23~24 - -- 카드형 목록 -- 시공번호와 상태 표시 -- 클릭 시 확장하여 상세 항목 표시 - -### 16.6 MOBILE_세로_목록 (4단계) - -> **페이지**: 25 - -- 카드형 목록 (세로 스크롤) -- 클릭 시 확장하여 상세 항목 표시 -- 확장 시 거래처, 현장명, 공사PM, 작업반장, 작업자, 시공투입일, 시공완료일 표시 - ---- - -## 17. 상세 화면 - 4단계 반응형 - -> **페이지**: 26~31 - -PC, TABLET, MOBILE 환경에서 상세 화면의 4단계 반응형 표시를 정의한다. - -### 17.1 반응형 단계 개요 - -| 단계 | 디바이스 | 화면명 | -|------|---------|--------| -| 1단계 | PC | PC_상세 | -| 2단계 | TABLET 가로 | TABLET_가로_상세 | -| 3단계 | TABLET 세로 / MOBILE 가로 | TABLET_세로_상세, MOBILE_가로_상세 | -| 4단계 | MOBILE 세로 | MOBILE_세로_상세 | - -### 17.2 PC_상세 (1단계) - -> **페이지**: 27 - -- 페이지 제목: "메뉴 상세" + 설명: "메뉴 상세를 관리합니다" -- 섹션명: "시공 정보" -- 버튼: `[수정]` `[삭제]` - -**표시 항목 예시**: - -| 필드 | 예시 값 | -|------|---------| -| 시공번호 | 123123 | -| 상태 | 시공진행 | -| 현장 | 현장명 | -| 작업반장 | 홍길동 (셀렉트 박스) | -| 시공투입일 | 2025-12-15 | -| 시공완료일 | 2025-12-15 | -| 항목명 | 항목 (다수) | - -### 17.3 TABLET_가로_상세 (2단계) - -> **페이지**: 28 - -- PC와 동일한 상세 정보 표시 -- 사이드 메뉴 아이콘 축소 상태 - -### 17.4 TABLET_세로_상세 (3단계) - -> **페이지**: 29 - -- 항목 수가 줄어들며 스크롤로 나머지 확인 - -### 17.5 MOBILE_가로_상세 (3단계) - -> **페이지**: 30 - -- 상세 항목을 세로 배치 -- 바텀에 `[수정]` `[삭제]` 버튼 플로팅 - -### 17.6 MOBILE_세로_상세 (4단계) - -> **페이지**: 31 - -- 모든 항목 세로 배치 -- 바텀에 `[수정]` `[삭제]` 버튼 플로팅 - ---- - -## 18. PC 섹션 정리 - -> **페이지**: 32~33 - -PC 화면의 섹션 레이아웃 및 필터/정렬 구성을 정의한다. - -### 18.1 필터 규칙 - -| 번호 | 항목 | 설명 | -|------|------|------| -| 01 | 라디오 버튼형 필터 | 선택 값이 2개일 경우 사용 (예: 수취/발행) | -| 02 | 필터 셀렉트 박스 | 최소로만 활용 | -| 03 | 표 헤더 정렬 | 표 헤더 정렬로 정렬 셀렉트 박스는 삭제 | - -### 18.2 PC 섹션 구성 요소 - -**상단 영역**: -- 페이지 제목 + 설명 -- 집계 카드 (예: `수취어음 55건`, `발행어음 1건`, `만기임박 5건`, `결제완료 15건`) -- 기간 선택 (날짜 범위 + 단축 버튼: 전전월, 어제, 오늘, 전월, 당월, 당해년도) -- 버튼: `[버튼명]` `[버튼명]` `[버튼명]` -- 탭: 탭1, 탭2, 탭3 - -**필터 영역**: -- 셀렉트 박스 필터 (전체) -- 라디오 버튼형 필터 (수취/발행) -- 상태 셀렉트 박스 (보관중) -- `[저장]` 버튼 - -**목록 테이블 예시**: - -| No. | 어음번호 | 구분 | 거래처 | 금액 | 발행일 | 만기일 | 차수 | 상태 | -|-----|---------|------|--------|------|--------|--------|------|------| -| 7 | 123123 | 수취 | 회사명 | 1,000,000 | 2025-12-12 | 2025-12-12 | 1 | 보관중 | -| 6 | 123123 | 수취 | 회사명 | 1,000,000 | 2025-12-12 | 2025-12-12 | 2 | 만기임박 | - -**하단 정보**: `총 7건` / `1건 선택` - ---- - -## 19. TBD (미정) - -> **페이지**: 34 - -추후 결정 예정 영역이다. - ---- - -## 20. 나의 메뉴 - -> **페이지**: 35~38 - -### 20.1 나의 메뉴 - 없음 - -> **페이지**: 35 - -- 나의 메뉴가 설정되지 않은 상태 -- 콘텐츠 상단에 `[...]` 아이콘만 표시 - -### 20.2 나의 메뉴 - 있음 - -> **페이지**: 36 - -- 나의 메뉴가 1개 설정된 상태 -- 콘텐츠 상단에 나의 메뉴명 탭 표시 (예: `메뉴관리`) - -### 20.3 나의 메뉴 - 여러 줄 - -> **페이지**: 37 - -- 나의 메뉴가 여러 개 설정된 상태 -- 콘텐츠 상단에 여러 메뉴명이 나열됨 -- 줄바꿈되어 여러 줄로 표시 가능 (예: `메뉴관리 메뉴명 메뉴명 메뉴명 ...`) - -### 20.4 나의 메뉴 - 메뉴 영역에 통합 - -> **페이지**: 38 - -- 좌측 메뉴 영역에 "메뉴" / "나의 메뉴" 탭으로 통합 -- 메뉴 탭: 일반 메뉴 목록 표시 -- 나의 메뉴 탭: 사용자 즐겨찾기 메뉴 표시 - ---- - -## 21. 검색, 필터, 정렬 모음 - -> **페이지**: 39 - -### 21.1 구성 요소 - -| 영역 | 구성 | -|------|------| -| 기간 선택 | 날짜 범위 (`2025-09-01 ~ 2025-09-03`) + 단축 버튼 (전전월, 어제, 오늘, 전월, 당월, 당해년도) | -| 검색바 | 검색 입력 필드 | -| 필터 셀렉트 박스 | 복수의 전체 셀렉트 박스 | -| 정렬 | 최신순 셀렉트 박스 | -| 항목 필터 | 항목명 태그 형태로 나열 | - ---- - -## 22. 페이지 설정 버튼 - -> **페이지**: 40 - -### 22.1 기능 - -| 번호 | 항목 | 설명 | -|------|------|------| -| 01 | 섹션 표시 및 순서 변경 | 페이지 내 섹션 ON/OFF 토글 및 순서 변경 | -| 02 | 일반 설정 | 일반 설정 > 페이지/섹션 설정 > 공통 요소 모두 제어 | - -### 22.2 설정 패널 구성 - -- 버전기록 -- 가져오기 -- 내보내기 -- 섹션 목록: 각 섹션별 ON/OFF 토글 - -**예시**: -``` -섹션명 [ON] -섹션명 [ON] -섹션명 [ON] -섹션명 [ON] -섹션명 [ON] -``` - ---- - -## 23. 섹션 설정 버튼 - -> **페이지**: 41 - -### 23.1 기능 - -| 번호 | 항목 | 설명 | -|------|------|------| -| 01 | 항목 표시 및 순서 변경 | 섹션 내 항목 ON/OFF 토글 및 순서 변경 | -| 02 | 일반 설정 | 일반 설정 > 페이지/섹션 설정 > 공통 요소 모두 제어 | - -### 23.2 설정 패널 구성 - -- 가져오기 -- 내보내기 -- 항목 목록: 각 항목별 ON/OFF 토글 - -**예시**: -``` -기간 [ON] -기간단축버튼 [ON] -검색바 [ON] -필터명 [ON] -필터명 [ON] -필터명 [ON] -필터명 [ON] -정렬 [ON] -``` - ---- - -## 24. 태스크 알림 아이콘 - -> **페이지**: 42~43 - -### 24.1 동작 규칙 - -| 번호 | 항목 | 설명 | -|------|------|------| -| 01 | 태스크 알림 아이콘 | 태스크가 추가될 경우 카운트하여 표시 | -| - | 메뉴 확장 시 표시 | 대/중/소메뉴로 확장될 경우 해당 메뉴에 아이콘 표시 | -| - | 카운트 범위 | 최소 1 ~ 최대 99 | - -### 24.2 표시 예시 - -**축소 상태**: 대메뉴 옆에 카운트 배지 표시 (예: `전자결재 [3]`) - -**확장 상태 (2Depth)**: -``` -전자결재 [3] - - 중메뉴명 [2] - - 중메뉴명 [1] - - 중메뉴명 - - 중메뉴명 - - 중메뉴명 -``` - -**확장 상태 (3Depth)**: -``` -전자결재 [3] - - 중메뉴명 - - 중메뉴명 [1] - · 소메뉴명 [1] - · 소메뉴명 - - 중메뉴명 - - 중메뉴명 - - 중메뉴명 -``` - -### 24.3 페이지 내 표시 - -- 메뉴 축소 상태에서도 대메뉴 아이콘 옆에 카운트 배지 표시 - ---- - -## 부록: 페이지 맵 - -| 페이지 | 섹션 | 화면명 | -|--------|------|--------| -| 1 | 표지 | SAM_General Rule | -| 2 | 문서 이력 | Document History | -| 3 | 공통 | - | -| 4 | 인터랙션 | Interaction | -| 5 | 반응형 웹 | Responsive Web | -| 6 | 화면 템플릿 | Screen Template | -| 7 | 메시지 | Notifications | -| 8 | GNB, LNB, 푸터 | GNB, LNB, 푸터 | -| 9 | 영역 구분 | 메뉴, 페이지, 섹션, 항목 영역 | -| 10 | 메뉴 목록 | 메뉴 목록 3Depth | -| 11 | 알림 팝업 | 알림 팝업 | -| 12 | 마이페이지 | 마이페이지 팝업 | -| 13 | 셀렉트 박스 | 셀렉트 박스 (기본/다중/검색) | -| 14 | 가이드 메시지 | 가이드 메시지 | -| 15 | 태블릿/모바일 헤더 | 태블릿/모바일 헤더 | -| 16 | 태블릿/모바일 바텀 버튼 | 태블릿/모바일 바텀 버튼 영역 | -| 17 | 공지 팝업 | 공지 팝업 | -| 18 | (구분) | PC, TABLET, MOBILE - 목록 4단계 | -| 19 | 목록 1단계 | PC_목록 | -| 20 | 목록 2단계 | TABLET_가로_목록 | -| 21 | 목록 3단계 | TABLET_세로_목록 | -| 22 | 목록 3단계 확장 | TABLET_세로_목록_확장 | -| 23 | 목록 3단계 | MOBILE_가로_목록 | -| 24 | 목록 3단계 확장 | MOBILE_가로_목록_확장 | -| 25 | 목록 4단계 | MOBILE_세로_목록, MOBILE_세로_목록_확장 | -| 26 | (구분) | PC, TABLET, MOBILE - 상세 4단계 | -| 27 | 상세 1단계 | PC_상세 | -| 28 | 상세 2단계 | TABLET_가로_상세 | -| 29 | 상세 3단계 | TABLET_세로_상세 | -| 30 | 상세 3단계 | MOBILE_가로_상세 | -| 31 | 상세 4단계 | MOBILE_세로_상세 | -| 32 | (구분) | 섹션 정리 | -| 33 | 섹션 정리 | PC 섹션 정리 | -| 34 | TBD | 미정 | -| 35 | 나의 메뉴 | 나의 메뉴_없음 | -| 36 | 나의 메뉴 | 나의 메뉴_있음 | -| 37 | 나의 메뉴 | 나의 메뉴_여러 줄 | -| 38 | 나의 메뉴 | 나의 메뉴_메뉴 영역에 통합 | -| 39 | 검색/필터/정렬 | 검색, 필터, 정렬 모음 | -| 40 | 페이지 설정 | 페이지 설정 버튼 | -| 41 | 섹션 설정 | 섹션 설정 버튼 | -| 42~43 | 태스크 알림 | 태스크 알림 아이콘 | - ---- - -## 관련 문서 - -- [SAM ERP 회계관리 스토리보드 D1.6](SAM_ERP_회계관리_Storyboard_D1.6.md) -- 원본 PDF: `SAM_General_Rule_Storyboard_D1.0_260116.pdf` - ---- - -**최종 업데이트**: 2026-02-23 diff --git a/sam/docs/plans/ai-quotation-engine-plan.md b/sam/docs/plans/ai-quotation-engine-plan.md deleted file mode 100644 index c1b5098..0000000 --- a/sam/docs/plans/ai-quotation-engine-plan.md +++ /dev/null @@ -1,928 +0,0 @@ -# AI 견적서 자동생성 엔진 개발 계획 - -> **작성일**: 2026-03-02 -> **상태**: 기획 초안 -> **프로젝트**: SAM API + MNG -> **우선순위**: 🔴 필수 -> **참조**: `docs/features/ai/README.md`, `docs/features/quotes/README.md`, `docs/rules/customer-pricing.md` - ---- - -## 1. 개요 - -### 1.1 목적 - -SAM 계약 완료 후 매니저가 고객사 직원과 인터뷰를 진행할 때, **인터뷰 내용을 AI가 분석하여 SAM 표준 견적서 형태로 자동 변환**하는 엔진을 구축한다. - -현재 매니저가 수동으로 수행하는 프로세스: - -``` -┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ -│ SAM 계약 │ → │ 현장 인터뷰 │ → │ 업무 파악 │ → │ 견적서 작성 │ -│ 완료 │ │ (매니저+직원)│ │ (수동 정리) │ │ (수동 작성) │ -└──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ -``` - -AI 엔진 도입 후: - -``` -┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ ┌──────────────┐ -│ SAM 계약 │ → │ 현장 인터뷰 │ → │ AI 엔진 │ → │ 견적서 초안 │ -│ 완료 │ │ (매니저+직원)│ │ (음성/텍스트 분석) │ │ (자동 생성) │ -│ │ │ │ │ (업무 매핑) │ │ (매니저 확인)│ -└──────────────┘ └──────────────┘ └──────────────────────┘ └──────────────┘ -``` - -### 1.2 핵심 원칙 - -| 원칙 | 설명 | -|------|------| -| **자체 AI 엔진** | Claude API 기반으로 SAM 전용 AI 서비스 구축 | -| **기존 인프라 활용** | `ai_configs`, `ai_token_usages`, `ai_pricing_configs` 테이블 재사용 | -| **견적 시스템 연동** | 기존 `quotes`, `quote_items` 테이블과 직접 연동 | -| **Multi-tenant** | 모든 데이터에 `tenant_id` 격리 적용 | -| **점진적 확장** | Phase 1 텍스트 → Phase 2 음성 (STT 구현 완료, 통합만 필요) → Phase 3 학습 고도화 | - -### 1.3 기존 인프라 현황 - -#### AI 인프라 (구축 완료) - -| 구성요소 | 상태 | 비고 | -|---------|------|------| -| `ai_configs` 테이블 | ✅ 완료 | Claude provider 설정 가능 | -| `ai_token_usages` 테이블 | ✅ 완료 | 토큰/비용 자동 추적 | -| `ai_pricing_configs` 테이블 | ✅ 완료 | Claude 모델 단가 등록 | -| `AiTokenHelper` | ✅ 완료 | `saveClaudeUsage()` 메서드 존재 | -| MNG AI 설정 UI | ✅ 완료 | `/system/ai-config` | - -#### 견적 시스템 (구축 완료) - -| 구성요소 | 상태 | 비고 | -|---------|------|------| -| `quotes` 테이블 | ✅ 완료 | 견적 마스터 | -| `quote_items` 테이블 | ✅ 완료 | 견적 품목 상세 | -| `QuoteService` | ✅ 완료 | 견적 CRUD, 상태 관리 | -| `QuoteCalculationService` | ✅ 완료 | BOM 10단계 계산 | -| 견적 API 엔드포인트 | ✅ 완료 | REST API 전체 | - -#### 음성 녹음/STT (구축 완료) - -| 구성요소 | 상태 | 비고 | -|---------|------|------| -| `ai_voice_recordings` 테이블 | ✅ 완료 | DB 스키마 + CRUD | -| GCS 업로드 | ✅ 완료 | `GoogleCloudService` — GCS 저장/조회/삭제 | -| Google Cloud STT 변환 | ✅ 완료 | `GoogleCloudService::speechToText()` — LongRunningRecognize, ko-KR | -| Web Speech API (브라우저 STT) | ✅ 완료 | `voice-recorder.blade.php` — 실시간 음성→텍스트 (무료) | -| STT + Gemini AI 분석 | ✅ 완료 | `AiVoiceRecordingService` — 음성→STT→AI 분석 파이프라인 | -| 화자 분리 (Diarization) | ✅ 완료 | `MeetingMinuteService` — Speaker Diarization | -| 영업 상담 음성 녹음 | ✅ 완료 | `ConsultationController` — MediaRecorder + STT + GCS 백업 | - -> **참조 구현 파일:** -> - `mng/app/Services/GoogleCloudService.php` — Google Cloud STT/GCS 통합 서비스 -> - `mng/app/Services/AiVoiceRecordingService.php` — STT + Gemini 분석 -> - `mng/app/Services/MeetingMinuteService.php` — 회의록 STT + 화자분리 -> - `mng/app/Http/Controllers/Sales/ConsultationController.php` — 영업 상담 음성 -> - `mng/resources/views/sales/modals/voice-recorder.blade.php` — 브라우저 음성 녹음 UI -> - `docs/features/voice-input-stt-guide.md` — STT 기술 가이드 - ---- - -## 📍 현재 진행 상태 - -| 항목 | 내용 | -|------|------| -| **마지막 완료 작업** | 기획 초안 작성 | -| **다음 작업** | Phase 1 상세 설계 → 구현 | -| **진행률** | 0/4 Phase (0%) | -| **마지막 업데이트** | 2026-03-02 | - ---- - -## 2. 시스템 아키텍처 - -### 2.1 전체 구조 - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ SAM AI 견적 엔진 │ -├─────────────────────────────────────────────────────────────────┤ -│ │ -│ ┌───────────────┐ ┌───────────────────────┐ │ -│ │ 입력 채널 │ │ AI 분석 파이프라인 │ │ -│ │ │ │ │ │ -│ │ 📝 텍스트 │───→│ 1. 인터뷰 전처리 │ │ -│ │ 🎤 음성(P2) │ │ 2. 업무 도메인 분류 │ │ -│ │ 📄 문서(P3) │ │ 3. SAM 모듈 매핑 │ │ -│ └───────────────┘ │ 4. 견적 항목 추출 │ │ -│ │ 5. 금액 산출 │ │ -│ └──────────┬────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌───────────────────────────────────────────────┐ │ -│ │ 견적서 생성기 │ │ -│ │ │ │ -│ │ SAM 표준 모듈 카탈로그 ←──→ Claude API │ │ -│ │ 고객 요금 정책 ←──→ 프롬프트 엔진 │ │ -│ │ 기존 견적 템플릿 ←──→ 결과 파서 │ │ -│ └──────────────────────┬────────────────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌───────────────────────────────────────────────┐ │ -│ │ 출력 │ │ -│ │ │ │ -│ │ 📊 견적서 초안 (quotes 테이블) │ │ -│ │ 📋 업무 분석 리포트 │ │ -│ │ 💡 추천 모듈 목록 │ │ -│ └───────────────────────────────────────────────┘ │ -│ │ -└─────────────────────────────────────────────────────────────────┘ -``` - -### 2.2 Claude API 연동 구조 - -``` -┌──────────────────┐ ┌──────────────────┐ -│ SAM API Server │ │ Claude API │ -│ (Laravel) │ │ (Anthropic) │ -│ │ │ │ -│ AiQuotation │ ──HTTP──→ Messages API │ -│ Service │ ←─JSON── (claude-sonnet) │ -│ │ │ │ -│ ┌────────────┐ │ │ System Prompt: │ -│ │ Prompt │ │ │ - SAM 모듈 목록 │ -│ │ Engine │ │ │ - 요금 정책 │ -│ │ │ │ │ - 견적 구조 │ -│ │ - 모듈목록 │ │ │ - 출력 형식 │ -│ │ - 요금표 │ │ │ │ -│ │ - 템플릿 │ │ │ │ -│ └────────────┘ │ │ │ -└──────────────────┘ └──────────────────┘ -``` - -### 2.3 데이터 흐름 - -``` -매니저 인터뷰 입력 - │ - ▼ -┌──────────────────────────────────────────────────┐ -│ Step 1: 인터뷰 전처리 │ -│ - 텍스트 정규화 (불필요한 표현 제거) │ -│ - 핵심 키워드 추출 │ -│ - 업무 도메인 태깅 │ -└──────────────────────┬───────────────────────────┘ - ▼ -┌──────────────────────────────────────────────────┐ -│ Step 2: Claude API 1차 호출 — 업무 분석 │ -│ - 고객사 업종/규모 파악 │ -│ - 현재 업무 프로세스 분석 │ -│ - 디지털화 필요 영역 식별 │ -│ - Pain Point 도출 │ -│ 출력: 구조화된 업무 분석 JSON │ -└──────────────────────┬───────────────────────────┘ - ▼ -┌──────────────────────────────────────────────────┐ -│ Step 3: SAM 모듈 매핑 │ -│ - 업무 분석 결과 ↔ SAM 모듈 카탈로그 대조 │ -│ - 필수/선택 모듈 분류 │ -│ - 사용자 수, 데이터량 추정 │ -│ 출력: 추천 모듈 목록 + 근거 │ -└──────────────────────┬───────────────────────────┘ - ▼ -┌──────────────────────────────────────────────────┐ -│ Step 4: Claude API 2차 호출 — 견적 생성 │ -│ - SAM 요금 정책 적용 │ -│ - 모듈별 개발비 + 월 구독료 계산 │ -│ - 추가 옵션 (AI 토큰, 저장공간) 산출 │ -│ - 할인 정책 적용 (통합 패키지 등) │ -│ 출력: 견적서 JSON (SAM 표준 형식) │ -└──────────────────────┬───────────────────────────┘ - ▼ -┌──────────────────────────────────────────────────┐ -│ Step 5: 견적서 초안 저장 │ -│ - quotes 테이블에 저장 (status: draft) │ -│ - quote_items에 모듈별 항목 저장 │ -│ - 업무 분석 리포트 첨부 │ -│ - 매니저에게 알림 → 검토/수정 → 확정 │ -└──────────────────────────────────────────────────┘ -``` - ---- - -## 3. SAM 모듈 카탈로그 (AI 프롬프트용) - -> **참조**: `docs/rules/customer-pricing.md` - -AI가 인터뷰 내용을 SAM 견적으로 변환하려면, SAM이 제공하는 모듈과 요금을 정확히 알아야 한다. 이 데이터는 **DB 테이블로 관리**하여 프롬프트에 동적 주입한다. - -### 3.1 모듈 카탈로그 테이블 설계 - -```sql -CREATE TABLE ai_quotation_modules ( - id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, - tenant_id BIGINT UNSIGNED NOT NULL, - module_code VARCHAR(50) NOT NULL, -- 'HR', 'SALES', 'FINANCE' 등 - module_name VARCHAR(100) NOT NULL, -- '인사관리', '영업관리', '재무관리' - category ENUM('basic', 'individual', 'addon') NOT NULL, - description TEXT, -- 모듈 기능 설명 - keywords JSON, -- AI 매핑용 키워드 목록 - dev_cost DECIMAL(12,0) DEFAULT 0, -- 개발비 (원) - monthly_fee DECIMAL(10,0) DEFAULT 0, -- 월 구독료 (원) - is_active BOOLEAN DEFAULT TRUE, - sort_order INT DEFAULT 0, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - INDEX idx_tenant (tenant_id), - INDEX idx_category (category), - UNIQUE KEY uk_tenant_module (tenant_id, module_code) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -``` - -### 3.2 초기 데이터 (customer-pricing.md 기준) - -| module_code | module_name | category | dev_cost | monthly_fee | -|-------------|-------------|----------|----------|-------------| -| `BASIC_PKG` | 기본 패키지 (인사+근태+급여+게시판) | basic | 5,000,000 | 200,000 | -| `HR` | 인사관리 | individual | 2,000,000 | 80,000 | -| `ATTENDANCE` | 근태관리 | individual | 1,500,000 | 60,000 | -| `PAYROLL` | 급여관리 | individual | 2,500,000 | 100,000 | -| `BOARD` | 게시판/공지사항 | individual | 500,000 | 20,000 | -| `SALES` | 영업관리 (CRM+견적+수주) | individual | 5,000,000 | 150,000 | -| `PURCHASE` | 구매/자재관리 | individual | 3,000,000 | 100,000 | -| `PRODUCTION` | 생산관리 (MES) | individual | 8,000,000 | 250,000 | -| `QUALITY` | 품질관리 | individual | 4,000,000 | 120,000 | -| `FINANCE` | 재무/회계관리 | individual | 5,000,000 | 150,000 | -| `LOGISTICS` | 물류/출하관리 | individual | 3,000,000 | 100,000 | -| `APPROVAL` | 전자결재 | individual | 3,000,000 | 80,000 | -| `DOCUMENT` | 문서관리 (전자서명) | individual | 2,000,000 | 60,000 | -| `EQUIPMENT` | 설비관리 | individual | 3,000,000 | 100,000 | -| `INTEGRATED` | 통합 패키지 | basic | 30,000,000 | 800,000 | -| `AI_TOKEN` | AI 토큰 추가 | addon | 0 | 별도 | -| `STORAGE` | 파일 저장공간 추가 | addon | 0 | 별도 | -| `CUSTOM_DEV` | 커스텀 개발 | addon | 별도 협의 | 0 | - -### 3.3 keywords 필드 예시 - -```json -// HR 모듈 -{ - "keywords": ["직원", "사원", "인사", "조직도", "부서", "입퇴사", "인력"], - "pain_points": ["엑셀로 직원 관리", "입퇴사 관리가 번거로움", "조직도 없음"], - "business_needs": ["직원 정보 통합", "조직 구조 관리", "인력 현황 파악"] -} - -// PRODUCTION 모듈 -{ - "keywords": ["생산", "제조", "작업지시", "공정", "LOT", "불량", "MES"], - "pain_points": ["생산 현황을 수기로 기록", "불량 추적 불가", "납기 관리 어려움"], - "business_needs": ["실시간 생산현황", "불량률 관리", "작업지시 자동화"] -} -``` - ---- - -## 4. AI 프롬프트 엔진 - -### 4.1 시스템 프롬프트 구조 - -``` -┌─────────────────────────────────────────────────────┐ -│ System Prompt │ -├─────────────────────────────────────────────────────┤ -│ │ -│ [역할 정의] │ -│ 너는 SAM ERP/MES 솔루션의 컨설팅 AI이다. │ -│ 고객 인터뷰를 분석하여 맞춤형 견적서를 작성한다. │ -│ │ -│ [SAM 모듈 카탈로그] ← DB에서 동적 로드 │ -│ 각 모듈의 기능, 키워드, 가격 정보 │ -│ │ -│ [요금 정책] ← customer-pricing 기반 │ -│ 기본패키지, 개별모듈, 추가옵션 요금 체계 │ -│ 할인 정책 (통합 패키지 할인 등) │ -│ │ -│ [출력 형식] │ -│ JSON Schema 명시 (견적서 구조) │ -│ │ -│ [분석 지침] │ -│ - 고객 업종/규모별 권장 모듈 기준 │ -│ - 우선순위 결정 기준 (필수 vs 선택) │ -│ - 비용 최적화 원칙 (패키지 vs 개별) │ -│ │ -└─────────────────────────────────────────────────────┘ -``` - -### 4.2 프롬프트 템플릿 (1차: 업무 분석) - -``` -당신은 SAM(Smart Automation Management) ERP/MES 솔루션의 전문 컨설턴트입니다. - -아래는 고객사 직원과의 인터뷰 내용입니다. 이를 분석하여 구조화된 업무 분석 보고서를 작성하세요. - -## 고객 정보 -- 회사명: {company_name} -- 업종: {industry} -- 직원 수: {employee_count} -- 인터뷰 대상: {interviewee_role} - -## 인터뷰 내용 -{interview_content} - -## 분석 기준 -다음 SAM 모듈 영역에 맞춰 분석하세요: -{module_catalog_json} - -## 출력 형식 (JSON) -{ - "company_analysis": { - "industry": "업종 분류", - "scale": "소규모/중소/중견", - "current_systems": ["현재 사용 중인 시스템"], - "digitalization_level": "상/중/하" - }, - "business_domains": [ - { - "domain": "인사/급여", - "current_process": "현재 처리 방식 설명", - "pain_points": ["문제점 1", "문제점 2"], - "improvement_needs": ["개선 필요사항"], - "priority": "필수/높음/보통/낮음", - "matched_modules": ["HR", "PAYROLL"] - } - ], - "recommendations": { - "essential_modules": ["반드시 필요한 모듈 코드"], - "recommended_modules": ["권장 모듈 코드"], - "optional_modules": ["선택 모듈 코드"], - "package_suggestion": "BASIC_PKG 또는 INTEGRATED 또는 individual", - "reasoning": "패키지 추천 근거" - } -} -``` - -### 4.3 프롬프트 템플릿 (2차: 견적 생성) - -``` -아래 업무 분석 결과를 바탕으로 SAM 견적서를 생성하세요. - -## 업무 분석 결과 -{analysis_result_json} - -## SAM 요금 정책 -{pricing_policy_json} - -## 견적 생성 규칙 -1. 필수 모듈은 반드시 포함 -2. 통합 패키지가 개별 합산보다 저렴하면 패키지 추천 -3. 직원 수 기반 사용자 라이선스 산출 -4. AI 토큰은 월 기본 100만 토큰 포함, 초과분 별도 -5. 파일 저장공간은 기본 10GB, 초과분 별도 - -## 출력 형식 (JSON) -{ - "quotation": { - "title": "견적서 제목", - "client_name": "고객사명", - "valid_until": "견적 유효기간", - "items": [ - { - "category": "기본서비스/추가모듈/추가옵션", - "module_code": "모듈코드", - "module_name": "모듈명", - "description": "포함 기능 설명", - "dev_cost": 0, - "monthly_fee": 0, - "quantity": 1, - "note": "비고" - } - ], - "summary": { - "total_dev_cost": 0, - "total_monthly_fee": 0, - "discount_type": "패키지할인/볼륨할인/없음", - "discount_rate": 0, - "final_dev_cost": 0, - "final_monthly_fee": 0 - }, - "implementation_plan": { - "estimated_months": 0, - "phases": [ - { - "phase": 1, - "name": "단계명", - "modules": ["모듈코드"], - "duration_weeks": 0 - } - ] - }, - "analysis_summary": "업무 분석 요약 (고객 설명용)" - } -} -``` - ---- - -## 5. API 설계 - -### 5.1 엔드포인트 - -| Method | Path | 설명 | -|--------|------|------| -| `POST` | `/api/v1/ai/quotation/analyze` | 인터뷰 분석 (1차) | -| `POST` | `/api/v1/ai/quotation/generate` | 견적서 생성 (2차) | -| `POST` | `/api/v1/ai/quotation/generate-full` | 분석+생성 통합 (원스텝) | -| `GET` | `/api/v1/ai/quotation/{id}` | AI 견적 상세 조회 | -| `GET` | `/api/v1/ai/quotation` | AI 견적 목록 | -| `PUT` | `/api/v1/ai/quotation/{id}` | AI 견적 수정 (매니저) | -| `POST` | `/api/v1/ai/quotation/{id}/confirm` | 정식 견적으로 전환 | -| `DELETE` | `/api/v1/ai/quotation/{id}` | AI 견적 삭제 | - -### 5.2 요청/응답 예시 - -#### POST `/api/v1/ai/quotation/analyze` - -**Request:** -```json -{ - "client_id": 15, - "client_name": "(주)대한기계", - "industry": "기계제조업", - "employee_count": 45, - "interviewee_role": "관리부 팀장", - "interview_content": "현재 직원 관리는 엑셀로 하고 있어요. 출퇴근도 수기로 기록하고... 영업팀에서는 견적서를 한글 프로그램으로 만들어서 이메일로 보내는데, 이력 관리가 안 돼요. 생산 현장에서는 작업일보를 종이에 쓰고 있고, 불량이 나면 어디서 발생했는지 추적이 안 됩니다. 재고도 실사를 해봐야 알 수 있어요...", - "interview_type": "text" -} -``` - -**Response:** -```json -{ - "success": true, - "data": { - "id": 1, - "analysis": { - "company_analysis": { - "industry": "기계제조업", - "scale": "중소기업 (45명)", - "current_systems": ["엑셀", "한글 프로그램", "종이 문서"], - "digitalization_level": "하" - }, - "business_domains": [ - { - "domain": "인사/급여", - "current_process": "엑셀로 직원 관리, 수기 출퇴근 기록", - "pain_points": ["인사정보 분산", "출퇴근 수기 기록"], - "priority": "필수", - "matched_modules": ["HR", "ATTENDANCE", "PAYROLL"] - }, - { - "domain": "영업관리", - "current_process": "한글 프로그램 견적서, 이메일 발송", - "pain_points": ["견적 이력 관리 불가", "영업 현황 파악 어려움"], - "priority": "높음", - "matched_modules": ["SALES"] - }, - { - "domain": "생산관리", - "current_process": "종이 작업일보, 수동 불량 관리", - "pain_points": ["불량 추적 불가", "생산현황 실시간 파악 불가"], - "priority": "필수", - "matched_modules": ["PRODUCTION", "QUALITY"] - }, - { - "domain": "재고/물류", - "current_process": "실사로만 재고 파악", - "pain_points": ["실시간 재고 파악 불가"], - "priority": "높음", - "matched_modules": ["PURCHASE", "LOGISTICS"] - } - ], - "recommendations": { - "essential_modules": ["HR", "ATTENDANCE", "PAYROLL", "PRODUCTION", "QUALITY"], - "recommended_modules": ["SALES", "PURCHASE", "LOGISTICS"], - "optional_modules": ["APPROVAL", "DOCUMENT"], - "package_suggestion": "INTEGRATED", - "reasoning": "8개 이상 모듈이 필요하므로 통합 패키지(30,000,000원)가 개별 합산(34,500,000원)보다 경제적" - } - }, - "token_usage": { - "prompt_tokens": 1250, - "completion_tokens": 890, - "cost_krw": 45 - } - } -} -``` - -### 5.3 컨트롤러 / 서비스 구조 - -``` -app/Http/Controllers/Api/V1/ -└── AiQuotationController.php - ├── analyze() ← 인터뷰 분석 - ├── generate() ← 견적 생성 - ├── generateFull() ← 통합 (분석+생성) - ├── index() ← 목록 - ├── show() ← 상세 - ├── update() ← 수정 - ├── confirm() ← 정식 견적 전환 - └── destroy() ← 삭제 - -app/Services/ -└── AiQuotationService.php - ├── analyzeInterview() ← 1차: 인터뷰 분석 - ├── generateQuotation() ← 2차: 견적 생성 - ├── generateFull() ← 통합 처리 - ├── confirmToQuote() ← quotes 테이블로 전환 - │ - ├── buildAnalysisPrompt() ← 분석 프롬프트 조립 - ├── buildQuotationPrompt() ← 견적 프롬프트 조립 - ├── loadModuleCatalog() ← DB에서 모듈 카탈로그 로드 - ├── loadPricingPolicy() ← DB에서 요금 정책 로드 - ├── callClaudeApi() ← Claude API 호출 - ├── parseResponse() ← 응답 JSON 파싱 - └── saveTokenUsage() ← 토큰 사용량 기록 - -app/Http/Requests/V1/AiQuotation/ -├── AiQuotationAnalyzeRequest.php -├── AiQuotationGenerateRequest.php -├── AiQuotationUpdateRequest.php -└── AiQuotationConfirmRequest.php -``` - ---- - -## 6. 데이터베이스 설계 - -### 6.1 신규 테이블 - -#### ai_quotations (AI 견적 마스터) - -```sql -CREATE TABLE ai_quotations ( - id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, - tenant_id BIGINT UNSIGNED NOT NULL, - - -- 고객 정보 - client_id BIGINT UNSIGNED NULL, - client_name VARCHAR(200) NOT NULL, - industry VARCHAR(100) NULL, - employee_count INT NULL, - interviewee_role VARCHAR(100) NULL, - - -- 인터뷰 데이터 - interview_content TEXT NOT NULL, - interview_type ENUM('text', 'voice', 'document') DEFAULT 'text', - voice_recording_id BIGINT UNSIGNED NULL, -- ai_voice_recordings 참조 - - -- AI 분석 결과 - analysis_result JSON NULL, -- 1차 분석 결과 - quotation_result JSON NULL, -- 2차 견적 결과 - - -- 상태 관리 - status ENUM('analyzing', 'analyzed', 'generating', 'generated', - 'confirmed', 'failed') DEFAULT 'analyzing', - error_message TEXT NULL, - - -- 연결 - quote_id BIGINT UNSIGNED NULL, -- 정식 견적 전환 시 quotes.id - - -- 금액 요약 - total_dev_cost DECIMAL(12,0) DEFAULT 0, - total_monthly_fee DECIMAL(10,0) DEFAULT 0, - discount_rate DECIMAL(5,2) DEFAULT 0, - final_dev_cost DECIMAL(12,0) DEFAULT 0, - final_monthly_fee DECIMAL(10,0) DEFAULT 0, - - -- 토큰 사용 - total_tokens INT DEFAULT 0, - total_cost_krw DECIMAL(12,2) DEFAULT 0, - - -- 감사 - created_by BIGINT UNSIGNED NULL, - updated_by BIGINT UNSIGNED NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - deleted_at TIMESTAMP NULL, - - INDEX idx_tenant_status (tenant_id, status), - INDEX idx_tenant_client (tenant_id, client_id), - INDEX idx_created (created_at) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -``` - -#### ai_quotation_items (AI 견적 항목) - -```sql -CREATE TABLE ai_quotation_items ( - id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, - ai_quotation_id BIGINT UNSIGNED NOT NULL, - - category ENUM('basic', 'module', 'addon') NOT NULL, - module_code VARCHAR(50) NOT NULL, - module_name VARCHAR(100) NOT NULL, - description TEXT NULL, - - dev_cost DECIMAL(12,0) DEFAULT 0, - monthly_fee DECIMAL(10,0) DEFAULT 0, - quantity INT DEFAULT 1, - priority ENUM('essential', 'recommended', 'optional') DEFAULT 'recommended', - - ai_reasoning TEXT NULL, -- AI가 이 모듈을 추천한 근거 - matched_pain_points JSON NULL, -- 매칭된 고객 Pain Point - - sort_order INT DEFAULT 0, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - - INDEX idx_quotation (ai_quotation_id), - FOREIGN KEY (ai_quotation_id) REFERENCES ai_quotations(id) ON DELETE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -``` - -### 6.2 기존 테이블 활용 - -| 테이블 | 용도 | 연동 방식 | -|--------|------|----------| -| `ai_configs` | Claude API 키/모델 설정 | provider='claude' 조회 | -| `ai_token_usages` | 토큰 비용 추적 | menu_name='AI견적' | -| `ai_pricing_configs` | Claude 모델 단가 | provider='claude' | -| `quotes` | 정식 견적 전환 대상 | `confirm` 시 생성 | -| `clients` | 고객사 정보 | client_id 참조 | - ---- - -## 7. Phase별 개발 계획 - -### Phase 1: 텍스트 인터뷰 → AI 견적 (MVP) - -> **목표**: 텍스트 인터뷰 입력 → Claude 분석 → 견적서 자동생성 -> **기간**: 2~3주 -> **우선순위**: 🔴 필수 - -| 단계 | 작업 | 프로젝트 | 상태 | -|------|------|---------|------| -| 1-1 | `ai_quotation_modules` 마이그레이션 + 시더 | API | ⏳ | -| 1-2 | `ai_quotations`, `ai_quotation_items` 마이그레이션 | API | ⏳ | -| 1-3 | 모델 생성 (`AiQuotation`, `AiQuotationItem`, `AiQuotationModule`) | API | ⏳ | -| 1-4 | `AiQuotationService` — Claude API 연동 | API | ⏳ | -| 1-5 | 프롬프트 엔진 구현 (분석 + 견적 템플릿) | API | ⏳ | -| 1-6 | `AiQuotationController` + FormRequest | API | ⏳ | -| 1-7 | API 라우트 등록 (`routes/api/v1/common.php`) | API | ⏳ | -| 1-8 | 정식 견적 전환 로직 (`confirmToQuote`) | API | ⏳ | -| 1-9 | MNG AI 견적 관리 화면 (목록/상세/수정) | MNG | ⏳ | -| 1-10 | 테스트 (인터뷰 샘플 3건 이상) | API | ⏳ | - -### Phase 2: 음성 인터뷰 연동 - -> **목표**: 현장에서 녹음한 음성 → STT 변환 → AI 분석 → 견적 생성 -> **기간**: 1주 (기존 STT 인프라 재사용으로 단축) -> **선행 조건**: Phase 1 완료 - -| 단계 | 작업 | 프로젝트 | 상태 | 비고 | -|------|------|---------|------|------| -| 2-1 | Google STT 서비스 구현 | MNG | ✅ 완료 | `GoogleCloudService::speechToText()` 재사용 | -| 2-2 | 음성 업로드 API (GCS 저장) | MNG | ✅ 완료 | `AiVoiceRecordingService`, `ConsultationController` 재사용 | -| 2-3 | STT → 텍스트 변환 파이프라인 | MNG | ✅ 완료 | LongRunningRecognize + 폴링 패턴 구현됨 | -| 2-4 | 음성 인터뷰 → AI 견적 통합 플로우 | API | ⏳ | 기존 STT 결과를 Claude 분석에 연결 | -| 2-5 | MNG 음성 녹음 업로드 UI | MNG | ✅ 완료 | `voice-recorder.blade.php` 재사용 가능 | - -> **핵심**: Google Cloud STT, GCS, 브라우저 음성 녹음 UI가 모두 구현 완료 상태. -> Phase 2에서는 기존 STT 결과를 AI 견적 파이프라인(Claude API)에 연결하는 **통합 플로우(2-4)만 신규 개발**하면 된다. - -### Phase 3: 학습 데이터 고도화 - -> **목표**: 과거 견적 데이터를 활용하여 AI 정확도 향상 -> **기간**: 2주 -> **선행 조건**: Phase 1 + 실제 사용 데이터 축적 - -| 단계 | 작업 | 프로젝트 | 상태 | -|------|------|---------|------| -| 3-1 | 과거 견적 데이터 → 프롬프트 Few-shot 예시 구성 | API | ⏳ | -| 3-2 | 확정된 AI 견적 → 학습 데이터 피드백 루프 | API | ⏳ | -| 3-3 | 업종별 견적 패턴 분석 → 추천 정확도 향상 | API | ⏳ | -| 3-4 | 프롬프트 A/B 테스트 프레임워크 | API | ⏳ | - -### Phase 4: 고객 셀프서비스 (확장) - -> **목표**: 고객이 직접 간단한 질문에 답변하면 견적 자동 생성 -> **기간**: 3주 -> **선행 조건**: Phase 1~3 안정화 - -| 단계 | 작업 | 프로젝트 | 상태 | -|------|------|---------|------| -| 4-1 | 고객용 인터뷰 설문 폼 설계 | React | ⏳ | -| 4-2 | 단계별 질문 → AI 분석 통합 | API + React | ⏳ | -| 4-3 | 견적서 미리보기 + PDF 다운로드 | React | ⏳ | -| 4-4 | 매니저 알림 → 후속 상담 연결 | API + MNG | ⏳ | - ---- - -## 8. Claude API 연동 상세 - -### 8.1 SDK 설치 - -```bash -# API 프로젝트에 Anthropic SDK 설치 -docker exec sam-api-1 composer require anthropic-ai/laravel -``` - -> **참고**: `anthropic-ai/laravel` 패키지는 Laravel용 공식 래퍼로, HTTP Client 기반으로 Claude API를 호출한다. 미출시/미지원 시 `GuzzleHttp`로 직접 HTTP 호출한다. - -### 8.2 Claude API 호출 패턴 - -```php -// app/Services/AiQuotationService.php - -class AiQuotationService -{ - private function callClaudeApi(string $systemPrompt, string $userMessage): array - { - // 1. ai_configs에서 Claude 설정 로드 - $config = AiConfig::where('provider', 'claude') - ->where('is_active', true) - ->first(); - - // 2. HTTP 호출 - $response = Http::withHeaders([ - 'x-api-key' => $config->api_key, - 'anthropic-version' => '2023-06-01', - 'content-type' => 'application/json', - ])->post($config->base_url . '/messages', [ - 'model' => $config->model, // claude-sonnet-4-20250514 - 'max_tokens' => 4096, - 'temperature' => 0.3, // 견적은 일관성 중요 - 'system' => $systemPrompt, - 'messages' => [ - ['role' => 'user', 'content' => $userMessage] - ], - ]); - - // 3. 토큰 사용량 기록 - $usage = $response->json('usage'); - AiTokenHelper::saveClaudeUsage( - tenantId: auth()->user()->tenant_id, - menuName: 'AI견적', - promptTokens: $usage['input_tokens'], - completionTokens: $usage['output_tokens'], - model: $config->model, - ); - - // 4. 응답 파싱 - $content = $response->json('content.0.text'); - return json_decode($content, true); - } -} -``` - -### 8.3 비용 예측 - -| 항목 | 토큰 | 비용 (USD) | 비용 (KRW) | -|------|------|-----------|------------| -| 1차 분석 프롬프트 (시스템+사용자) | ~2,000 입력 | $0.0005 | ~1원 | -| 1차 분석 응답 | ~1,500 출력 | $0.0019 | ~3원 | -| 2차 견적 프롬프트 | ~3,000 입력 | $0.0008 | ~1원 | -| 2차 견적 응답 | ~2,000 출력 | $0.0025 | ~4원 | -| **견적 1건 합계** | **~8,500** | **~$0.006** | **~9원** | - -> Claude Sonnet 기준. 1건당 약 **9원**으로 매우 경제적이다. - ---- - -## 9. MNG 관리 화면 - -### 9.1 화면 목록 - -| 화면 | URL | 설명 | -|------|-----|------| -| AI 견적 목록 | `/ai-quotation` | 생성된 AI 견적 목록 | -| AI 견적 생성 | `/ai-quotation/create` | 인터뷰 입력 폼 | -| AI 견적 상세 | `/ai-quotation/{id}` | 분석 결과 + 견적서 조회 | -| AI 견적 수정 | `/ai-quotation/{id}/edit` | 매니저가 수정 | -| 모듈 카탈로그 관리 | `/ai-quotation/modules` | SAM 모듈 목록 관리 | - -### 9.2 AI 견적 생성 화면 구성 - -``` -┌─────────────────────────────────────────────────────┐ -│ AI 견적서 생성 │ -├─────────────────────────────────────────────────────┤ -│ │ -│ [고객 정보] │ -│ ┌─────────────┐ ┌─────────────┐ │ -│ │ 고객사 선택 ▼│ │ 업종 │ │ -│ └─────────────┘ └─────────────┘ │ -│ ┌─────────────┐ ┌─────────────┐ │ -│ │ 직원 수 │ │ 인터뷰 대상 │ │ -│ └─────────────┘ └─────────────┘ │ -│ │ -│ [인터뷰 내용] │ -│ ┌─────────────────────────────────────────────┐ │ -│ │ │ │ -│ │ (텍스트 입력 또는 음성 녹음 업로드) │ │ -│ │ │ │ -│ │ │ │ -│ └─────────────────────────────────────────────┘ │ -│ │ -│ [🔄 분석 시작] [📊 분석+견적 한번에] │ -│ │ -├─────────────────────────────────────────────────────┤ -│ [분석 결과] (Ajax 응답) │ -│ │ -│ 📊 업무 도메인 분석 │ -│ ┌──────────┬──────────┬──────────┬──────────┐ │ -│ │ 도메인 │ 현재상태 │ 문제점 │ 추천모듈 │ │ -│ ├──────────┼──────────┼──────────┼──────────┤ │ -│ │ 인사/급여 │ 엑셀관리 │ 분산관리 │ HR,PAYROLL│ │ -│ │ 생산관리 │ 종이기록 │ 추적불가 │PRODUCTION │ │ -│ └──────────┴──────────┴──────────┴──────────┘ │ -│ │ -│ 💰 견적서 초안 │ -│ ┌──────────┬──────────┬──────────┬──────────┐ │ -│ │ 모듈 │ 개발비 │ 월구독료 │ 우선순위 │ │ -│ ├──────────┼──────────┼──────────┼──────────┤ │ -│ │ 통합패키지 │30,000,000│ 800,000 │ 필수 │ │ -│ │ AI토큰 │ 0│ 50,000 │ 선택 │ │ -│ └──────────┴──────────┴──────────┴──────────┘ │ -│ 합계: 개발비 30,000,000원 / 월 850,000원 │ -│ │ -│ [✅ 정식 견적으로 전환] [✏️ 수정] [🗑️ 삭제] │ -│ │ -└─────────────────────────────────────────────────────┘ -``` - ---- - -## 10. 보안 및 운영 - -### 10.1 보안 고려사항 - -| 항목 | 대책 | -|------|------| -| API 키 노출 | `ai_configs` 테이블에 암호화 저장, .env 폴백 | -| 인터뷰 데이터 보호 | tenant_id 격리, 접근 권한 제어 | -| Claude API 비용 제어 | 일일/월별 토큰 한도 설정 (ai_configs.options) | -| 프롬프트 인젝션 | 사용자 입력 sanitize, 시스템 프롬프트 분리 | - -### 10.2 모니터링 - -| 항목 | 방법 | -|------|------| -| API 호출 성공/실패 | `ai_quotations.status` + `error_message` | -| 토큰 사용량 | `ai_token_usages` 테이블 (기존 인프라) | -| 비용 추적 | MNG `/system/ai-token-usage` (기존 UI) | -| 견적 전환율 | `ai_quotations` → `quotes` 전환 비율 통계 | - -### 10.3 에러 처리 - -```php -try { - $result = $this->callClaudeApi($systemPrompt, $userMessage); -} catch (ConnectionException $e) { - // Claude API 연결 실패 - $aiQuotation->update(['status' => 'failed', 'error_message' => 'Claude API 연결 실패']); -} catch (JsonException $e) { - // 응답 JSON 파싱 실패 - $aiQuotation->update(['status' => 'failed', 'error_message' => 'AI 응답 파싱 실패']); -} -``` - ---- - -## 11. 기대 효과 - -| 항목 | Before (현재) | After (AI 엔진) | -|------|--------------|-----------------| -| 견적 작성 시간 | 2~4시간 (수동) | 5~10분 (AI 초안 + 검토) | -| 모듈 누락 위험 | 매니저 경험 의존 | AI가 체계적으로 분석 | -| 고객 맞춤화 | 표준 템플릿 복사 | 인터뷰 기반 맞춤 견적 | -| 비용 최적화 | 수동 비교 | AI가 패키지 vs 개별 자동 비교 | -| 견적 1건 AI 비용 | — | ~9원 (Claude Sonnet) | - ---- - -## 변경 이력 - -| 날짜 | 내용 | -|------|------| -| 2026-03-02 | 기획 초안 작성 | - ---- - -## 관련 문서 - -| 문서 | 경로 | -|------|------| -| SAM 프로젝트 개요 | `docs/SAM_PROJECT_OVERVIEW_FOR_AI.md` | -| 견적 기능 상세 | `docs/features/quotes/README.md` | -| 견적 시스템 분석 | `docs/data/견적/견적시스템_분석문서.md` | -| AI 기능 현황 | `docs/features/ai/README.md` | -| AI 설정 가이드 | `docs/guides/ai-config-settings.md` | -| 고객 요금 안내 | `docs/rules/customer-pricing.md` | -| 내부 과금 정책 | `docs/rules/billing-policy.md` | -| 단가 정책 | `docs/rules/pricing-policy.md` | -| Plans 가이드 | `docs/plans/GUIDE.md` | - ---- - -**최종 업데이트**: 2026-03-02 diff --git a/sam/docs/plans/attendance-management-plan.md b/sam/docs/plans/attendance-management-plan.md deleted file mode 100644 index c5f8889..0000000 --- a/sam/docs/plans/attendance-management-plan.md +++ /dev/null @@ -1,284 +0,0 @@ -# MNG 근태현황 개발 계획서 - -> **작성일**: 2026-02-26 -> **상태**: 계획 수립 - ---- - -## 1. 개요 - -### 1.1 목적 - -MNG 인사관리 > 근태현황 기능을 완성한다. 현재 기본 CRUD가 구현되어 있으나, 미완성 기능과 알려진 버그를 해결하고 실무에 필요한 추가 기능을 구현한다. - -### 1.2 현재 상태 분석 - -#### 구현 완료 - -| 항목 | 상태 | 파일 | -|------|------|------| -| 근태 목록 조회 (HTMX 테이블) | ✅ | `index.blade.php`, `table.blade.php` | -| 월간 통계 카드 (5종) | ✅ | `index.blade.php` | -| 필터 (이름, 부서, 상태, 날짜) | ✅ | `index.blade.php` | -| 등록/수정 모달 | ✅ | `index.blade.php` | -| CRUD API (목록/등록/수정/삭제) | ✅ | `AttendanceController.php` (API) | -| AttendanceService | ✅ | `AttendanceService.php` | -| Attendance 모델 (8개 상태) | ✅ | `Attendance.php` | -| Soft Delete | ✅ | 모델 + 서비스 | - -#### 알려진 문제 (E2E 테스트 결과) - -| 문제 | 심각도 | 설명 | -|------|--------|------| -| 엑셀 다운로드 미구현 | 🟡 중요 | 버튼 없음, API 미연결 | -| 근태 등록 서버 에러 | 🔴 필수 | 모달 submit 시 500 에러 발생 가능 | - -#### 미구현 기능 (API 대비) - -| 기능 | API 지원 | MNG 상태 | -|------|---------|---------| -| 엑셀 내보내기 | ✅ `/v1/attendances/export` | ❌ 미구현 | -| 일괄 삭제 | ✅ `/v1/attendances/bulk-delete` | ❌ 미구현 | -| 개인별 근태 상세 | ✅ `/v1/attendances/{id}` | ❌ 미구현 | -| 월간 요약 통계 | ✅ `/v1/attendances/monthly-stats` | ⚠️ 기본만 구현 | -| 출퇴근 설정 관리 | ✅ `attendance_settings` 테이블 | ❌ 미구현 | - ---- - -## 2. 구현 범위 - -### 2.1 Phase 1: 버그 수정 + 핵심 기능 (우선) - -| # | 작업 | 난이도 | 설명 | -|---|------|--------|------| -| 1-1 | 근태 등록/수정 버그 수정 | 🟢 낮음 | store/update API 요청 오류 점검 및 수정 | -| 1-2 | 엑셀 다운로드 | 🟢 낮음 | API `/v1/attendances/export` 연동, 다운로드 버튼 추가 | -| 1-3 | 일괄 삭제 | 🟡 보통 | 체크박스 선택 → 일괄 삭제 버튼 | -| 1-4 | 월간 통계 기간 선택 | 🟢 낮음 | 현재 당월 고정 → 연/월 선택 가능하게 | - -### 2.2 Phase 2: 확장 기능 - -| # | 작업 | 난이도 | 설명 | -|---|------|--------|------| -| 2-1 | 개인별 근태 상세 페이지 | 🟡 보통 | 사원 클릭 → 월간 달력 + 출퇴근 이력 | -| 2-2 | 출퇴근 설정 관리 | 🟡 보통 | 표준 출근시간, GPS 사용여부, 허용반경 설정 | -| 2-3 | 월간/주간 요약 뷰 | 🟡 보통 | 부서별/사원별 근태 요약 테이블 | -| 2-4 | 근태 일괄 등록 | 🔴 높음 | 날짜 범위 + 대상 사원 → 일괄 근태 등록 | - ---- - -## 3. 상세 설계 - -### 3.1 Phase 1-1: 근태 등록/수정 버그 수정 - -**점검 항목**: -- MNG `AttendanceController::store()` validation 규칙과 실제 폼 데이터 일치 여부 -- `check_in`, `check_out` 포맷 (HH:MM vs HH:MM:SS) 불일치 가능성 -- `user_id` 전달 누락 여부 -- HTMX `hx-headers` CSRF 토큰 전달 확인 - -**수정 대상 파일**: -- `mng/app/Http/Controllers/Api/Admin/HR/AttendanceController.php` -- `mng/resources/views/hr/attendances/index.blade.php` (JS `submitAttendance()`) - ---- - -### 3.2 Phase 1-2: 엑셀 다운로드 - -**방식**: MNG에서 직접 엑셀 생성 (API 서버 미경유) - -**구현**: -1. `AttendanceService::getExportData()` 메서드 추가 -2. `AttendanceController::export()` 메서드 추가 -3. 라우트: `GET /api/admin/hr/attendances/export` -4. 인덱스 페이지에 다운로드 버튼 추가 - -**엑셀 컬럼**: - -| 컬럼 | 값 | -|------|-----| -| 날짜 | `base_date` | -| 사원명 | `user.name` | -| 부서 | `department.name` | -| 상태 | `status_label` | -| 출근 | `check_in` | -| 퇴근 | `check_out` | -| 비고 | `remarks` | - -**수정 대상 파일**: -- `mng/app/Services/HR/AttendanceService.php` -- `mng/app/Http/Controllers/Api/Admin/HR/AttendanceController.php` -- `mng/routes/api.php` -- `mng/resources/views/hr/attendances/index.blade.php` - ---- - -### 3.3 Phase 1-3: 일괄 삭제 - -**UI**: 테이블 각 행에 체크박스 추가, 헤더에 전체선택, 상단에 "선택 삭제" 버튼 - -**구현**: -1. `table.blade.php`에 체크박스 컬럼 추가 -2. Alpine.js 컴포넌트로 선택 상태 관리 -3. `AttendanceController::bulkDestroy()` 메서드 추가 -4. 라우트: `POST /api/admin/hr/attendances/bulk-delete` - -**수정 대상 파일**: -- `mng/resources/views/hr/attendances/partials/table.blade.php` -- `mng/resources/views/hr/attendances/index.blade.php` -- `mng/app/Http/Controllers/Api/Admin/HR/AttendanceController.php` -- `mng/app/Services/HR/AttendanceService.php` -- `mng/routes/api.php` - ---- - -### 3.4 Phase 1-4: 월간 통계 기간 선택 - -**현재**: 당월 통계만 표시 (하드코딩) -**변경**: 연/월 드롭다운 추가 → 선택 시 통계 카드 HTMX 갱신 - -**구현**: -1. 통계 카드 영역을 별도 partial로 분리 (`partials/stats.blade.php`) -2. 연/월 선택 UI 추가 -3. `hx-get` + `hx-vals`로 선택된 연/월 전달 -4. `stats()` API가 `year`, `month` 파라미터 이미 지원 - -**수정 대상 파일**: -- `mng/resources/views/hr/attendances/index.blade.php` -- `mng/resources/views/hr/attendances/partials/stats.blade.php` (신규) - ---- - -### 3.5 Phase 2-1: 개인별 근태 상세 페이지 - -**URL**: `/hr/attendances/{userId}` - -**페이지 구성**: -1. **사원 프로필 카드**: 이름, 부서, 직급, 재직상태 -2. **월간 달력**: 날짜별 근태 상태를 색상 도트로 표시 -3. **월간 통계**: 정시출근 N일, 지각 N일, 결근 N일 등 -4. **출퇴근 이력 테이블**: 해당 월의 상세 출퇴근 기록 - -**수정 대상 파일**: -- `mng/routes/web.php` (라우트 추가) -- `mng/app/Http/Controllers/HR/AttendanceController.php` (`show()` 추가) -- `mng/app/Services/HR/AttendanceService.php` (`getUserMonthlyAttendances()` 추가) -- `mng/resources/views/hr/attendances/show.blade.php` (신규) - ---- - -### 3.6 Phase 2-2: 출퇴근 설정 관리 - -**URL**: `/hr/attendance-settings` - -**설정 항목** (`attendance_settings` 테이블 기반): - -| 항목 | 필드 | 설명 | -|------|------|------| -| GPS 출퇴근 사용 | `use_gps` | on/off 토글 | -| 자동 출퇴근 | `use_auto` | on/off 토글 | -| 허용 반경 | `allowed_radius` | 미터 단위 입력 | -| 본사 주소 | `hq_address` | 주소 입력 | -| 본사 위도/경도 | `hq_latitude`, `hq_longitude` | 좌표 입력 | - -**수정 대상 파일**: -- `mng/routes/web.php`, `mng/routes/api.php` -- `mng/app/Http/Controllers/HR/AttendanceSettingController.php` (신규) -- `mng/app/Models/HR/AttendanceSetting.php` (신규 — API 모델 미러링) -- `mng/resources/views/hr/attendance-settings/index.blade.php` (신규) - ---- - -## 4. 데이터 흐름 - -### 4.1 MNG 자체 CRUD 패턴 (현재) - -``` -브라우저 ──HTMX──→ MNG API Controller ──→ MNG Service ──→ DB (직접) - (api/admin/hr/attendances) -``` - -> MNG는 API 서버를 경유하지 않고 DB에 직접 접근한다. - -### 4.2 엑셀 다운로드 흐름 - -``` -브라우저 ──GET──→ MNG AttendanceController::export() - → AttendanceService::getExportData() - → ExportService::download() (라라벨 엑셀) - ← BinaryFileResponse (.xlsx) -``` - ---- - -## 5. 구현 순서 및 의존 관계 - -``` -Phase 1 (버그 수정 + 핵심) - 1-1 버그 수정 ─────────────────────────────┐ - 1-2 엑셀 다운로드 ─────────────────────────┤ 독립적, 병렬 가능 - 1-3 일괄 삭제 ─────────────────────────────┤ - 1-4 통계 기간 선택 ────────────────────────┘ - -Phase 2 (확장) - 2-1 개인별 상세 ───→ 2-3 월간/주간 요약 (데이터 재사용) - 2-2 출퇴근 설정 ─── 독립적 - 2-4 일괄 등록 ───── 독립적 -``` - ---- - -## 6. 관련 파일 목록 - -### MNG 프로젝트 (`/home/aweso/sam/mng`) - -| 파일 | 역할 | -|------|------| -| `app/Models/HR/Attendance.php` | 모델 (8개 상태, json_details) | -| `app/Services/HR/AttendanceService.php` | 비즈니스 로직 | -| `app/Http/Controllers/HR/AttendanceController.php` | 뷰 컨트롤러 | -| `app/Http/Controllers/Api/Admin/HR/AttendanceController.php` | API 컨트롤러 | -| `resources/views/hr/attendances/index.blade.php` | 메인 페이지 | -| `resources/views/hr/attendances/partials/table.blade.php` | 테이블 partial | -| `routes/web.php` | 웹 라우트 | -| `routes/api.php` | API 라우트 | - -### API 프로젝트 (`/home/aweso/sam/api`) - -| 파일 | 역할 | -|------|------| -| `database/migrations/2025_12_09_*_attendances*` | 마이그레이션 (2개) | -| `database/migrations/2025_12_17_*_attendance_settings*` | 설정 테이블 | -| `app/Models/Tenants/Attendance.php` | API 모델 (참조용) | -| `app/Models/Tenants/AttendanceSetting.php` | 설정 모델 (참조용) | - -### 참조 문서 - -| 문서 | 경로 | -|------|------| -| 근태 API 규칙 | `docs/rules/attendance-api.md` | -| GPS 출퇴근 스펙 | `docs/specs/erp-analysis/03-gps-attendance.md` | - ---- - -## 7. 검증 방법 - -### Phase 1 체크리스트 - -- [ ] 근태 등록 모달 → 사원 선택 + 날짜 + 상태 입력 → 저장 성공 -- [ ] 근태 수정 모달 → 기존 데이터 로드 → 수정 → 저장 성공 -- [ ] 동일 사원/날짜 중복 등록 시 기존 데이터 업데이트 (Upsert) -- [ ] 엑셀 다운로드 버튼 클릭 → .xlsx 파일 다운로드 -- [ ] 체크박스 선택 → 일괄 삭제 → 테이블 갱신 -- [ ] 연/월 선택 → 통계 카드 갱신 - -### Phase 2 체크리스트 - -- [ ] 사원 이름 클릭 → 개인별 상세 페이지 이동 -- [ ] 달력에 근태 상태 색상 표시 -- [ ] 출퇴근 설정 페이지 → GPS/자동 토글 → 저장 -- [ ] 허용 반경 변경 → 저장 → DB 반영 - ---- - -**최종 업데이트**: 2026-02-26 diff --git a/sam/docs/plans/block-builder-evolution-plan.md b/sam/docs/plans/block-builder-evolution-plan.md deleted file mode 100644 index 57385f3..0000000 --- a/sam/docs/plans/block-builder-evolution-plan.md +++ /dev/null @@ -1,706 +0,0 @@ -# 양식 디자이너(Block Builder) 고도화 계획 - -> **작성일**: 2026-03-06 -> **상태**: 계획 수립 -> **담당**: Claude Code + 개발팀 -> **관련**: [문서양식관리](../features/documents/mng-document-template.md) | [문서관리](../features/documents/mng-document-system.md) - ---- - -## 1. 현재 상태 진단 - -### 1.1 구현 완료 (Phase 1 — 2026-02-28) - -- 13개 블록 타입 (기본 6 + 폼 7) -- 3패널 UI (팔레트 / 캔버스 / 속성) -- SortableJS 드래그-앤-드롭 정렬 -- Undo/Redo (최대 50단계) -- JSON 스키마 저장 (`document_templates.schema`) -- 페이지 설정 (A4/A3/B5, 세로/가로, 여백) - -### 1.2 핵심 미구현 사항 - -| 기능 | 상태 | 영향도 | -|------|------|--------| -| 문서 생성 시 블록 렌더링 | 미구현 | 블록 서식으로 문서 작성 불가 | -| 결재선 블록 | 미구현 | 결재 워크플로우 연동 불가 | -| 데이터 바인딩 (EAV 연동) | 미구현 | 입력값 저장/로드 불가 | -| 동적 행 추가 | 미구현 | 검사 데이터 행 추가 불가 | -| 변수/매크로 시스템 | 미구현 | 자동 값 주입 불가 | -| 인쇄/PDF 출력 | 미구현 | 블록 문서 인쇄 불가 | -| Columns 내부 블록 | 미구현 | 다단 레이아웃 활용 불가 | - -> **결론**: 양식 디자이너는 **레이아웃 편집기**로만 동작. 실제 문서 생성/결재/인쇄에서는 Legacy Builder만 사용 가능. - ---- - -## 2. 목표 - -Legacy Builder의 모든 기능을 양식 디자이너에서 지원하면서, 더 유연하고 확장 가능한 문서 시스템 구축. - -**최종 목표:** -``` -양식 디자이너로 서식 설계 - ↓ -블록 스키마 기반 문서 생성 (데이터 입력) - ↓ -결재 워크플로우 (작성 → 검토 → 승인) - ↓ -인쇄/PDF 출력 - ↓ -Legacy Builder 완전 대체 -``` - ---- - -## 3. 개발 로드맵 (6단계) - -### Phase 2: 블록 런타임 렌더러 (기반 인프라) - -> **목표**: 저장된 블록 스키마를 문서 생성/조회/인쇄에서 렌더링 - -#### 2-1. 블록 렌더러 엔진 - -**위치**: `mng/resources/views/documents/partials/block-renderer.blade.php` - -``` -schema JSON 입력 - ↓ -블록 타입별 Blade 컴포넌트 렌더링 - ↓ -모드별 출력: - - view 모드: 읽기 전용 HTML - - edit 모드: 입력 폼 HTML - - print 모드: 인쇄 최적화 HTML -``` - -**핵심 구현:** - -```php -// BlockRendererService -class BlockRendererService -{ - public function render(array $schema, string $mode, array $data = []): string - { - $html = ''; - foreach ($schema['blocks'] as $block) { - $html .= $this->renderBlock($block, $mode, $data); - } - return $html; - } - - private function renderBlock(array $block, string $mode, array $data): string - { - return match($block['type']) { - 'heading' => $this->renderHeading($block, $mode), - 'paragraph' => $this->renderParagraph($block, $mode), - 'table' => $this->renderTable($block, $mode, $data), - 'text_field' => $this->renderTextField($block, $mode, $data), - 'number_field' => $this->renderNumberField($block, $mode, $data), - 'date_field' => $this->renderDateField($block, $mode, $data), - 'select_field' => $this->renderSelectField($block, $mode, $data), - 'checkbox_field' => $this->renderCheckboxField($block, $mode, $data), - 'textarea_field' => $this->renderTextareaField($block, $mode, $data), - 'signature_field'=> $this->renderSignatureField($block, $mode, $data), - 'divider' => $this->renderDivider($block), - 'spacer' => $this->renderSpacer($block), - 'columns' => $this->renderColumns($block, $mode, $data), - 'approval_line' => $this->renderApprovalLine($block, $mode, $data), - 'dynamic_table' => $this->renderDynamicTable($block, $mode, $data), - default => '', - }; - } -} -``` - -#### 2-2. 문서 편집 화면 통합 - -**수정 대상**: `mng/resources/views/documents/edit.blade.php` - -``` -Template 로드 - ↓ -isBlockBuilder() 체크 - ├── true → BlockRendererService::render(schema, 'edit', data) - └── false → 기존 Legacy 렌더링 (변경 없음) -``` - -#### 2-3. 데이터 바인딩 (EAV 매핑) - -블록의 `binding` 속성으로 EAV 데이터와 연결: - -```javascript -// 블록 스키마 예시 -{ - "type": "text_field", - "props": { - "label": "제품명", - "binding": "bf_product_name", // ← EAV field_key - "required": true - } -} -``` - -``` -저장 시: - block.binding → document_data.field_key - input.value → document_data.field_value - block.id → document_data.section_id (블록 ID를 섹션으로 활용) - -로드 시: - document_data 조회 → field_key로 블록 매칭 → 값 주입 -``` - -**산출물:** - -| 파일 | 작업 | -|------|------| -| `mng/app/Services/BlockRendererService.php` | 신규 생성 | -| `mng/resources/views/documents/partials/block-renderer.blade.php` | 신규 생성 | -| `mng/resources/views/documents/edit.blade.php` | 블록 빌더 분기 추가 | -| `mng/resources/views/documents/show.blade.php` | 블록 빌더 분기 추가 | -| `api/app/Services/DocumentService.php` | 블록 데이터 저장/로드 로직 | - ---- - -### Phase 3: 결재선 블록 - -> **목표**: 블록 스키마 내에서 결재 워크플로우 정의 - -#### 3-1. approval_line 블록 타입 추가 - -**스키마:** - -```json -{ - "type": "approval_line", - "props": { - "steps": [ - { "role": "작성", "department": "", "name": "" }, - { "role": "검토", "department": "", "name": "" }, - { "role": "승인", "department": "", "name": "" } - ], - "style": "horizontal", - "showStamp": true - } -} -``` - -#### 3-2. 팔레트에 결재선 블록 추가 - -```javascript -// 블록 팔레트 추가 -{ type: 'approval_line', icon: '✓', label: '결재선', category: '워크플로우' } -``` - -#### 3-3. 속성 패널 결재선 편집기 - -``` -┌─────────────────────────────┐ -│ 결재선 설정 │ -│ │ -│ [+ 단계 추가] │ -│ │ -│ 1. 역할: [작성 ▼] │ -│ 부서: [___________] │ -│ 이름: [___________] │ -│ │ -│ 2. 역할: [검토 ▼] │ -│ 부서: [___________] │ -│ 이름: [___________] │ -│ │ -│ 3. 역할: [승인 ▼] │ -│ 부서: [___________] │ -│ 이름: [___________] │ -│ │ -│ ☐ 직인 표시 │ -│ 스타일: [가로형 ▼] │ -└─────────────────────────────┘ -``` - -#### 3-4. 문서 생성 시 결재 연동 - -``` -블록 스키마 → approval_line 블록 추출 - ↓ -DocumentApproval 레코드 자동 생성 - ↓ -기존 결재 워크플로우 (submit → approve → reject) 그대로 활용 -``` - -**산출물:** - -| 파일 | 작업 | -|------|------| -| `block-editor.blade.php` | approval_line 블록 추가 | -| `block-canvas.blade.php` | 결재선 렌더링 | -| `BlockRendererService.php` | 결재선 view/edit/print 렌더 | -| `DocumentService.php` | 블록 결재선 → DocumentApproval 변환 | - ---- - -### Phase 4: 동적 테이블 블록 + 변수 시스템 - -> **목표**: 문서 작성 시 행 추가/삭제 가능한 테이블 + 자동 값 주입 - -#### 4-1. dynamic_table 블록 타입 - -기존 `table` 블록은 정적 (양식 설계 시 행 고정). `dynamic_table`은 문서 작성 시 행 동적 추가. - -**스키마:** - -```json -{ - "type": "dynamic_table", - "props": { - "label": "검사 데이터", - "columns": [ - { "key": "col_item", "label": "항목", "type": "text", "width": 120 }, - { "key": "col_standard", "label": "기준값", "type": "text", "width": 100 }, - { "key": "col_measured", "label": "측정값", "type": "number", "width": 100 }, - { "key": "col_result", "label": "판정", "type": "select", - "options": ["합격", "불합격", "보류"], "width": 80 } - ], - "minRows": 1, - "maxRows": 50, - "initialRows": 3, - "showRowNumber": true, - "binding": "inspection_data" - } -} -``` - -#### 4-2. EAV 데이터 매핑 - -``` -dynamic_table 블록 데이터 저장: - -document_data 레코드: - section_id = (dynamic_table 블록 ID → section 매핑) - column_id = (columns[].key → column 매핑) - row_index = 0, 1, 2, ... - field_key = "col_item", "col_standard", ... - field_value = 입력값 -``` - -#### 4-3. 변수/매크로 시스템 - -**내장 변수:** - -| 변수 | 값 | 설명 | -|------|-----|------| -| `{{today}}` | 현재 날짜 | YYYY-MM-DD | -| `{{now}}` | 현재 시각 | YYYY-MM-DD HH:mm | -| `{{user.name}}` | 로그인 사용자명 | | -| `{{user.department}}` | 로그인 사용자 부서 | | -| `{{doc.number}}` | 문서 번호 | 자동채번 | -| `{{doc.title}}` | 문서 제목 | | -| `{{template.company}}` | 서식 회사명 | | - -**연결 데이터 변수 (linked data):** - -| 변수 | 설명 | -|------|------| -| `{{item.name}}` | 연결 품목명 | -| `{{item.code}}` | 연결 품목 코드 | -| `{{order.number}}` | 연결 작업지시서 번호 | -| `{{order.quantity}}` | 연결 수량 | - -**변수 사용 예시 (블록 속성):** - -```json -{ - "type": "text_field", - "props": { - "label": "검사일자", - "binding": "bf_inspection_date", - "default": "{{today}}" - } -} -``` - -```json -{ - "type": "paragraph", - "props": { - "text": "작성자: {{user.name}} ({{user.department}})" - } -} -``` - -#### 4-4. 변수 해석 엔진 - -```php -// VariableResolver -class VariableResolver -{ - public function resolve(string $text, array $context): string - { - return preg_replace_callback('/\{\{(\w+(?:\.\w+)*)\}\}/', function ($m) use ($context) { - return data_get($context, $m[1], $m[0]); - }, $text); - } - - public function buildContext(Document $document, ?User $user = null): array - { - return [ - 'today' => now()->format('Y-m-d'), - 'now' => now()->format('Y-m-d H:i'), - 'user' => [ - 'name' => $user?->name, - 'department' => $user?->department?->name, - ], - 'doc' => [ - 'number' => $document->document_number, - 'title' => $document->title, - ], - 'item' => $this->resolveLinkedItem($document), - 'order' => $this->resolveLinkedOrder($document), - ]; - } -} -``` - -**산출물:** - -| 파일 | 작업 | -|------|------| -| `block-editor.blade.php` | dynamic_table 블록 추가 | -| `BlockRendererService.php` | 동적 테이블 렌더링 (edit: 행 추가/삭제 UI) | -| `mng/app/Services/VariableResolver.php` | 신규 생성 | -| `DocumentService.php` | 동적 테이블 EAV 저장/로드 | - ---- - -### Phase 5: 고급 블록 + 조건부 로직 - -> **목표**: 수식 계산, 조건부 표시, 이미지 블록 등 고급 기능 - -#### 5-1. 수식 블록 (formula) - -```json -{ - "type": "formula_field", - "props": { - "label": "합계", - "expression": "SUM(inspection_data.col_measured)", - "format": "number", - "decimal": 2 - } -} -``` - -**지원 함수:** - -| 함수 | 설명 | 예시 | -|------|------|------| -| `SUM()` | 합계 | `SUM(table.col_amount)` | -| `AVG()` | 평균 | `AVG(table.col_measured)` | -| `COUNT()` | 개수 | `COUNT(table.col_item)` | -| `MIN()` / `MAX()` | 최솟값/최댓값 | `MIN(table.col_value)` | -| `IF()` | 조건 | `IF(AVG(table.col_measured) > 5, "합격", "불합격")` | -| `ROUND()` | 반올림 | `ROUND(AVG(table.col_measured), 2)` | - -#### 5-2. 조건부 표시 (conditional visibility) - -모든 블록에 `visibility` 속성 추가: - -```json -{ - "type": "paragraph", - "props": { - "text": "불합격 사유를 기재해 주세요.", - "visibility": { - "condition": "field", - "field": "bf_judgement", - "operator": "equals", - "value": "불합격" - } - } -} -``` - -**연산자:** - -| 연산자 | 설명 | -|--------|------| -| `equals` | 같으면 표시 | -| `not_equals` | 다르면 표시 | -| `contains` | 포함하면 표시 | -| `greater_than` | 크면 표시 | -| `less_than` | 작으면 표시 | -| `is_empty` | 비어있으면 표시 | -| `is_not_empty` | 비어있지 않으면 표시 | - -#### 5-3. 이미지 블록 - -```json -{ - "type": "image", - "props": { - "label": "검사 사진", - "source": "upload", - "maxSize": 10, - "accept": ["jpeg", "png", "webp"], - "width": "100%", - "align": "center" - } -} -``` - -#### 5-4. Columns 내부 블록 (중첩 렌더링) - -```json -{ - "type": "columns", - "props": { - "count": 2, - "ratio": "1:1", - "children": [ - [ - { "type": "text_field", "props": { "label": "품명" } }, - { "type": "date_field", "props": { "label": "검사일" } } - ], - [ - { "type": "text_field", "props": { "label": "LOT NO" } }, - { "type": "select_field", "props": { "label": "판정", "options": ["합격","불합격"] } } - ] - ] - } -} -``` - -**산출물:** - -| 파일 | 작업 | -|------|------| -| `block-editor.blade.php` | formula, image, conditional 블록 추가 | -| `mng/app/Services/FormulaEngine.php` | 수식 해석 엔진 | -| `BlockRendererService.php` | 조건부 표시, 수식 계산 렌더링 | - ---- - -### Phase 6: 인쇄/PDF + Legacy 대체 - -> **목표**: 블록 문서 인쇄 완성, Legacy Builder 완전 대체 - -#### 6-1. 인쇄 레이아웃 - -``` -print 모드 렌더링: - - 페이지 설정 (A4/A3) 적용 - - 여백 적용 - - 폼 필드 → 값 표시 (입력란 제거) - - 서명 → 서명 이미지 표시 - - 결재선 → 직인 표시 - - 페이지 넘김 (page-break) 자동 계산 -``` - -#### 6-2. PDF 내보내기 - -``` -블록 렌더러 (print 모드 HTML) - ↓ -Puppeteer / wkhtmltopdf - ↓ -PDF 파일 생성 - ↓ -다운로드 또는 첨부 -``` - -#### 6-3. Legacy → Block 마이그레이션 도구 - -기존 Legacy 서식을 Block 스키마로 자동 변환: - -```php -// LegacyToBlockMigrator -class LegacyToBlockMigrator -{ - public function convert(DocumentTemplate $legacy): array - { - $blocks = []; - - // 1. 결재선 → approval_line 블록 - if ($legacy->approvalLines->isNotEmpty()) { - $blocks[] = $this->convertApprovalLines($legacy->approvalLines); - } - - // 2. 기본필드 → text_field / date_field 블록 - foreach ($legacy->basicFields as $field) { - $blocks[] = $this->convertBasicField($field); - } - - // 3. 섹션 → heading + image 블록 - foreach ($legacy->sections as $section) { - $blocks[] = ['type' => 'heading', 'props' => ['text' => $section->title]]; - if ($section->image_path) { - $blocks[] = ['type' => 'image', 'props' => ['source' => $section->image_path]]; - } - } - - // 4. 컬럼 → dynamic_table 블록 - if ($legacy->columns->isNotEmpty()) { - $blocks[] = $this->convertColumns($legacy->columns); - } - - return [ - 'version' => '1.0', - 'page' => ['size' => 'A4', 'orientation' => 'portrait'], - 'blocks' => $blocks, - ]; - } -} -``` - -#### 6-4. Legacy Builder 비활성화 - -``` -Phase 6 완료 후: - - 새 양식 생성: 양식 디자이너만 허용 - - 기존 Legacy 서식: 조회/편집 가능 (변환 유도) - - Legacy Builder "새 양식" 버튼: "양식 디자이너" 사용 안내 -``` - -**산출물:** - -| 파일 | 작업 | -|------|------| -| `mng/resources/views/documents/print-block.blade.php` | 인쇄 전용 뷰 | -| `mng/app/Services/LegacyToBlockMigrator.php` | 변환 도구 | -| `mng/app/Services/PdfExportService.php` | PDF 생성 | - ---- - -## 4. Phase별 우선순위 및 의존관계 - -``` -Phase 2: 블록 런타임 렌더러 ──────────────────────┐ - (렌더러 엔진, 데이터 바인딩, 문서 편집 통합) │ - │ -Phase 3: 결재선 블록 ─────────────────────┐ │ - (approval_line 블록, 결재 워크플로우) │ │ - ↓ ↓ -Phase 4: 동적 테이블 + 변수 ──────→ Phase 5: 고급 블록 - (dynamic_table, 매크로) (수식, 조건부, 이미지) - │ - ↓ - Phase 6: 인쇄/PDF + Legacy 대체 - (마이그레이션 도구) -``` - -| Phase | 의존 | 난이도 | 예상 범위 | -|-------|------|--------|----------| -| **Phase 2** | 없음 (기반) | 높음 | 렌더러 엔진 + EAV 매핑 | -| **Phase 3** | Phase 2 | 중간 | 결재선 블록 + 워크플로우 연동 | -| **Phase 4** | Phase 2 | 높음 | 동적 테이블 + 변수 해석 | -| **Phase 5** | Phase 4 | 높음 | 수식 엔진 + 조건부 로직 | -| **Phase 6** | Phase 3~5 | 중간 | 인쇄 + 마이그레이션 | - ---- - -## 5. 스키마 버전 관리 - -### 5.1 버전 규칙 - -| 버전 | Phase | 변경 내용 | -|------|-------|----------| -| `1.0` | Phase 1 (현재) | 기본 13개 블록 | -| `2.0` | Phase 2~3 | 데이터 바인딩, approval_line 추가 | -| `3.0` | Phase 4 | dynamic_table, 변수 시스템 | -| `4.0` | Phase 5 | formula, conditional, image | - -### 5.2 하위 호환 - -```json -{ - "version": "3.0", - "page": { ... }, - "blocks": [ ... ], - "variables": { ... }, - "migrations": { - "from_1.0": "auto" - } -} -``` - -- 이전 버전 스키마 자동 인식 및 업그레이드 -- 신규 블록 타입은 이전 버전에서 무시 (graceful degradation) - ---- - -## 6. 신규 블록 타입 전체 목록 - -### Phase별 블록 추가 계획 - -| Phase | 블록 타입 | 카테고리 | 설명 | -|-------|----------|---------|------| -| 1 (완료) | `heading` | 기본 | 제목 | -| 1 (완료) | `paragraph` | 기본 | 문단 | -| 1 (완료) | `table` | 기본 | 정적 테이블 | -| 1 (완료) | `columns` | 기본 | 다단 레이아웃 | -| 1 (완료) | `divider` | 기본 | 구분선 | -| 1 (완료) | `spacer` | 기본 | 여백 | -| 1 (완료) | `text_field` | 폼 | 텍스트 입력 | -| 1 (완료) | `number_field` | 폼 | 숫자 입력 | -| 1 (완료) | `date_field` | 폼 | 날짜 입력 | -| 1 (완료) | `select_field` | 폼 | 드롭다운 | -| 1 (완료) | `checkbox_field` | 폼 | 체크박스 | -| 1 (완료) | `textarea_field` | 폼 | 장문 텍스트 | -| 1 (완료) | `signature_field` | 폼 | 서명 | -| **3** | `approval_line` | 워크플로우 | 결재선 | -| **4** | `dynamic_table` | 데이터 | 동적 행 테이블 | -| **5** | `formula_field` | 데이터 | 수식 계산 | -| **5** | `image` | 미디어 | 이미지 업로드/표시 | - ---- - -## 7. 기술 스택 정리 - -| 구성 요소 | 기술 | 비고 | -|----------|------|------| -| 블록 에디터 UI | Alpine.js + Blade | 기존 유지 | -| 드래그-앤-드롭 | SortableJS | 기존 유지 | -| 블록 렌더러 | PHP (BlockRendererService) | 신규 | -| 변수 해석 | PHP (VariableResolver) | 신규 | -| 수식 엔진 | PHP (FormulaEngine) | 신규 | -| 데이터 저장 | EAV (document_data) | 기존 테이블 활용 | -| 결재 워크플로우 | DocumentApproval | 기존 로직 활용 | -| 인쇄 | CSS @media print | 신규 | -| PDF | Puppeteer 또는 wkhtmltopdf | 신규 | - ---- - -## 8. 위험 요소 및 대응 - -| 위험 | 영향 | 대응 | -|------|------|------| -| EAV 매핑 복잡도 | 블록 ID ↔ section_id 매핑 불일치 | 블록 ID를 section 대용으로 사용, 매핑 테이블 추가 검토 | -| Legacy 데이터 호환 | 기존 문서 데이터 접근 불가 | Legacy 서식 문서는 기존 방식 유지, 신규 서식만 블록 적용 | -| 수식 엔진 보안 | 임의 코드 실행 위험 | 화이트리스트 함수만 허용, eval 사용 금지 | -| 인쇄 레이아웃 | 브라우저별 차이 | CSS @page 규격 준수, PDF 변환 권장 | -| 스키마 마이그레이션 | 버전 업그레이드 시 데이터 손실 | 하위 호환 보장, 자동 업그레이드 로직 | - ---- - -## 9. 성공 기준 - -| 기준 | 측정 방법 | -|------|----------| -| 블록 서식으로 문서 생성 가능 | Phase 2 완료 후 테스트 | -| 결재 워크플로우 정상 동작 | Phase 3 완료 후 테스트 | -| 동적 행 추가/삭제 | Phase 4 완료 후 테스트 | -| 변수 자동 주입 | Phase 4 완료 후 테스트 | -| Legacy 서식 자동 변환 | Phase 6 완료 후 테스트 | -| 인쇄 품질 A4 기준 정상 | Phase 6 완료 후 테스트 | - ---- - -## 관련 문서 - -- [문서양식관리](../features/documents/mng-document-template.md) — 현재 양식관리 기술문서 -- [문서관리 시스템](../features/documents/mng-document-system.md) — 문서 생성/결재 기술문서 -- [문서관리 API](../features/documents/README.md) — API 엔드포인트 목록 - ---- - -**최종 업데이트**: 2026-03-06 diff --git a/sam/docs/plans/design-insight-menu-plan.md b/sam/docs/plans/design-insight-menu-plan.md deleted file mode 100644 index 28122f5..0000000 --- a/sam/docs/plans/design-insight-menu-plan.md +++ /dev/null @@ -1,611 +0,0 @@ -# UI/UX 디자인 인사이트 연구 메뉴 기획서 - -> **작성일**: 2026-03-08 -> **상태**: 기획 중 -> **라우트**: `/rd/design-insight` -> **모티브**: 기획디자인 스토리보드 에디터 (`/rd/planning-design`) - ---- - -## 1. 개요 - -### 1.1 배경 - -기획디자인 메뉴는 ERP 화면을 **설계(Output)**하는 도구다. -그런데 좋은 설계를 하려면 **연구(Input)**가 먼저 필요하다. - -``` -연구 (이 메뉴) 설계 (기획디자인) -┌─────────────────┐ ┌─────────────────┐ -│ 레퍼런스 수집 │ │ 스토리보드 작성 │ -│ 패턴 분석 │ ──→ │ 와이어프레임 설계 │ -│ 인사이트 정리 │ │ HTML 내보내기 │ -│ 디자인 원칙 학습 │ │ 인쇄 │ -└─────────────────┘ └─────────────────┘ -``` - -현재 SAM ERP 화면을 만들 때 참고할 디자인 패턴이나 인사이트를 체계적으로 관리하는 도구가 없다. 외부 서비스(Dribbble, Mobbin 등)를 참고하지만 **우리 ERP에 맞는 패턴**을 축적하는 곳이 없다. - -### 1.2 목적 - -SAM ERP 화면 개발에 필요한 **UI/UX 디자인 인사이트를 수집·분석·축적**하는 연구 도구 - -### 1.3 핵심 가치 - -| 가치 | 설명 | -|------|------| -| **패턴 축적** | "이 화면은 왜 좋은가?" — 반복 사용할 패턴을 라이브러리화 | -| **Before/After** | 개선 전후를 비교하여 디자인 결정의 근거를 기록 | -| **팀 학습** | 디자인 인사이트를 팀원과 공유, 일관된 UI 품질 유지 | -| **빠른 참조** | 새 화면 설계 시 기존 패턴을 즉시 찾아 재사용 | - ---- - -## 2. 기술 아키텍처 - -### 2.1 기획디자인과 동일한 패턴 - -기획디자인 메뉴의 성공 패턴을 그대로 적용한다. - -| 항목 | 선택 | 이유 | -|------|------|------| -| 프레임워크 | Alpine.js 단일 파일 SPA | 서버 API 없이 즉시 사용, MNG 기존 스택 | -| 저장 | localStorage | 서버 의존성 제거, 즉시 사용 가능 | -| 뷰 파일 | `resources/views/rd/design-insight/index.blade.php` | 단일 파일 구조 | -| 컨트롤러 | `RdController@designInsight()` | 기존 R&D 컨트롤러 확장 | -| 이미지 | Base64 Data URL (localStorage) | 서버 업로드 불필요 | - -### 2.2 라우트 - -```php -// routes/web.php — R&D 그룹 내 추가 -Route::get('/rd/design-insight', [RdController::class, 'designInsight']) - ->name('rd.design-insight'); -``` - -### 2.3 localStorage 키 - -| 키 | 용도 | -|----|------| -| `di_projects` | 연구 프로젝트 목록 (메인 저장소) | -| `di_current` | 현재 프로젝트 ID | -| `di_patterns` | 디자인 패턴 라이브러리 (프로젝트 간 공유) | - ---- - -## 3. 화면 구조 - -### 3.1 전체 레이아웃 - -``` -┌──────────────────────────────────────────────────────────────┐ -│ 툴바: [프로젝트명] [저장] [내보내기] [뷰: 보드│리스트│갤러리] │ -├──────────────────────────────────────────────────────────────┤ -│ 카테고리 탭: 전체 │ 레퍼런스 │ 분석 │ 패턴 │ Before/After │ -├────────┬─────────────────────────────────────────────────────┤ -│ │ │ -│ 사이드 │ 메인 콘텐츠 영역 │ -│ 바 │ │ -│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ -│ ◆ 프로 │ │ 인사이트 │ │ 인사이트 │ │ 인사이트 │ │ -│ 젝트 │ │ 카드 1 │ │ 카드 2 │ │ 카드 3 │ │ -│ 목록 │ │ │ │ │ │ │ │ -│ │ │ 🏷️태그 │ │ 🏷️태그 │ │ 🏷️태그 │ │ -│ ◆ 태그 │ └─────────┘ └─────────┘ └─────────┘ │ -│ 필터 │ │ -│ │ ┌─────────┐ ┌─────────┐ │ -│ ◆ 검색 │ │ 인사이트 │ │ + 새 카드 │ │ -│ │ │ 카드 4 │ │ 추가 │ │ -│ │ └─────────┘ └─────────┘ │ -│ │ │ -├────────┴─────────────────────────────────────────────────────┤ -│ 상태바: 카드 12개 │ 패턴 5개 │ 태그 8개 │ -└──────────────────────────────────────────────────────────────┘ -``` - -### 3.2 뷰 모드 (3종) - -| 뷰 | 설명 | 용도 | -|----|------|------| -| **보드 (Board)** | 칸반 스타일 카드 격자 배열 | 전체 현황 파악, 기본 뷰 | -| **리스트 (List)** | 테이블형 목록 (정렬/필터) | 대량 데이터 관리, 검색 | -| **갤러리 (Gallery)** | 이미지 중심 큰 썸네일 격자 | 시각적 비교, 레퍼런스 브라우징 | - ---- - -## 4. 인사이트 카드 (핵심 데이터 단위) - -### 4.1 카드 유형 (4종) - -#### A. 레퍼런스 카드 (Reference) - -외부/내부 화면 스크린샷을 수집하고 메모를 남긴다. - -``` -┌──────────────────────────────┐ -│ 📷 [스크린샷 이미지] │ -│ │ -├──────────────────────────────┤ -│ 📌 Notion 대시보드 │ -│ "카드형 레이아웃이 정보 밀도를 │ -│ 유지하면서도 시각적으로 깔끔" │ -├──────────────────────────────┤ -│ 출처: notion.so │ -│ 🏷️ 대시보드 카드 레이아웃 │ -│ ⭐⭐⭐⭐☆ │ -└──────────────────────────────┘ -``` - -| 필드 | 타입 | 설명 | -|------|------|------| -| `image` | string (Base64) | 스크린샷 이미지 | -| `title` | string | 제목 | -| `memo` | string | 인사이트 메모 (왜 좋은가/나쁜가) | -| `source` | string | 출처 (URL, 앱 이름 등) | -| `tags` | string[] | 태그 배열 | -| `rating` | number (1-5) | 평점 | -| `category` | string | 화면 카테고리 | - -#### B. 분석 카드 (Analysis) - -화면을 분석하고 디자인 원칙을 체크한다. - -``` -┌──────────────────────────────┐ -│ 🔍 SAM 수주 목록 화면 분석 │ -├──────────────────────────────┤ -│ [스크린샷 + 어노테이션 오버레이]│ -│ ①→ 검색 영역 너무 넓음 │ -│ ②→ 버튼 정렬 불일치 │ -│ ③→ 여백 불균형 │ -├──────────────────────────────┤ -│ ✅ 정렬 (Alignment) │ -│ ❌ 대비 (Contrast) │ -│ ✅ 반복 (Repetition) │ -│ ⚠️ 근접성 (Proximity) │ -├──────────────────────────────┤ -│ 개선 제안: │ -│ "검색 영역을 접을 수 있게 하고 │ -│ 버튼 그룹을 우측 정렬" │ -│ 🏷️ 목록화면 개선필요 │ -└──────────────────────────────┘ -``` - -| 필드 | 타입 | 설명 | -|------|------|------| -| `image` | string (Base64) | 분석 대상 스크린샷 | -| `annotations` | Annotation[] | 어노테이션 배열 (마커 번호, 좌표, 텍스트) | -| `principles` | object | CRAP 원칙 체크 (contrast, repetition, alignment, proximity) | -| `suggestion` | string | 개선 제안 | -| `severity` | string | 심각도 (info, warning, critical) | - -#### C. 패턴 카드 (Pattern) - -반복 사용할 UI 패턴을 템플릿으로 등록한다. - -``` -┌──────────────────────────────┐ -│ 📐 검색 + 필터 + 목록 패턴 │ -├──────────────────────────────┤ -│ [패턴 와이어프레임 이미지] │ -├──────────────────────────────┤ -│ 사용처: │ -│ • 수주 목록 │ -│ • 거래처 목록 │ -│ • 품목 목록 │ -├──────────────────────────────┤ -│ 구성 요소: │ -│ ☑ 검색바 (상단 고정) │ -│ ☑ 필터 칩 (접기/펼치기) │ -│ ☑ 테이블 (정렬 가능) │ -│ ☑ 페이지네이션 (하단) │ -│ ☑ 액션 버튼 (우상단) │ -├──────────────────────────────┤ -│ 🏷️ 목록 CRUD 테이블 │ -│ 📊 사용빈도: ★★★★★ (12회) │ -└──────────────────────────────┘ -``` - -| 필드 | 타입 | 설명 | -|------|------|------| -| `image` | string (Base64) | 패턴 와이어프레임 | -| `usedIn` | string[] | 사용처 목록 | -| `components` | Component[] | 구성 요소 체크리스트 | -| `guidelines` | string | 사용 가이드라인 | -| `frequency` | number | 사용 빈도 | - -#### D. Before/After 카드 (Comparison) - -디자인 개선 전후를 비교한다. - -``` -┌──────────────────────────────────────────┐ -│ 🔄 거래처 상세 화면 리뉴얼 │ -├───────────────────┬──────────────────────┤ -│ ❌ Before │ ✅ After │ -│ [이전 스크린샷] │ [개선 스크린샷] │ -│ │ │ -├───────────────────┴──────────────────────┤ -│ 변경 포인트: │ -│ 1. 탭 구조 → 섹션 접기/펼치기 변경 │ -│ 2. 좌우 2컬럼 → 단일 컬럼 (모바일 대응) │ -│ 3. 저장 버튼 하단 고정 → 상단 sticky │ -├──────────────────────────────────────────┤ -│ 효과: 스크롤 40% 감소, 작업 완료 시간 단축 │ -│ 🏷️ 상세화면 폼 리뉴얼 │ -└──────────────────────────────────────────┘ -``` - -| 필드 | 타입 | 설명 | -|------|------|------| -| `beforeImage` | string (Base64) | 개선 전 스크린샷 | -| `afterImage` | string (Base64) | 개선 후 스크린샷 | -| `changes` | string[] | 변경 포인트 목록 | -| `effect` | string | 개선 효과 | - -### 4.2 공통 필드 - -모든 카드 유형이 공유하는 기본 필드: - -```json -{ - "id": "di_1709856000000_abc", - "type": "reference", - "title": "카드 제목", - "createdAt": "2026-03-08T10:00:00", - "updatedAt": "2026-03-08T15:30:00", - "tags": ["대시보드", "카드", "레이아웃"], - "category": "dashboard", - "pinned": false, - "archived": false -} -``` - -### 4.3 카테고리 (화면 유형별) - -| 카테고리 | 코드 | 설명 | -|---------|------|------| -| 대시보드 | `dashboard` | 통계, KPI, 차트 화면 | -| 목록 | `list` | 테이블, 검색, 필터 화면 | -| 상세/폼 | `form` | 입력, 편집, 상세 보기 | -| 모달/팝업 | `modal` | 모달 다이얼로그, 확인창 | -| 네비게이션 | `navigation` | 사이드바, 탭, 메뉴 | -| 로그인/온보딩 | `auth` | 인증, 초기 설정 | -| 보고서/인쇄 | `report` | 인쇄용, PDF 출력 화면 | -| 기타 | `etc` | 분류 불가 | - ---- - -## 5. 기능 상세 - -### 5.1 이미지 수집 - -| 기능 | 설명 | -|------|------| -| 파일 업로드 | 이미지 파일 선택 (PNG, JPG, GIF) | -| 클립보드 붙여넣기 | `Ctrl+V`로 스크린샷 즉시 붙여넣기 | -| 드래그 앤 드롭 | 이미지 파일을 카드 영역에 드롭 | - -> **Ctrl+V 붙여넣기가 핵심** — 스크린샷 캡처 후 즉시 카드 생성이 워크플로우의 핵심 - -### 5.2 어노테이션 (분석 카드) - -분석 카드에서 이미지 위에 마커를 추가하여 문제점이나 인사이트를 표시한다. - -| 어노테이션 유형 | 설명 | -|---------------|------| -| 번호 마커 (①②③) | 이미지 위 클릭 → 번호 자동 증가, 하단 설명과 연동 | -| 영역 하이라이트 | 드래그로 사각형 영역 표시 (반투명 컬러 오버레이) | -| 텍스트 메모 | 이미지 위 임의 위치에 짧은 메모 | - -> 기획디자인의 번호 마커(marker 블록) + Description 패널 패턴을 재활용 - -### 5.3 태그 시스템 - -| 기능 | 설명 | -|------|------| -| 자유 태그 | 카드에 자유 태그 추가 (콤마 구분 입력) | -| 태그 자동 완성 | 기존 태그 목록에서 자동 완성 | -| 태그 필터 | 사이드바에서 태그 클릭 → 해당 태그 카드만 표시 | -| 태그 색상 | 카테고리별 자동 색상 배정 | - -### 5.4 CRAP 디자인 원칙 체크리스트 - -분석 카드에서 사용하는 디자인 원칙 평가: - -| 원칙 | 체크 항목 | -|------|----------| -| **C**ontrast (대비) | 중요 요소가 시각적으로 구분되는가? | -| **R**epetition (반복) | 일관된 스타일이 반복 적용되는가? | -| **A**lignment (정렬) | 요소들이 논리적으로 정렬되어 있는가? | -| **P**roximity (근접성) | 관련 요소가 가까이 그룹핑되어 있는가? | - -추가 체크: - -| 원칙 | 체크 항목 | -|------|----------| -| 여백 (Whitespace) | 적절한 여백이 확보되어 있는가? | -| 계층 (Hierarchy) | 정보의 우선순위가 시각적으로 드러나는가? | -| 일관성 (Consistency) | 다른 화면과 일관된 패턴을 따르는가? | -| 접근성 (Accessibility) | 색상 대비, 폰트 크기가 충분한가? | - -### 5.5 검색 & 필터 - -| 기능 | 설명 | -|------|------| -| 텍스트 검색 | 제목, 메모, 태그에서 전문 검색 | -| 카테고리 필터 | 화면 유형별 필터 (탭) | -| 카드 유형 필터 | 레퍼런스 / 분석 / 패턴 / Before/After | -| 평점 필터 | ⭐ 3점 이상만 표시 등 | -| 정렬 | 최신순, 평점순, 이름순 | - -### 5.6 내보내기 - -| 형식 | 설명 | -|------|------| -| JSON | 전체 프로젝트 데이터 백업/복원 | -| HTML | 인사이트 카드를 HTML 보고서로 출력 (인쇄 가능) | -| 패턴 → 기획디자인 | 패턴 카드의 와이어프레임을 기획디자인 템플릿으로 전송 | - -### 5.7 키보드 단축키 - -| 단축키 | 기능 | -|--------|------| -| `Ctrl+V` | 클립보드 이미지로 새 카드 생성 | -| `Ctrl+S` | 프로젝트 저장 | -| `Ctrl+F` | 검색 포커스 | -| `Ctrl+N` | 새 카드 추가 | -| `Delete` | 선택 카드 삭제 | -| `Ctrl+Z` | 실행 취소 | -| `Ctrl+Y` | 다시 실행 | - ---- - -## 6. 데이터 구조 - -### 6.1 프로젝트 (localStorage: `di_projects`) - -```json -[ - { - "id": "diproj_1709856000000", - "title": "SAM ERP v2 디자인 연구", - "description": "SAM ERP 화면 개선을 위한 UI/UX 인사이트 수집", - "cards": [], - "createdAt": "2026-03-08T10:00:00", - "updatedAt": "2026-03-08T15:30:00" - } -] -``` - -### 6.2 인사이트 카드 (cards 배열 내) - -```json -{ - "id": "di_1709856000000_abc", - "type": "reference", - "title": "Notion 대시보드 카드 레이아웃", - "image": "data:image/png;base64,...", - "memo": "카드형 레이아웃이 정보 밀도를 유지하면서도 시각적으로 깔끔", - "source": "notion.so", - "tags": ["대시보드", "카드", "레이아웃"], - "category": "dashboard", - "rating": 4, - "pinned": false, - "archived": false, - "createdAt": "2026-03-08T10:00:00", - "updatedAt": "2026-03-08T15:30:00" -} -``` - -### 6.3 분석 어노테이션 - -```json -{ - "annotations": [ - { - "id": "ann_001", - "type": "marker", - "num": 1, - "x": 150, - "y": 80, - "text": "검색 영역 너무 넓음 — 접기 기능 필요" - }, - { - "id": "ann_002", - "type": "highlight", - "x": 200, - "y": 300, - "w": 150, - "h": 40, - "color": "rgba(239,68,68,0.3)", - "text": "버튼 정렬 불일치" - } - ] -} -``` - -### 6.4 디자인 패턴 라이브러리 (localStorage: `di_patterns`) - -프로젝트 간 공유되는 패턴 라이브러리: - -```json -[ - { - "id": "pat_001", - "name": "검색 + 필터 + 목록", - "image": "data:image/png;base64,...", - "components": [ - { "name": "검색바", "required": true }, - { "name": "필터 칩", "required": false }, - { "name": "데이터 테이블", "required": true }, - { "name": "페이지네이션", "required": true }, - { "name": "액션 버튼", "required": true } - ], - "guidelines": "검색바는 상단 고정, 필터는 접기/펼치기 지원", - "usedIn": ["수주 목록", "거래처 목록", "품목 목록"], - "tags": ["목록", "CRUD", "테이블"], - "frequency": 12, - "createdAt": "2026-03-08T10:00:00" - } -] -``` - ---- - -## 7. 프리셋 데이터 - -### 7.1 기본 카테고리 (하드코딩) - -```javascript -categories: [ - { code: 'dashboard', label: '대시보드', icon: '📊', color: '#6366f1' }, - { code: 'list', label: '목록', icon: '📋', color: '#3b82f6' }, - { code: 'form', label: '상세/폼', icon: '📝', color: '#10b981' }, - { code: 'modal', label: '모달/팝업', icon: '💬', color: '#f59e0b' }, - { code: 'navigation',label: '네비게이션',icon: '🧭', color: '#8b5cf6' }, - { code: 'auth', label: '로그인', icon: '🔐', color: '#ec4899' }, - { code: 'report', label: '보고서', icon: '📄', color: '#0ea5e9' }, - { code: 'etc', label: '기타', icon: '📎', color: '#64748b' }, -] -``` - -### 7.2 CRAP 원칙 체크리스트 (하드코딩) - -```javascript -designPrinciples: [ - { key: 'contrast', label: '대비 (Contrast)', icon: '🔲', desc: '중요 요소가 시각적으로 구분' }, - { key: 'repetition', label: '반복 (Repetition)', icon: '🔁', desc: '일관된 스타일 반복 적용' }, - { key: 'alignment', label: '정렬 (Alignment)', icon: '📏', desc: '논리적 정렬' }, - { key: 'proximity', label: '근접성 (Proximity)', icon: '🧲', desc: '관련 요소 그룹핑' }, - { key: 'whitespace', label: '여백 (Whitespace)', icon: '⬜', desc: '적절한 여백 확보' }, - { key: 'hierarchy', label: '계층 (Hierarchy)', icon: '🔺', desc: '정보 우선순위 시각화' }, - { key: 'consistency', label: '일관성 (Consistency)',icon: '🔗', desc: '다른 화면과의 일관성' }, - { key: 'a11y', label: '접근성 (A11y)', icon: '♿', desc: '색상 대비, 폰트 크기' }, -] -``` - -### 7.3 샘플 패턴 템플릿 (프리셋) - -| 패턴명 | 구성 요소 | SAM 내 사용처 | -|--------|----------|--------------| -| 검색 + 목록 | 검색바, 필터, 테이블, 페이지네이션, 액션버튼 | 수주/거래처/품목 목록 | -| 상세 폼 | 섹션 헤더, 라벨+입력, 저장/취소 버튼 | 수주 상세, 거래처 상세 | -| 대시보드 | 통계 카드 4개, 차트 2개, 요약 테이블 | 메인 대시보드 | -| 탭 레이아웃 | 탭 메뉴, 탭 콘텐츠, 액션 버튼 | 설정, 품목기준관리 | -| 트리 + 상세 | 좌측 트리, 우측 상세 패널 | 메뉴 관리, 조직도 | -| 모달 폼 | 모달 헤더, 입력 필드, 확인/취소 | 등록/수정 팝업 | -| 칸반 보드 | 컬럼 헤더, 드래그 카드, 필터 | 업무 관리 | -| 캘린더 | 월/주/일 뷰, 이벤트 카드, 필터 | 일정 관리, 근태 | - ---- - -## 8. 워크플로우 - -### 8.1 일반 사용 흐름 - -``` -1. 새 연구 프로젝트 생성 ("SAM ERP v2 디자인 연구") - ↓ -2. 레퍼런스 수집 - • 외부 서비스 스크린샷 → Ctrl+V 붙여넣기 - • SAM 기존 화면 스크린샷 → 파일 업로드 - • 태그 + 카테고리 분류 - ↓ -3. 화면 분석 - • 분석 카드 생성 → 어노테이션 추가 - • CRAP 원칙 체크 - • 개선 제안 작성 - ↓ -4. 패턴 추출 - • 반복되는 좋은 패턴 → 패턴 카드로 등록 - • 구성 요소 정리, 사용 가이드라인 작성 - ↓ -5. Before/After 기록 - • 개선 전후 비교 카드 생성 - • 변경 포인트 + 효과 기록 - ↓ -6. 기획디자인 연계 - • 패턴 라이브러리에서 참고하며 스토리보드 작성 -``` - -### 8.2 기획디자인 연계 - -``` -디자인 인사이트 기획디자인 -┌──────────────┐ ┌──────────────┐ -│ 패턴 카드: │ │ 스토리보드: │ -│ "검색+목록" │──참조──→│ 새 페이지에 │ -│ 구성요소 체크 │ │ 패턴 적용 │ -│ 가이드라인 │ │ │ -└──────────────┘ └──────────────┘ -``` - -> 향후 패턴 카드의 구성 요소를 기획디자인 블록 템플릿으로 자동 변환하는 연계 기능을 검토한다. - ---- - -## 9. 개발 로드맵 - -### Phase 1 — 기본 구조 (MVP) - -| 항목 | 내용 | -|------|------| -| 라우트 + 컨트롤러 | `GET /rd/design-insight` → 뷰 반환 | -| 프로젝트 CRUD | 생성/저장/로드/삭제 (localStorage) | -| 레퍼런스 카드 | 이미지 업로드 + 메모 + 태그 + 카테고리 | -| 보드 뷰 | 카드 격자 배열 기본 화면 | -| 검색/필터 | 텍스트 검색, 카테고리 탭 필터 | -| Ctrl+V 붙여넣기 | 클립보드 이미지 → 새 카드 자동 생성 | - -### Phase 2 — 분석 도구 - -| 항목 | 내용 | -|------|------| -| 분석 카드 | 어노테이션 시스템 (마커, 하이라이트) | -| CRAP 체크리스트 | 디자인 원칙 체크 UI | -| Before/After 카드 | 전후 비교 카드 유형 | -| 갤러리 뷰 | 이미지 중심 큰 썸네일 | -| 리스트 뷰 | 테이블형 정렬/필터 | - -### Phase 3 — 패턴 라이브러리 - -| 항목 | 내용 | -|------|------| -| 패턴 카드 | 구성 요소 체크리스트, 가이드라인 | -| 패턴 프리셋 | SAM ERP 기본 패턴 8종 | -| 패턴 공유 | 프로젝트 간 패턴 공유 (di_patterns) | -| 내보내기 | JSON 백업, HTML 보고서 | - -### Phase 4 — 연계 & 고도화 - -| 항목 | 내용 | -|------|------| -| 기획디자인 연계 | 패턴 → 블록 템플릿 변환 | -| DB 저장 전환 | localStorage → DB (협업 지원) | -| 팀 공유 | 다른 사용자와 인사이트 공유 | - ---- - -## 10. 파일 구조 (예상) - -``` -mng/ -├── app/Http/Controllers/ -│ └── RdController.php ← designInsight() 메서드 추가 -├── resources/views/rd/design-insight/ -│ └── index.blade.php ← 전체 CSS + HTML + Alpine.js -└── routes/web.php ← Route 추가 -``` - ---- - -## 11. 관련 문서 - -- [기획디자인 기술 스펙](../features/rd/planning-design.md) — 모티브가 된 스토리보드 에디터 -- [기획디자인 프로젝트](../projects/planning-design/README.md) — 프로젝트 이력 -- [R&D 메뉴 개요](../features/rd/README.md) — R&D 전체 메뉴 구조 - ---- - -**최종 업데이트**: 2026-03-08 diff --git a/sam/docs/plans/fire-shutter-drawing-generator-plan.md b/sam/docs/plans/fire-shutter-drawing-generator-plan.md deleted file mode 100644 index 1b9a680..0000000 --- a/sam/docs/plans/fire-shutter-drawing-generator-plan.md +++ /dev/null @@ -1,753 +0,0 @@ -# 방화셔터 도면생성 기능 기획서 - -> **작성일**: 2026-03-08 -> **상태**: 기획 초안 -> **위치**: MNG > R&D > 방화셔터 도면생성 -> **라우트**: `GET /rd/fire-shutter-drawing` -> **참고**: 기존 `자동도면 생성` (`/rd/auto-drawing`) 구조를 확장 - ---- - -## 1. 개요 - -### 1.1 목적 - -방화셔터의 **가이드레일 단면**과 **셔터박스(케이스) 형태**를 파라미터로 입력하면, **2D 단면도(SVG)**와 **3D 렌더링(Three.js)**을 실시간으로 생성하는 도구를 제공한다. - -### 1.2 핵심 가치 - -| 기존 (수동) | 개선 (SAM 도면생성) | -|-------------|-------------------| -| CAD 프로그램에서 수동 작도 | 파라미터 입력 → 자동 도면 생성 | -| 도면 수정 시 전체 재작업 | 치수 변경 → 실시간 미리보기 | -| 제품별 도면 관리 어려움 | 프리셋 저장/불러오기로 재활용 | -| 영업/설치팀 도면 요청 대기 | 현장에서 즉시 단면도 확인 가능 | - -### 1.3 대상 사용자 - -- 설계팀: 방화셔터 단면 설계 및 검토 -- 영업팀: 고객 제안 시 단면도/3D 이미지 첨부 -- 설치팀: 현장 설치 전 가이드레일/케이스 형태 확인 -- 생산팀: 절곡/제작 사양 확인 - ---- - -## 2. 방화셔터 핵심 구조 - -### 2.1 전체 구성도 - -``` -┌─────────────────── 천장 슬래브 ───────────────────┐ -│ │ -│ ┌──────────── 셔터박스 (HEAD BOX / CASE) ──────┐ │ -│ │ ┌─────┐ ┌─────┐ │ │ -│ │ │브래킷│ [샤프트+슬랫 감김] │브래킷│ │ │ -│ │ └──┬──┘ [모터+감속기+브레이크] └──┬──┘ │ │ -│ │ │ [밸런스 스프링] │ │ │ -│ └─────┼─────────────────────────────────┼──────┘ │ -│ │ │ │ -│ ┌─────┴─────┐ ┌──────┴─────┐ │ -│ │ 가이드레일 │ ← 슬랫 커튼 → │ 가이드레일 │ │ -│ │ (좌) │ (강판/스크린) │ (우) │ │ -│ │ │ │ │ │ -│ │ 연기차단재│ │연기차단재 │ │ -│ │ │ │ │ │ -│ └─────┬─────┘ └──────┬─────┘ │ -│ │ │ │ -│ ══════╧═══ 하장바 (BOTTOM BAR) ═════════╧═══════ │ -│ [고무 실링] │ -└────────────────── 바닥 ──────────────────────────┘ -``` - -### 2.2 주요 구성요소 상세 - -#### A. 가이드레일 (Guide Rail) - -- **형태**: C-채널 단면 (ㄷ자 형태) -- **재질**: 강판 2.3mm 이상 -- **기능**: 슬랫 커튼의 좌우 안내 + 연기 차단 -- **표준 길이**: 2,438mm / 3,305mm / 4,430mm (조합 사용) -- **수량**: 항상 **2개** (좌우 1쌍) -- **부속**: 연기차단재(Smoke Seal Packing), 앵커볼트 - -``` -가이드레일 단면 (상단에서 본 모습) - - ┌────────────┐ - │ │ ← 가이드레일 본체 (C-채널) - │ ┌──────┐ │ - │ │ 연기 │ │ - │ │ 차단 │ │ - │ │ 재 │ │ - │ │ │ │ - │ │슬랫 │ │ - │ │엣지→ ● │ - │ │ │ │ - │ │ 연기 │ │ - │ │ 차단 │ │ - │ │ 재 │ │ - │ └──────┘ │ - │ │ - └────────────┘ - ■■■■■■■■■■■■■ ← 방화벽 -``` - -**파라미터**: - -| 파라미터 | 설명 | 단위 | 기본값 | -|---------|------|------|--------| -| `rail_width` | 레일 전체 폭 | mm | 65 | -| `rail_depth` | 레일 깊이 (채널 깊이) | mm | 50 | -| `rail_thickness` | 강판 두께 | mm | 2.3 | -| `rail_lip` | 립(입구) 높이 | mm | 15 | -| `seal_thickness` | 연기차단재 두께 | mm | 5 | -| `seal_depth` | 연기차단재 깊이 | mm | 40 | -| `slat_thickness` | 슬랫 두께 (끼워지는 부분) | mm | 1.6 | -| `rail_height` | 레일 전체 높이 | mm | 3305 | -| `anchor_spacing` | 앵커볼트 간격 | mm | 500 | - -#### B. 셔터박스 / 케이스 (Head Box / Case) - -- **형태**: 직사각형 박스 (상부 천장 부착) -- **재질**: 강판 1.6mm 이상 -- **기능**: 샤프트/모터/슬랫 감김 수납 -- **표준 규격**: 1500×380mm / 500×380mm (개구부 크기에 따라) - -``` -셔터박스 단면 (정면에서 본 모습) - - ┌─────────────────────────────────────────┐ ← 상판 - │ │ - │ [브래킷] ┌──── 샤프트 ────┐ [브래킷] │ - │ │ │ (슬랫 감김) │ │ │ - │ ├──────┤ ├──────┤ │ - │ │ │ ◎ 중심축 │ │ │ - │ │ └───────────────┘ │ │ - │ │ │ │ - │ │ [모터+감속기] [브레이크] │ │ - │ │ [밸런스 스프링] │ │ - │ │ - └───┬─────────────────────────────────┬───┘ ← 하판 (슬랫 출구) - │ ↓ 슬랫 하강 ↓ │ - └─────────────────────────────────┘ -``` - -**파라미터**: - -| 파라미터 | 설명 | 단위 | 기본값 | -|---------|------|------|--------| -| `box_width` | 케이스 전체 폭 (= 개구부 폭 + 마진) | mm | 1500 | -| `box_height` | 케이스 높이 | mm | 380 | -| `box_depth` | 케이스 깊이 (전후) | mm | 380 | -| `box_thickness` | 케이스 강판 두께 | mm | 1.6 | -| `shaft_diameter` | 샤프트 직경 | mm | 120 | -| `shaft_offset_x` | 샤프트 중심 수평 오프셋 | mm | 0 | -| `shaft_offset_y` | 샤프트 중심 수직 오프셋 | mm | 0 | -| `motor_side` | 모터 위치 (좌/우) | - | 우 | -| `slat_exit_width` | 슬랫 출구 폭 | mm | 1400 | -| `bracket_width` | 브래킷 폭 | mm | 80 | - -#### C. 슬랫 (Steel Slat / Screen) - -- **강판형**: EGI 강판 1.6mm, C/S형 인터록킹 프로파일 -- **스크린형**: 실리카/와이어 원단, 가이드레일 11mm 홈 -- **피치**: 75~100mm - -**파라미터**: - -| 파라미터 | 설명 | 단위 | 기본값 | -|---------|------|------|--------| -| `slat_type` | 슬랫 유형 (강판/스크린) | - | 강판 | -| `slat_pitch` | 슬랫 피치 | mm | 80 | -| `slat_thickness` | 슬랫 두께 | mm | 1.6 | -| `slat_profile` | 단면 형태 (C형/S형) | - | C형 | - -#### D. 하장바 (Bottom Bar) - -- **기능**: 슬랫 커튼 하단 마감 + 바닥 밀착 -- **부속**: 고무 실링 - -**파라미터**: - -| 파라미터 | 설명 | 단위 | 기본값 | -|---------|------|------|--------| -| `bar_width` | 하장바 폭 | mm | 60 | -| `bar_height` | 하장바 높이 | mm | 40 | -| `bar_seal_height` | 고무 실링 높이 | mm | 15 | - ---- - -## 3. 기능 설계 - -### 3.1 탭 구성 - -기존 자동도면 생성의 탭 구조를 참고하여 4개 탭으로 구성한다. - -``` -┌──────────┬──────────┬──────────┬──────────┐ -│ 설정 │ 가이드 │ 셔터박스 │ 3D │ -│ Settings │ 레일 │ (케이스) │ 렌더링 │ -└──────────┴──────────┴──────────┴──────────┘ -``` - -| 탭 | ID | 기능 | -|----|----|------| -| **설정** | `Settings` | 제품 유형 선택, 개구부 크기, 전역 설정 | -| **가이드레일** | `GuideRail` | 가이드레일 단면 파라미터 입력 + SVG 단면도 실시간 미리보기 | -| **셔터박스** | `ShutterBox` | 셔터박스 단면 파라미터 입력 + SVG 단면도 실시간 미리보기 | -| **3D 렌더링** | `3D` | 전체 방화셔터 조립체 3D 렌더링 (Three.js) | - -### 3.2 설정 탭 (Settings) - -#### 입력 항목 - -| 항목 | 타입 | 설명 | -|------|------|------| -| 제품 유형 | 드롭다운 | 강판형 (KFS) / 스크린형 (KSS) | -| 제품 모델 | 드롭다운 | KSS01, KSS02, KFS01 등 (유형 선택 시 필터링) | -| 개구부 폭 (W0) | 숫자 입력 | mm | -| 개구부 높이 (H0) | 숫자 입력 | mm | -| 수량 | 숫자 입력 | 기본값 1 | - -#### 자동 계산 (표시 전용) - -| 항목 | 수식 | 설명 | -|------|------|------| -| 제작 폭 (W1) | 스크린: W0+140 / 강판: W0+110 | 마진 포함 | -| 제작 높이 (H1) | H0+350 | 마진 포함 | -| 면적 (M) | W1 × H1 / 1,000,000 | m² | -| 중량 (K) | 스크린: M×2 / 강판: M×25 | kg | -| 권장 모터 | K 기준 자동 선택 | 150K~1500K | - -#### 프리셋 관리 - -- **프리셋 저장**: 현재 파라미터를 이름 지정하여 localStorage에 저장 -- **프리셋 불러오기**: 저장된 프리셋 목록에서 선택하여 파라미터 복원 -- **기본 프리셋**: 강판형 기본, 스크린형 기본 (제품 유형 선택 시 자동 적용) - -### 3.3 가이드레일 탭 - -#### UI 구성 (2컬럼 레이아웃) - -``` -┌──────────────────────┬──────────────────────────────────┐ -│ 왼쪽: 파라미터 입력 │ 오른쪽: SVG 단면도 미리보기 │ -│ │ │ -│ ■ 레일 전체 폭: [65] │ │ -│ ■ 레일 깊이: [50] │ ┌────────┐ │ -│ ■ 강판 두께: [2.3] │ │ │ │ -│ ■ 립 높이: [15] │ │ ┌────┐ │ ← SVG 실시간 │ -│ ■ 연기차단재: [5/40] │ │ │ ● │ │ 렌더링 │ -│ ■ 슬랫 두께: [1.6] │ │ └────┘ │ │ -│ │ │ │ │ -│ [치수 표시 ON/OFF] │ └────────┘ │ -│ [연기차단재 ON/OFF] │ ← 치수 라벨 (mm) │ -│ │ │ -│ ■ 레일 높이: [3305] │ [줌 +] [줌 -] [리셋] [DXF 저장] │ -│ ■ 앵커 간격: [500] │ │ -└──────────────────────┴──────────────────────────────────┘ -``` - -#### SVG 단면도 렌더링 상세 - -**뷰 모드 3가지**: - -1. **횡단면도 (Cross-Section)**: 가이드레일을 위에서 본 단면 — 슬랫이 레일에 끼워진 형태 -2. **종단면도 (Longitudinal)**: 가이드레일을 측면에서 본 단면 — 앵커볼트 배치 -3. **정면도 (Front View)**: 가이드레일을 정면에서 본 모습 — 레일 전체 높이 + 앵커 위치 - -**렌더링 요소**: - -| 요소 | 색상 | 설명 | -|------|------|------| -| 레일 본체 | `#94a3b8` (은회색) | 강판 단면 | -| 연기차단재 | `#f97316` (주황) | 실링 재질 | -| 슬랫 엣지 | `#60a5fa` (파랑) | 레일 안의 슬랫 | -| 방화벽 | `#a1887f` (갈색 해칭) | 콘크리트 벽 | -| 앵커볼트 | `#ef4444` (빨강) | 고정 부속 | -| 치수선 | `#3b82f6` (파랑) | mm 단위 치수 | - -### 3.4 셔터박스 탭 - -#### UI 구성 (2컬럼 레이아웃) - -``` -┌──────────────────────┬──────────────────────────────────┐ -│ 왼쪽: 파라미터 입력 │ 오른쪽: SVG 단면도 미리보기 │ -│ │ │ -│ ■ 케이스 폭: [1500] │ ┌────────────────────────────┐ │ -│ ■ 케이스 높이: [380] │ │ [브래킷] ◎샤프트 [브래킷]│ │ -│ ■ 케이스 깊이: [380] │ │ 감김 슬랫 │ │ -│ ■ 강판 두께: [1.6] │ │ [모터+감속기] [브레이크] │ │ -│ │ └────────────────────────────┘ │ -│ ■ 샤프트 직경: [120] │ │ -│ ■ 샤프트 오프셋 │ ← SVG 실시간 렌더링 │ -│ X: [0] Y: [0] │ ← 치수 라벨 (mm) │ -│ ■ 모터 위치: [좌/우] │ │ -│ │ │ -│ ■ 내부 부품 표시 │ [줌 +] [줌 -] [리셋] [DXF 저장] │ -│ □ 샤프트 │ │ -│ □ 모터/감속기 │ │ -│ □ 브레이크 │ │ -│ □ 밸런스 스프링 │ │ -└──────────────────────┴──────────────────────────────────┘ -``` - -#### SVG 단면도 렌더링 상세 - -**뷰 모드 3가지**: - -1. **정면 단면도**: 케이스를 정면에서 본 내부 구조 (샤프트, 모터, 브래킷 위치) -2. **측면 단면도**: 케이스를 측면에서 본 단면 (깊이 방향, 슬랫 감김 단면) -3. **하부 상세도**: 슬랫 출구 부분 확대 - -**렌더링 요소**: - -| 요소 | 색상 | 설명 | -|------|------|------| -| 케이스 외곽 | `#94a3b8` (은회색) | 강판 박스 | -| 샤프트 | `#64748b` (짙은 회색) | 중심축 + 감김 슬랫 | -| 모터 | `#3b82f6` (파랑) | 전동 개폐기 | -| 브레이크 | `#ef4444` (빨강) | 전자 브레이크 | -| 스프링 | `#22c55e` (녹색) | 밸런스 스프링 | -| 브래킷 | `#8b5cf6` (보라) | 벽 고정 브래킷 | -| 슬랫 | `#f59e0b` (주황) | 감긴 슬랫 단면 | - -### 3.5 3D 렌더링 탭 - -#### 렌더링 대상 - -Three.js를 사용하여 방화셔터 전체 조립체를 3D로 시각화한다. - -``` -3D 렌더링 요소: -├── 셔터박스 (반투명 상자) -│ ├── 샤프트 (원통) -│ ├── 감긴 슬랫 (원통 표면) -│ ├── 모터+감속기 (박스) -│ ├── 브레이크 (디스크) -│ └── 브래킷 (L형 판) -├── 가이드레일 좌 (C-채널 압출) -├── 가이드레일 우 (C-채널 압출) -├── 슬랫 커튼 (평면 텍스처) -│ ├── 강판형: 줄무늬 텍스처 (인터록킹 표현) -│ └── 스크린형: 반투명 메쉬 -├── 하장바 (직사각형 바) -└── 방화벽 (반투명 콘크리트 텍스처) -``` - -#### 3D 인터랙션 - -| 기능 | 조작 | 설명 | -|------|------|------| -| 회전 | 마우스 드래그 | OrbitControls | -| 줌 | 마우스 휠 | 확대/축소 | -| 팬 | 우클릭 드래그 | 시점 이동 | -| 부품 하이라이트 | 마우스 호버 | 해당 부품 강조 + 이름 표시 | -| 부품 ON/OFF | 체크박스 | 개별 부품 표시/숨김 | -| 투명도 | 슬라이더 | 케이스 투명도 조절 (내부 구조 확인) | -| 셔터 개폐 | 슬라이더 | 0%(전개)~100%(전폐) 애니메이션 | -| 조명 | 프리셋 | 기본/스튜디오/야외/드라마틱 | - -#### 3D 모델링 방식 - -DB나 외부 3D 파일 없이, **파라미터 기반 절차적 모델링(Procedural Modeling)**으로 구현한다. - -```javascript -// 가이드레일 C-채널 3D 생성 예시 (Three.js ExtrudeGeometry) -function createGuideRailMesh(params) { - const shape = new THREE.Shape(); - // C-채널 프로파일 경로 정의 - shape.moveTo(0, 0); - shape.lineTo(params.rail_width, 0); - shape.lineTo(params.rail_width, params.rail_lip); - shape.lineTo(params.rail_width - params.rail_thickness, params.rail_lip); - shape.lineTo(params.rail_width - params.rail_thickness, params.rail_thickness); - shape.lineTo(params.rail_thickness, params.rail_thickness); - shape.lineTo(params.rail_thickness, params.rail_lip); - shape.lineTo(0, params.rail_lip); - shape.lineTo(0, 0); - - // 높이 방향으로 압출 - const extrudeSettings = { - depth: params.rail_height, - bevelEnabled: false - }; - - return new THREE.Mesh( - new THREE.ExtrudeGeometry(shape, extrudeSettings), - new THREE.MeshStandardMaterial({ color: 0x94a3b8 }) - ); -} -``` - -### 3.6 출력 기능 - -| 기능 | 형식 | 설명 | -|------|------|------| -| **DXF 다운로드** | `.dxf` | 가이드레일/셔터박스 단면도를 CAD 호환 파일로 저장 | -| **PNG 다운로드** | `.png` | SVG 단면도를 이미지로 저장 | -| **3D 스크린샷** | `.png` | 3D 렌더링 현재 뷰를 이미지로 저장 | -| **파라미터 JSON** | `.json` | 현재 설정값을 파일로 내보내기/가져오기 | - ---- - -## 4. 기술 설계 - -### 4.1 아키텍처 - -기존 자동도면 생성과 동일한 **순수 클라이언트 측** 아키텍처를 사용한다. - -``` -┌─────────────────────────────────────────────┐ -│ Browser (Client-Side Only) │ -│ │ -│ ┌─────────────────────────────────────┐ │ -│ │ Blade Template │ │ -│ │ (fire-shutter-drawing/index.blade) │ │ -│ ├─────────────────────────────────────┤ │ -│ │ JavaScript State Management │ │ -│ │ (fireShutterState 객체) │ │ -│ ├──────────┬──────────────────────────┤ │ -│ │ SVG 엔진 │ Three.js 3D 엔진 │ │ -│ │ (단면도) │ (조립체 렌더링) │ │ -│ ├──────────┴──────────────────────────┤ │ -│ │ DXF 생성기 │ PNG 내보내기 │ │ -│ └─────────────────────────────────────┘ │ -│ │ -│ DB 연동: 없음 (localStorage 프리셋만 사용) │ -│ API 호출: 없음 │ -└─────────────────────────────────────────────┘ -``` - -### 4.2 파일 구조 - -``` -mng/ -├── routes/web.php ← 라우트 추가 -├── app/Http/Controllers/RdController.php ← 메서드 추가 -└── resources/views/rd/fire-shutter-drawing/ - ├── index.blade.php ← 메인 레이아웃 + 탭 UI - ├── partials/ - │ ├── _settings.blade.php ← 설정 탭 HTML - │ ├── _guide-rail.blade.php ← 가이드레일 탭 HTML - │ ├── _shutter-box.blade.php ← 셔터박스 탭 HTML - │ └── _3d-viewer.blade.php ← 3D 렌더링 탭 HTML - └── js/ - (인라인 또는 @push('scripts')에 포함) -``` - -> **참고**: 기존 `auto-drawing/index.blade.php`는 단일 파일 4,884줄이다. 유지보수성을 위해 **Blade partial로 분리**하되, JavaScript는 상태 공유가 필요하므로 메인 파일의 `@push('scripts')`에 통합한다. - -### 4.3 상태 관리 객체 - -```javascript -const fireShutterState = { - // 활성 탭 - activeTab: 'Settings', - - // 설정 탭 - settings: { - productType: 'steel', // 'steel' | 'screen' - productModel: 'KFS01', // 제품 모델 코드 - openWidth: 2000, // 개구부 폭 W0 (mm) - openHeight: 3000, // 개구부 높이 H0 (mm) - quantity: 1, - // 자동 계산 - mfgWidth: 0, // 제작 폭 W1 - mfgHeight: 0, // 제작 높이 H1 - area: 0, // 면적 M (m²) - weight: 0, // 중량 K (kg) - motorSpec: '', // 권장 모터 - }, - - // 가이드레일 파라미터 - guideRail: { - width: 65, - depth: 50, - thickness: 2.3, - lip: 15, - sealThickness: 5, - sealDepth: 40, - slatThickness: 1.6, - height: 3305, - anchorSpacing: 500, - // 뷰 옵션 - showDimensions: true, - showSeal: true, - viewMode: 'cross', // 'cross' | 'longitudinal' | 'front' - }, - - // 셔터박스 파라미터 - shutterBox: { - width: 1500, - height: 380, - depth: 380, - thickness: 1.6, - shaftDiameter: 120, - shaftOffsetX: 0, - shaftOffsetY: 0, - motorSide: 'right', // 'left' | 'right' - slatExitWidth: 1400, - bracketWidth: 80, - // 내부 부품 표시 - showShaft: true, - showMotor: true, - showBrake: true, - showSpring: true, - viewMode: 'front', // 'front' | 'side' | 'bottom' - }, - - // 슬랫 파라미터 - slat: { - type: 'steel', // 'steel' | 'screen' - pitch: 80, - thickness: 1.6, - profile: 'C', // 'C' | 'S' - }, - - // 하장바 파라미터 - bottomBar: { - width: 60, - height: 40, - sealHeight: 15, - }, - - // 3D 뷰 설정 - threeD: { - caseOpacity: 0.3, // 케이스 투명도 - shutterPosition: 100, // 0=전개, 100=전폐 - showComponents: { - case: true, - shaft: true, - motor: true, - brake: true, - spring: true, - guideRailL: true, - guideRailR: true, - slats: true, - bottomBar: true, - wall: true, - }, - lightPreset: 'default', - }, - - // 프리셋 관리 - presets: [], // localStorage에서 로드 - - // 뷰 컨트롤 (줌/팬) - view: { - scale: 1, - offset: { x: 0, y: 0 }, - isDragging: false, - }, -}; -``` - -### 4.4 제품 유형별 기본값 매핑 - -```javascript -const PRODUCT_DEFAULTS = { - steel: { - label: '강판형', - marginW: 110, // W1 = W0 + 110 - marginH: 350, // H1 = H0 + 350 - weightFactor: 25, // K = M × 25 - guideRail: { width: 65, depth: 50, thickness: 2.3, lip: 15 }, - slat: { type: 'steel', pitch: 80, thickness: 1.6, profile: 'C' }, - }, - screen: { - label: '스크린형', - marginW: 140, // W1 = W0 + 140 - marginH: 350, // H1 = H0 + 350 - weightFactor: 2, // K = M × 2 - guideRail: { width: 30, depth: 25, thickness: 1.5, lip: 11 }, - slat: { type: 'screen', pitch: 100, thickness: 0.8, profile: 'flat' }, - }, -}; - -const MOTOR_TABLE = [ - { maxWeight: 150, spec: '150K', inch: 4 }, - { maxWeight: 300, spec: '300K', inch: 4 }, - { maxWeight: 500, spec: '500K', inch: 5 }, - { maxWeight: 750, spec: '750K', inch: 5 }, - { maxWeight: 1000, spec: '1000K', inch: 6 }, - { maxWeight: 1500, spec: '1500K', inch: 6 }, -]; -``` - ---- - -## 5. 개발 단계 - -### Phase 1: 기본 구조 + 가이드레일 단면도 (1단계) - -> **목표**: 라우트/컨트롤러/뷰 생성, 설정 탭, 가이드레일 SVG 단면도 - -| 작업 | 상세 | 예상 | -|------|------|------| -| 라우트 등록 | `GET /rd/fire-shutter-drawing` | 10분 | -| 컨트롤러 메서드 | `RdController@fireShutterDrawing` | 10분 | -| 레이아웃 + 탭 UI | 4탭 구조, 다크 테마 | 1시간 | -| 설정 탭 | 제품 유형/개구부 크기 입력 + 자동 계산 | 1시간 | -| 가이드레일 SVG 엔진 | C-채널 단면도 + 치수선 + 연기차단재 | 3시간 | -| 줌/팬 컨트롤 | 기존 auto-drawing 코드 재사용 | 30분 | - -**산출물**: 가이드레일 파라미터 입력 → SVG 횡단면도 실시간 렌더링 - -### Phase 2: 셔터박스 단면도 (2단계) - -> **목표**: 셔터박스(케이스) SVG 단면도 + 내부 부품 표시 - -| 작업 | 상세 | 예상 | -|------|------|------| -| 셔터박스 SVG 엔진 | 케이스 외곽 + 내부 구조 | 3시간 | -| 내부 부품 렌더링 | 샤프트, 모터, 브레이크, 스프링 | 2시간 | -| 뷰 모드 전환 | 정면/측면/하부 | 1시간 | -| 부품 ON/OFF 토글 | 체크박스 → SVG 요소 표시/숨김 | 30분 | - -**산출물**: 셔터박스 파라미터 입력 → SVG 단면도 (정면/측면/하부) - -### Phase 3: 3D 렌더링 (3단계) - -> **목표**: Three.js 기반 방화셔터 전체 조립체 3D 렌더링 - -| 작업 | 상세 | 예상 | -|------|------|------| -| Three.js 씬 구축 | 카메라, 조명, OrbitControls | 1시간 | -| 가이드레일 3D 모델 | ExtrudeGeometry (C-채널 압출) | 2시간 | -| 셔터박스 3D 모델 | BoxGeometry + 내부 부품 | 2시간 | -| 슬랫 커튼 3D 모델 | 평면 메쉬 + 텍스처 | 1시간 | -| 셔터 개폐 애니메이션 | 슬라이더 → 슬랫 위치 변경 | 1시간 | -| 조명/투명도 패널 | 기존 auto-drawing 패널 재사용 | 30분 | - -**산출물**: 파라미터 연동 3D 방화셔터 조립체 + 인터랙션 - -### Phase 4: 출력 + 프리셋 (4단계) - -> **목표**: DXF/PNG 저장, 프리셋 관리, 완성도 향상 - -| 작업 | 상세 | 예상 | -|------|------|------| -| DXF 내보내기 | 기존 DXF 생성기 확장 | 1시간 | -| PNG 내보내기 | SVG → Canvas → PNG | 30분 | -| 3D 스크린샷 | Three.js renderer.domElement.toDataURL | 15분 | -| 프리셋 저장/불러오기 | localStorage CRUD | 1시간 | -| JSON 가져오기/내보내기 | 파일 업로드/다운로드 | 30분 | -| UI 다듬기 | 반응형, 툴팁, 키보드 단축키 | 1시간 | - -**산출물**: 완성된 방화셔터 도면생성 도구 - ---- - -## 6. UI/UX 설계 - -### 6.1 디자인 시스템 - -기존 자동도면 생성의 **다크 테마 (Space Theme)**를 그대로 이어간다. - -| 요소 | 값 | -|------|------| -| 배경 | `#020617` (slate-950) | -| 패널 | `rgba(15, 23, 42, 0.7)` + backdrop-blur | -| 테두리 | `rgba(255, 255, 255, 0.1)` | -| 강조색 | `#3b82f6` (blue-500) | -| 텍스트 | `#f8fafc` (white) / `#94a3b8` (slate-400) | -| 입력 필드 | `bg-slate-950/80` + `border-slate-800` | - -### 6.2 반응형 레이아웃 - -``` -Desktop (1200px+): 2컬럼 (4:8 비율) -Tablet (768-1199px): 1컬럼 (상: 파라미터, 하: 미리보기) -Mobile: 지원 안 함 (최소 768px) -``` - -### 6.3 인터랙션 흐름 - -``` -사용자 → 제품 유형 선택 (강판/스크린) - → 기본값 자동 적용 - → 개구부 크기 입력 - → 제작 치수/중량/모터 자동 계산 - - → 가이드레일 탭 이동 - → 파라미터 조정 (폭, 깊이, 두께 등) - → SVG 실시간 업데이트 (입력 즉시) - → 뷰 모드 전환 (횡단면/종단면/정면) - → DXF 다운로드 가능 - - → 셔터박스 탭 이동 - → 파라미터 조정 - → SVG 실시간 업데이트 - → 내부 부품 ON/OFF - - → 3D 탭 이동 - → 전체 조립체 3D 뷰 - → 셔터 개폐 애니메이션 - → 스크린샷 저장 -``` - ---- - -## 7. 메뉴 등록 - -### 7.1 메뉴 위치 - -``` -R&D -├── 대시보드 -├── 조직도 관리 -├── 중대재해처벌법 점검 -├── AI 견적 -├── 기획디자인 -├── 디자인 인사이트 -├── 사운드 로고 스튜디오 -├── CM송 제작 -├── 자동도면 생성 ← 기존 -└── 방화셔터 도면생성 ← 신규 (자동도면 하위에 배치) -``` - -### 7.2 메뉴 등록 (tinker) - -```php -// 개발 서버 -App\Models\Commons\Menu::create([ - 'tenant_id' => 1, - 'parent_id' => , - 'name' => '방화셔터 도면생성', - 'url' => '/rd/fire-shutter-drawing', - 'icon' => 'shield', - 'sort_order' => <자동도면 다음 순서>, - 'is_active' => true, -]); -``` - -> **주의**: 메뉴 시더 실행 금지 — tinker로 수동 등록 - ---- - -## 8. 향후 확장 가능성 - -| 확장 | 설명 | 우선순위 | -|------|------|---------| -| **STL/OBJ 내보내기** | 3D 프린팅/CAD 호환 | 🟡 중요 | -| **견적 연동** | 도면 파라미터 → 견적 자동 산출 | 🔴 필수 | -| **제품 카탈로그 연동** | DB에서 제품별 기본 파라미터 로드 | 🟡 중요 | -| **비교 모드** | 2개 설정을 나란히 비교 | 🟢 권장 | -| **PDF 도면 출력** | A3/A4 도면 양식 포함 출력 | 🟡 중요 | -| **설치 시뮬레이션** | 현장 사진 위에 3D 오버레이 | 🟢 권장 | - ---- - -## 관련 문서 - -- `/home/aweso/sam/docs/features/academy/fire-shutter-image-prompts.md` — 방화셔터 이미지 프롬프트 -- `/home/aweso/sam/docs/samples/방화셔터_견적구조_인터뷰.md` — 견적 구조 인터뷰 -- `/home/aweso/sam/docs/features/quotes/README.md` — 견적 시스템 분석 -- `/home/aweso/sam/docs/projects/quotation/phase-1-5130-analysis/js-formulas.md` — 견적 수식 상세 -- `/home/aweso/sam/mng/resources/views/rd/auto-drawing/index.blade.php` — 기존 자동도면 생성 - ---- - -**최종 업데이트**: 2026-03-08 diff --git a/sam/docs/plans/sound-logo-generator-plan.md b/sam/docs/plans/sound-logo-generator-plan.md deleted file mode 100644 index a3ecf48..0000000 --- a/sam/docs/plans/sound-logo-generator-plan.md +++ /dev/null @@ -1,637 +0,0 @@ -# 사운드 로고 생성기 — 기획서 - -> **작성일**: 2026-03-08 -> **상태**: 기획 확정 -> **메뉴명**: 사운드 로고 생성기 -> **라우트**: `GET /rd/sound-logo` -> **담당**: R&D실 - ---- - -## 1. 개요 - -### 1.1 목적 - -1~5초의 **짧고 강렬한 시그니처 사운드(Sound Logo)**를 생성하는 도구. 브라우저 내 Web Audio API 신디사이저와 Google Gemini AI를 결합하여, 누구나 전문적인 사운드 로고를 만들 수 있도록 한다. - -### 1.2 벤치마킹 - -| 브랜드 | 사운드 | 길이 | 특징 | -|--------|--------|------|------| -| Intel | 봉-봉봉봉-봉 | 1.5초 | 5음, 밝고 미래적 | -| Netflix | 타-둠 | 3초 | 2음, 깊은 울림 + 리버브 | -| Samsung | 오버더호라이즌 | 2초 | 5음, 따뜻한 멜로디 | -| McDonald's | 바다바바~ | 2초 | 5음, 경쾌한 리듬 | -| Windows | 시작 사운드 | 3초 | 4음, 화음 진행 | -| 카카오톡 | 카톡~ | 0.5초 | 2음, 귀여운 효과음 | -| T-Mobile | 띠-띠띠-띠-띠 | 1초 | 5음, 단순 반복 | - -### 1.3 핵심 차별점 — AI 어드바이저 엔진 - -단순 신디사이저 도구가 아니라, **Google Gemini AI가 음악 이론 기반으로 조언하고 생성을 도와주는** 지능형 도구. - -``` -┌─────────────────────────────────────────────────────┐ -│ 사운드 로고 생성기 │ -│ │ -│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ -│ │ 수동 모드 │ │ AI 어시스트│ │ AI 자동 │ │ -│ │ (신디사이저)│ ←→ │ (Gemini) │ ←→ │ (Lyria) │ │ -│ │ │ │ │ │ │ │ -│ │ 음표 직접 │ │ 브랜드 분석│ │ 프롬프트→ │ │ -│ │ 배치/편집 │ │ 음악 추천 │ │ AI 음악 │ │ -│ │ │ │ 코드 제안 │ │ 직접 생성 │ │ -│ └──────────┘ └──────────┘ └──────────┘ │ -│ ↕ ↕ ↕ │ -│ ┌──────────────────────────────────────────┐ │ -│ │ Web Audio API 재생 엔진 │ │ -│ │ (실시간 미리듣기 + WAV 내보내기) │ │ -│ └──────────────────────────────────────────┘ │ -└─────────────────────────────────────────────────────┘ -``` - ---- - -## 2. 3가지 모드 설계 - -### 2.1 모드 A — 수동 모드 (신디사이저) - -> 음표를 직접 배치하고 파라미터를 조절하여 사운드를 만드는 전통적 방식 - -| 기능 | 설명 | -|------|------| -| 음표 시퀀서 | 음표(C4, E4 등) + 길이(0.05~2초) + 쉼표를 시각적 배열로 편집 | -| 신디사이저 4종 | Sine(부드러움), Square(8bit), Triangle(따뜻함), Sawtooth(날카로움) | -| ADSR 엔벨로프 | Attack(0~500ms), Decay(0~1s), Sustain(0~1), Release(0~3s) | -| 화음(Chord) | 동시에 여러 음 재생 (C+E+G = C Major 등) | -| 이펙트 | 리버브, 딜레이, 로우패스/하이패스 필터 | -| 파형 시각화 | Canvas 실시간 파형 + 스펙트럼 표시 | - -**기술 기반**: Web Audio API (`OscillatorNode`, `GainNode`, `BiquadFilterNode`, `ConvolverNode`) - -### 2.2 모드 B — AI 어시스트 (Gemini 텍스트) - -> 브랜드 정보를 입력하면 Gemini가 **음악 이론 기반으로 사운드 로고를 설계**해 주고, 사용자가 미세 조정 - -**입력 → AI 분석 → 음표 데이터 출력 → Web Audio 재생** - -``` -사용자 입력 Gemini 분석·추천 출력 -┌───────────────┐ ┌──────────────────────┐ ┌──────────────┐ -│ 브랜드명 │ │ │ │ │ -│ 업종/분위기 │──요청──→ │ 1. 브랜드 성격 분석 │──JSON──→ │ 음표 시퀀스 │ -│ 키워드 │ │ 2. 조성/스케일 추천 │ │ BPM, 조성 │ -│ 참고 브랜드 │ │ 3. 음표 시퀀스 생성 │ │ 신디 파라미터 │ -│ 원하는 느낌 │ │ 4. ADSR 파라미터 제안 │ │ ADSR 값 │ -└───────────────┘ │ 5. 이펙트 추천 │ │ 이펙트 설정 │ - │ 6. 근거 설명 │ │ │ - └──────────────────────┘ └──────────────┘ - ↓ - Web Audio 재생 - ↓ - 사용자 미세 조정 -``` - -**Gemini 프롬프트 설계**: - -``` -당신은 사운드 브랜딩 전문가이자 음악 이론가입니다. -다음 브랜드 정보를 분석하여 1~5초 사운드 로고를 설계해 주세요. - -[브랜드 정보] -- 브랜드명: {name} -- 업종: {industry} -- 브랜드 성격: {personality} (예: 혁신적, 신뢰, 친근함) -- 참고 사운드: {reference} (예: 인텔처럼 밝은 느낌) -- 원하는 길이: {duration}초 - -[응답 형식 - 반드시 JSON으로] -{ - "analysis": "브랜드 분석 설명 (한글)", - "reasoning": "이 사운드를 추천하는 음악 이론적 근거 (한글)", - "key": "C", - "scale": "major", - "bpm": 120, - "synth": "sine", - "adsr": { "attack": 0.01, "decay": 0.1, "sustain": 0.7, "release": 0.5 }, - "effects": { "reverb": 0.3, "delay": 0 }, - "notes": [ - { "note": "C5", "duration": 0.2, "velocity": 0.8 }, - { "note": "E5", "duration": 0.2, "velocity": 0.9 }, - { "note": "G5", "duration": 0.15, "velocity": 0.7 }, - { "rest": 0.05 }, - { "chord": ["C5", "E5", "G5"], "duration": 0.8, "velocity": 1.0 } - ], - "variations": [ - { "name": "밝은 버전", "notes": [...] }, - { "name": "차분한 버전", "notes": [...] } - ] -} -``` - -**AI 어시스트 기능 상세**: - -| 기능 | 설명 | -|------|------| -| 브랜드 분석 | 업종·성격 기반 적합한 조성/템포/음색 추천 | -| 음표 시퀀스 생성 | 음악 이론(화성학, 리듬 패턴) 기반 멜로디 제안 | -| 변형 3종 제공 | 밝은/차분한/임팩트 버전 동시 생성 | -| 근거 설명 | "C Major → 신뢰감, 5도 상행 → 상승 에너지" 등 이론 설명 | -| 반복 개선 | "좀 더 밝게" "더 짧게" 등 자연어로 수정 요청 | - -### 2.3 모드 C — AI 자동 생성 (Google Lyria) - -> Google Lyria AI가 프롬프트 기반으로 **실제 음악을 직접 생성** - -**2가지 Lyria 엔진 지원** (기존 API 키로 사용 가능, 별도 발급 불필요): - -| 엔진 | 인증 | 방식 | 특징 | -|------|------|------|------| -| **Lyria RealTime** (권장) | 기존 Gemini API 키 | WebSocket (브라우저 직접) | 실시간 스트리밍, BPM/스케일 실시간 조절 | -| Lyria 2 (폴백) | Vertex AI 서비스 계정 | REST API (서버 경유) | 30초 단위 파일 생성, $0.06/30초 | - -#### Lyria RealTime — 브라우저에서 직접 음악 생성 - -``` -브라우저 (Alpine.js) Google API -┌───────────────────┐ ┌──────────────────┐ -│ BPM: 130 │ │ │ -│ Scale: C Major │──WebSocket 연결──→ │ Lyria RealTime │ -│ 프롬프트 입력 │ │ (lyria-realtime- │ -│ │←─2초 단위 오디오── │ exp) │ -│ 🔊 실시간 재생 │ │ │ -│ BPM 슬라이더 조절 │──실시간 파라미터──→ │ 즉시 반영 │ -└───────────────────┘ └──────────────────┘ -``` - -- **모델**: `lyria-realtime-exp` (experimental, Gemini API v1alpha) -- **인증**: 기존 `.env`의 `GEMINI_API_KEY` 그대로 사용 -- **출력**: 48kHz 스테레오, 2초 청크 단위 스트리밍 -- **제어 파라미터**: BPM(60~200), Scale(Key + Mode), 텍스트 프롬프트 -- **지연**: 파라미터 변경 후 최대 2초 이내 반영 - -**Lyria RealTime 프롬프트 예시**: - -``` -Short sonic logo. Bright, futuristic, memorable melody. -Clean synthesizer with light reverb. -Ascending progression, major chord resolution. -``` - -#### Lyria 2 — 서버 경유 파일 생성 (폴백) - -기존 `BgmService::generateWithLyria()` 패턴 재활용. Vertex AI 서비스 계정(`google_service_account.json`) 이미 보유. - -``` -사용자 입력 서버 (Laravel) 결과 -┌───────────────┐ ┌──────────────────────┐ ┌──────────────┐ -│ 분위기 선택 │ │ SoundLogoService │ │ │ -│ 길이 (1~5초) │──POST──→ │ → Lyria 2 API (REST) │──→ │ WAV/MP3 파일 │ -│ 프롬프트 입력 │ │ (Vertex AI) │ │ (다운로드) │ -└───────────────┘ └──────────────────────┘ └──────────────┘ -``` - -> **우선순위**: Lyria RealTime(브라우저) 먼저 시도 → 실패 시 Lyria 2(서버) 폴백. -> 두 엔진 모두 기존 인증 정보로 사용 가능하며 별도 API 키 발급 불필요. - ---- - -## 3. UI 레이아웃 - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ 🎵 사운드 로고 생성기 [내 프로젝트 ▾] [저장] │ -├─────────────────────────────────────────────────────────────────┤ -│ │ -│ 모드: [🎹 수동] [🤖 AI 어시스트] [✨ AI 자동] │ -│ │ -│ ┌─ 모드 B: AI 어시스트 ──────────────────────────────────────┐ │ -│ │ │ │ -│ │ 브랜드명 [SAM ] │ │ -│ │ 업종 [ERP/MES 통합 솔루션 ] │ │ -│ │ 브랜드 성격 [○혁신적 ●신뢰 ○친근 ○고급 ○에너지] │ │ -│ │ 참고 사운드 [인텔처럼 짧고 밝은 ▾ ] │ │ -│ │ 길이 [━━━●━━━ 2초 ] │ │ -│ │ │ │ -│ │ [🤖 AI에게 사운드 설계 요청] │ │ -│ │ │ │ -│ │ ┌─ AI 분석 결과 ─────────────────────────────────────┐ │ │ -│ │ │ 💡 "SAM은 ERP/MES 통합 솔루션으로, 신뢰와 기술력을 │ │ │ -│ │ │ 전달해야 합니다. C Major 조성으로 안정감을, │ │ │ -│ │ │ 5도 상행 진행으로 성장과 발전을 표현합니다." │ │ │ -│ │ │ │ │ │ -│ │ │ 추천: C Major | BPM 130 | Sine + 리버브 30% │ │ │ -│ │ │ │ │ │ -│ │ │ 변형 3종: │ │ │ -│ │ │ [▶ 밝은 버전] [▶ 차분한 버전] [▶ 임팩트 버전] │ │ │ -│ │ └─────────────────────────────────────────────────────┘ │ │ -│ │ │ │ -│ │ 💬 추가 요청: [좀 더 짧고 강렬하게 해줘 ] [전송] │ │ -│ └─────────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌─ 음표 에디터 (AI 결과 또는 수동 편집) ──────────────────────┐ │ -│ │ C5(0.2s) E5(0.2s) G5(0.15s) .(0.05s) [CEG](0.8s) │ │ -│ │ ████ ████ ███ · ████████████ │ │ -│ │ [+음표] [+쉼표] [+화음] [삭제] │ │ -│ └────────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌─ 파라미터 ────────────────────────────────────────────────┐ │ -│ │ 음색: ●Sine ○Square ○Triangle ○Sawtooth │ │ -│ │ BPM: ━━━━━━●━━━━━ 130 │ │ -│ │ 리버브: ━━━●━━━━━━━ 30% │ │ -│ │ Attack: ━●━━━━━━━━ 10ms Release: ━━━━━●━━━ 500ms │ │ -│ └────────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌─ 파형 시각화 ─────────────────────────────────────────────┐ │ -│ │ ∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿ │ │ -│ └────────────────────────────────────────────────────────────┘ │ -│ │ -│ [▶ 재생] [⏹ 정지] [💾 WAV 저장] [📋 JSON 내보내기] │ -│ │ -├─ 내 사운드 라이브러리 ──────────────────────────────────────────┤ -│ 🎵 SAM 시그널 v1 | 🎵 알림음 v2 | 🎵 전환 효과 | [+ 새로] │ -└─────────────────────────────────────────────────────────────────┘ -``` - ---- - -## 4. 프리셋 템플릿 (10종) - -| 프리셋 | 스타일 | 음표 수 | 길이 | 용도 | -|--------|--------|---------|------|------| -| 기업 시그널 (밝음) | Intel 스타일 | 5 | 1.5초 | 브랜드 인트로 | -| 기업 시그널 (무게감) | Netflix 스타일 | 2 | 3초 | 프리미엄 브랜드 | -| 알림음 (경쾌) | 카카오톡 스타일 | 2~3 | 0.5초 | 푸시 알림 | -| 알림음 (정보) | Slack 스타일 | 3 | 1초 | 시스템 알림 | -| 성공 사운드 | 게임 레벨업 | 4 | 1초 | 작업 완료 | -| 에러 사운드 | 경고음 | 2 | 0.5초 | 오류 알림 | -| 전환 효과 (업) | 상승 스윕 | 연속 | 0.5초 | 화면 전환 | -| 전환 효과 (다운) | 하강 스윕 | 연속 | 0.5초 | 메뉴 닫기 | -| 팡파레 | 축하 | 6 | 2초 | 이벤트/달성 | -| 로딩 루프 | 반복 패턴 | 4 | 2초 | 대기 상태 | - ---- - -## 5. 기술 아키텍처 - -### 5.1 기술 스택 - -| 계층 | 기술 | 설명 | -|------|------|------| -| 프론트엔드 | Blade + Alpine.js | 단일 파일 SPA (디자인 인사이트 패턴) | -| 오디오 엔진 | Web Audio API | `OscillatorNode`, `GainNode`, `ConvolverNode` | -| 시각화 | Canvas API | `AnalyserNode` → 파형/스펙트럼 렌더링 | -| AI 어시스트 | Gemini 2.5 Flash | 텍스트 기반 음악 이론 분석·추천 (모드 B) | -| AI 자동 생성 (1차) | Lyria RealTime | WebSocket 실시간 음악 스트리밍 (모드 C, 브라우저 직접) | -| AI 자동 생성 (폴백) | Lyria 2 (Vertex AI) | REST API 파일 생성 (모드 C, 서버 경유) | -| 저장 | localStorage + DB | 프로젝트 데이터(localStorage), 음원 파일(DB+Storage) | - -### 5.2 기존 인프라 재활용 - -| 기존 코드 | 재활용 내용 | -|----------|-----------| -| `BgmService::generateWithLyria()` | Lyria API 호출 패턴, Vertex AI 인증 흐름 | -| `BgmService::getMoodChord()` | 분위기별 화음 주파수 매핑 | -| `BgmService::generateAmbient()` | FFmpeg 기반 오디오 합성 (서버사이드 폴백) | -| `CmSongController::generateLyrics()` | Gemini API 호출 패턴 (프롬프트 → JSON 응답) | -| `CmSongController::pcmToWav()` | PCM → WAV 변환 유틸리티 | -| `AiConfig::getActiveGemini()` | AI 설정 조회 (API 키, 모델, 리전) | -| `GoogleCloudService::getAccessToken()` | Vertex AI 인증 토큰 | - -### 5.3 파일 구조 - -``` -app/Http/Controllers/Rd/ -└── SoundLogoController.php # 컨트롤러 (AI API 프록시) - -app/Services/Rd/ -└── SoundLogoService.php # Gemini 프롬프트 + Lyria 호출 - -resources/views/rd/sound-logo/ -└── index.blade.php # 단일 파일 SPA - -routes/web.php # 라우트 추가 -``` - -### 5.4 라우트 설계 - -| Method | Path | 컨트롤러 | 설명 | -|--------|------|---------|------| -| `GET` | `/rd/sound-logo` | `soundLogo.index` | 메인 페이지 | -| `POST` | `/rd/sound-logo/ai-assist` | `soundLogo.aiAssist` | Gemini 음악 설계 요청 (모드 B) | -| `POST` | `/rd/sound-logo/ai-refine` | `soundLogo.aiRefine` | Gemini 추가 수정 요청 | -| `POST` | `/rd/sound-logo/ai-generate` | `soundLogo.aiGenerate` | Lyria 음악 생성 (모드 C) | -| `POST` | `/rd/sound-logo/save` | `soundLogo.save` | 사운드 저장 (DB + Storage) | -| `GET` | `/rd/sound-logo/{id}/download` | `soundLogo.download` | WAV 다운로드 | - -### 5.5 Web Audio API 핵심 구조 - -```javascript -// 노드 그래프 -const ctx = new AudioContext(); - -// Oscillator → Gain(ADSR) → Filter → Reverb → Analyser → Destination -function createSynthChain(type, freq, adsr, effects) { - const osc = ctx.createOscillator(); // 음원 - const gain = ctx.createGain(); // ADSR 엔벨로프 - const filter = ctx.createBiquadFilter(); // LP/HP 필터 - const analyser = ctx.createAnalyser(); // 시각화 - - osc.type = type; // sine | square | triangle | sawtooth - osc.frequency.value = freq; // Hz - - // ADSR - const now = ctx.currentTime; - gain.gain.setValueAtTime(0, now); - gain.gain.linearRampToValueAtTime(1, now + adsr.attack); - gain.gain.linearRampToValueAtTime(adsr.sustain, now + adsr.attack + adsr.decay); - - osc.connect(gain).connect(filter).connect(analyser).connect(ctx.destination); - return { osc, gain, filter, analyser }; -} - -// WAV 내보내기 (OfflineAudioContext) -async function exportWav(notes, params) { - const offline = new OfflineAudioContext(2, 44100 * duration, 44100); - // ... 노트 렌더링 - const buffer = await offline.startRendering(); - const wav = audioBufferToWav(buffer); - // Blob → 다운로드 -} -``` - -### 5.6 음표 ↔ 주파수 매핑 - -```javascript -const NOTE_FREQ = { - 'C3': 130.81, 'D3': 146.83, 'E3': 164.81, 'F3': 174.61, - 'G3': 196.00, 'A3': 220.00, 'B3': 246.94, - 'C4': 261.63, 'D4': 293.66, 'E4': 329.63, 'F4': 349.23, - 'G4': 392.00, 'A4': 440.00, 'B4': 493.88, - 'C5': 523.25, 'D5': 587.33, 'E5': 659.25, 'F5': 698.46, - 'G5': 783.99, 'A5': 880.00, 'B5': 987.77, - 'C6': 1046.50 - // 반음(#/b)도 포함 -}; -``` - ---- - -## 6. Phase별 개발 계획 - -### Phase 1 — MVP (수동 모드 + 프리셋) - -| 항목 | 내용 | -|------|------| -| 음표 시퀀서 UI | 음표 추가/삭제/편집, 드래그 순서 변경 | -| 신디사이저 4종 | Sine, Square, Triangle, Sawtooth | -| ADSR 슬라이더 | Attack, Decay, Sustain, Release | -| 실시간 재생 | Web Audio API 즉시 재생 | -| WAV 내보내기 | OfflineAudioContext → WAV 다운로드 | -| 프리셋 10종 | 즉시 로드 가능한 사운드 패턴 | -| 프로젝트 저장 | localStorage (디자인 인사이트 패턴) | - -### Phase 2 — AI 어시스트 (Gemini) - -| 항목 | 내용 | -|------|------| -| 브랜드 입력 폼 | 브랜드명, 업종, 성격, 참고 사운드, 길이 | -| Gemini 분석 API | 브랜드 → 음악 이론 기반 사운드 설계 JSON | -| 변형 3종 생성 | 밝은/차분한/임팩트 버전 동시 제공 | -| 대화형 개선 | "좀 더 밝게" 등 자연어 추가 수정 | -| 근거 표시 | AI가 이 사운드를 추천하는 이유 설명 | -| 라우트 | `POST /rd/sound-logo/ai-assist`, `ai-refine` | - -### Phase 3 — AI 자동 생성 (Lyria RealTime + Lyria 2) + 고도화 - -| 항목 | 내용 | -|------|------| -| Lyria RealTime 연동 | WebSocket으로 브라우저에서 직접 실시간 음악 생성 (기존 Gemini API 키) | -| Lyria 2 폴백 | Vertex AI REST API로 서버 경유 파일 생성 (기존 서비스 계정) | -| 실시간 BPM/스케일 조절 | Lyria RealTime의 파라미터 실시간 변경 | -| 화음(Chord) 편집 | 동시에 여러 음 배치 | -| 이펙트 체인 | 리버브, 딜레이, 필터 | -| 파형 시각화 | Canvas 실시간 파형 + 스펙트럼 | -| DB 저장 | 사운드 로고를 DB + Storage에 영구 저장 | -| 공유/내보내기 | JSON 설정 공유, MP3 변환 | - -### Phase 4 — 프로급 확장 (선택) - -| 항목 | 내용 | -|------|------| -| 타임라인 UI | 드래그로 음표 배치하는 DAW 스타일 | -| 샘플 기반 음색 | 피아노, 벨, 마림바 등 실제 악기 | -| 드럼/퍼커션 | 노이즈 기반 킥/스네어/하이햇 | -| MIDI 내보내기 | 전문 DAW에서 추가 편집 가능 | -| A/B 비교 | 두 사운드를 나란히 비교 재생 | - ---- - -## 7. Gemini AI 연동 상세 - -### 7.1 API 호출 흐름 - -``` -Frontend (Alpine.js) - │ - │ POST /rd/sound-logo/ai-assist - │ { brand_name, industry, personality, reference, duration } - │ - ▼ -SoundLogoController::aiAssist() - │ - │ 프롬프트 구성 - │ - ▼ -Gemini 2.5 Flash API - │ - │ JSON 응답 (notes, adsr, effects, analysis) - │ - ▼ -SoundLogoController → JsonResponse - │ - │ { success: true, data: { notes, params, analysis, variations } } - │ - ▼ -Frontend: 음표 에디터에 자동 로드 → 즉시 재생 -``` - -### 7.2 대화형 개선 흐름 - -``` -사용자: "좀 더 짧고 강렬하게" - │ - ▼ -POST /rd/sound-logo/ai-refine -{ previous_notes: [...], feedback: "좀 더 짧고 강렬하게" } - │ - ▼ -Gemini: 기존 노트를 분석하고 피드백 반영하여 수정된 JSON 반환 - │ - ▼ -수정된 음표가 에디터에 반영 -``` - -### 7.3 Lyria 음악 생성 흐름 - -#### 7.3.1 Lyria RealTime (브라우저 직접, 권장) - -``` -사용자: "AI 자동 생성" 탭 → Lyria RealTime 선택 - │ - ▼ -브라우저 JavaScript (Alpine.js) - │ - │ WebSocket 연결 (Gemini API v1alpha) - │ wss://generativelanguage.googleapis.com/ws/google.ai.generativelanguage.v1alpha.GenerativeService.BidiGenerateContent - │ API Key: .env GEMINI_API_KEY (서버 경유 프록시) - │ Model: lyria-realtime-exp - │ - ▼ -Lyria RealTime 스트리밍 - │ - │ 2초 청크 단위 48kHz 스테레오 오디오 - │ ← BPM/Scale 실시간 조절 가능 - │ - ▼ -Web Audio API로 실시간 재생 + 녹음(MediaRecorder) → WAV 저장 -``` - -> **API 키 보안**: 브라우저에서 직접 Gemini API 키를 노출하지 않기 위해, -> 서버를 WebSocket 프록시로 사용하거나 `/rd/sound-logo/ws-token` 엔드포인트에서 -> 임시 토큰을 발급하는 방식을 검토한다. - -#### 7.3.2 Lyria 2 (서버 경유, 폴백) - -``` -사용자: Lyria RealTime 실패 시 자동 전환 - │ - ▼ -POST /rd/sound-logo/ai-generate -{ mood: "bright_futuristic", duration: 3, prompt: "..." } - │ - ▼ -SoundLogoService::generateWithLyria() - ├── AiConfig::getActiveGemini() → Vertex AI 설정 확인 - ├── GoogleCloudService::getAccessToken() → OAuth 토큰 - └── Lyria API 호출 → audioContent (base64) - │ - ▼ -WAV 파일 저장 → 다운로드 URL 반환 -``` - ---- - -## 8. 데이터 모델 - -### 8.1 localStorage 구조 (Phase 1~2) - -```json -{ - "sl_projects": [ - { - "id": "sl_1709000000_abc", - "title": "SAM 사운드 로고", - "sounds": [ - { - "id": "snd_001", - "name": "SAM 시그널 v1", - "notes": [ - { "note": "C5", "duration": 0.2, "velocity": 0.8 }, - { "note": "E5", "duration": 0.2, "velocity": 0.9 }, - { "chord": ["C5", "E5", "G5"], "duration": 0.8, "velocity": 1.0 } - ], - "params": { - "synth": "sine", - "bpm": 130, - "adsr": { "attack": 0.01, "decay": 0.1, "sustain": 0.7, "release": 0.5 }, - "effects": { "reverb": 0.3, "delay": 0, "filterFreq": 2000 } - }, - "aiAnalysis": "C Major 조성, 5도 상행으로 신뢰감과 성장 표현", - "createdAt": "2026-03-08T00:00:00.000Z" - } - ], - "createdAt": "2026-03-08T00:00:00.000Z" - } - ], - "sl_current": "sl_1709000000_abc" -} -``` - -### 8.2 DB 테이블 (Phase 3, API 프로젝트에서 마이그레이션) - -| 컬럼 | 타입 | 설명 | -|------|------|------| -| `id` | bigint | PK | -| `tenant_id` | bigint | FK → tenants | -| `user_id` | bigint | FK → users | -| `name` | varchar(200) | 사운드 이름 | -| `audio_path` | varchar(500) | WAV/MP3 파일 경로 | -| `options` | json | notes, params, aiAnalysis 등 | -| `created_at` | timestamp | | -| `updated_at` | timestamp | | - ---- - -## 9. API 인증 및 키 현황 - -> **별도 API 키 발급 불필요** — 기존 인증 정보로 모든 엔진 사용 가능 - -### 9.1 사용 가능한 인증 정보 - -| 엔진 | 인증 방식 | 설정 위치 | 상태 | -|------|----------|----------|------| -| Gemini 2.5 Flash (모드 B) | API 키 | `.env` `GEMINI_API_KEY` | ✅ 운영 중 | -| Lyria RealTime (모드 C) | 동일 API 키 | `.env` `GEMINI_API_KEY` | ✅ 사용 가능 (experimental) | -| Lyria 2 (모드 C 폴백) | 서비스 계정 | `GOOGLE_APPLICATION_CREDENTIALS` | ✅ 파일 존재 | -| Vertex AI | 프로젝트 ID | `.env` `VERTEX_AI_PROJECT_ID=codebridge-chatbot` | ✅ 설정됨 | - -### 9.2 현재 .env 설정 (관련 항목) - -```env -GEMINI_API_KEY=AIzaSy... # Gemini + Lyria RealTime 공용 -GEMINI_MODEL=gemini-2.5-flash # 텍스트 AI (모드 B) -GEMINI_BASE_URL=https://generativelanguage.googleapis.com/v1beta -VERTEX_AI_PROJECT_ID=codebridge-chatbot # Lyria 2 (폴백) -VERTEX_AI_LOCATION=us-central1 -GOOGLE_APPLICATION_CREDENTIALS=/var/www/sales/apikey/google_service_account.json -``` - -### 9.3 Lyria RealTime API 사양 - -| 항목 | 값 | -|------|------| -| 모델 | `lyria-realtime-exp` | -| API 버전 | `v1alpha` (experimental) | -| 프로토콜 | WebSocket (양방향 스트리밍) | -| 출력 포맷 | 48kHz 스테레오 PCM | -| 청크 크기 | 2초 단위 | -| 제어 파라미터 | BPM (60~200), Scale (Key + Mode) | -| 비용 | 무료 (experimental 기간) | -| 참고 | [공식 문서](https://ai.google.dev/gemini-api/docs/music-generation) | - -### 9.4 Lyria 2 API 사양 (폴백) - -| 항목 | 값 | -|------|------| -| 모델 | `lyria` | -| API | Vertex AI REST (`/publishers/google/models/lyria:predict`) | -| 인증 | 서비스 계정 OAuth 토큰 | -| 출력 포맷 | WAV (base64) | -| 비용 | $0.06 / 30초 | -| 기존 코드 | `BgmService::generateWithLyria()` | - ---- - -## 10. 관련 문서 - -- [AI 관리 종합 가이드](../guides/ai-management.md) — Gemini API 설정, 호출 흐름 -- [R&D 메뉴 개요](../features/rd/README.md) — R&D 메뉴 구조 -- [디자인 인사이트](../features/rd/design-insight.md) — 유사 SPA 패턴 참고 -- [Lyria RealTime 공식 문서](https://ai.google.dev/gemini-api/docs/music-generation) — Gemini API 음악 생성 -- [Lyria 2 Vertex AI 문서](https://docs.cloud.google.com/vertex-ai/generative-ai/docs/model-reference/lyria-music-generation) — REST API 레퍼런스 -- [Lyria RealTime 개발자 가이드](https://dev.to/googleai/lyria-realtime-the-developers-guide-to-infinite-music-streaming-4m1h) — 구현 튜토리얼 - ---- - -**최종 업데이트**: 2026-03-08 diff --git a/sam/docs/projects/e-sign/esign-storyboard.pptx b/sam/docs/projects/e-sign/esign-storyboard.pptx deleted file mode 100644 index 07c3b5d..0000000 Binary files a/sam/docs/projects/e-sign/esign-storyboard.pptx and /dev/null differ diff --git a/sam/docs/projects/index_projects.md b/sam/docs/projects/index_projects.md deleted file mode 100644 index 7ce5106..0000000 --- a/sam/docs/projects/index_projects.md +++ /dev/null @@ -1,304 +0,0 @@ -# 프로젝트 문서 인덱스 - -> SAM 시스템 개발 프로젝트별 문서 모음 -> **최종 업데이트**: 2026-03-08 - ---- - -## 프로젝트 현황 요약 - -| 프로젝트 | 상태 | 설명 | -|---------|------|------| -| [mes](#mes---meserp-프로젝트) | 🟡 진행중 | 차세대 MES/ERP 기능 개발 | -| [quotation](#quotation---견적-기능) | 🟢 Phase 3 완료 | 5130 견적 → SAM 이관 | -| [api-integration](#api-integration---react--api-연동) | 🟡 진행중 | React ↔ API 연동 | -| [5130-migration](#5130-migration---품목-마이그레이션) | 🟡 Phase 1 진행중 | 5130 품목 데이터 마이그레이션 | -| [legacy-5130](#legacy-5130---레거시-분석) | 📚 참조용 | 5130 레거시 모듈 분석 | -| [mng-mobile-responsive](#mng-mobile-responsive---모바일-반응형) | 🟡 진행중 | mng 모바일 반응형 개선 | -| [auto-login](#auto-login---자동-로그인) | ⚪ 대기 | 자동 로그인 기능 | -| [migration-5130-mng](#migration-5130-mng---5130--mng-마이그레이션) | 🟡 진행중 | 5130 → mng 통합 마이그레이션 | -| [e-sign](#e-sign---전자계약-서명) | 🟢 v1.0 구현 완료 | 전자계약 서명 솔루션 (SAM E-Sign) | -| [org-chart](#org-chart---조직도-관리) | 🟢 v1.0 구현 완료 | 트리형 조직도 관리 (드래그앤드롭, 숨기기) | -| [planning-design](#planning-design---기획디자인-스토리보드-에디터) | 🟢 v1.2 운영 중 | 브라우저 블록 에디터 (Notion/Figma 스타일) | - ---- - -## 프로젝트 상세 - -### mes - MES/ERP 프로젝트 - -**경로**: `docs/projects/mes/` -**상태**: 🟡 Phase 0 (베이스라인 분석) 30% 완료 -**목표**: SAM 시스템의 차세대 MES/ERP 기능 개발 - -**핵심 문서**: -- [README.md](./mes/README.md) - 프로젝트 개요 및 문서 안내 -- [MES_PROGRESS_TRACKER.md](./mes/MES_PROGRESS_TRACKER.md) - 진행 상황 추적 -- [MES_PROJECT_ROADMAP.md](./mes/MES_PROJECT_ROADMAP.md) - 전체 로드맵 - -**분석 결과**: -- `00_baseline/` - Phase 0 분석 결과 - - [PHASE_0_FINAL_REPORT.md](./mes/00_baseline/PHASE_0_FINAL_REPORT.md) - - [BACKEND_DEVELOPMENT_ROADMAP_V2.md](./mes/00_baseline/BACKEND_DEVELOPMENT_ROADMAP_V2.md) - - `docs_breakdown/` - 문서 분석 (7개) - -**v2 분석**: -- `v2-analysis/` - MES v2 화면 분석 - - `quote-analysis/` - 견적 분석 - - `order-analysis/` - 주문 분석 - - `production-analysis/` - 생산 분석 - - `customer-analysis/` - 거래처 분석 - - `site-analysis/` - 현장 분석 - - `price-analysis/` - 단가 분석 - - `master-data-analysis/` - 기준정보 분석 - - `production-userflow/` - 생산 유저플로우 - ---- - -### quotation - 견적 기능 - -**경로**: `docs/projects/quotation/` -**상태**: 🟢 Phase 3 완료 (2025-12-19) -**목표**: 5130 레거시 견적 기능을 SAM 시스템으로 이관 - -**핵심 문서**: -- [MASTER_PLAN.md](./quotation/MASTER_PLAN.md) - 마스터 플랜 -- [PROGRESS.md](./quotation/PROGRESS.md) - 진행 현황 - -**Phase 문서**: -| Phase | 상태 | 경로 | -|-------|------|------| -| 1. 5130 분석 | ✅ 완료 | `phase-1-5130-analysis/` | -| 2. mng 분석 | ✅ 완료 | `phase-2-mng-analysis/` | -| 3. 구현 | ✅ 완료 | `phase-3-implementation/` | -| 4. API 개발 | ⚪ 대기 | `phase-4-api/` | - -**참조 자료**: -- `screenshots/` - MES 프로토타입 화면 캡쳐 (7개) - ---- - -### api-integration - React ↔ API 연동 - -**경로**: `docs/projects/api-integration/` -**상태**: 🟡 Phase 4 진행중 -**목표**: React(dev.sam.kr)와 API(api.sam.kr) 완벽 연동 - -**핵심 문서**: -- [MASTER_PLAN.md](./api-integration/MASTER_PLAN.md) - 마스터 플랜 -- [PROGRESS.md](./api-integration/PROGRESS.md) - 진행 현황 -- [WORKFLOW.md](./api-integration/WORKFLOW.md) - 작업 프로세스 - -**Phase 문서**: -| Phase | 상태 | 경로 | -|-------|------|------| -| 1. 테이블 통합 | 🟢 완료(스킵) | `phase-1-table-migration/` | -| 2. 메뉴 추출 | 🟡 진행중 | `phase-2-menu-extraction/` | -| 3. API 매핑 | 🟡 진행중 | `phase-3-api-mapping/` | -| 4. 연동+검증 | 🟡 진행중 | `phase-4-integration/` | - -**TC 파일**: `phase-4-integration/tc/` - 기능별 테스트 케이스 JSON (17개) - ---- - -### 5130-migration - 품목 마이그레이션 - -**경로**: `docs/projects/5130-migration/` -**상태**: 🟡 Phase 1 진행중 -**목표**: 5130 품목(부품, 자재, BOM) 데이터를 SAM DB로 이전 - -**핵심 문서**: -- [MASTER_PLAN.md](./5130-migration/MASTER_PLAN.md) - 마스터 플랜 -- [PROGRESS.md](./5130-migration/PROGRESS.md) - 진행 현황 - -**Phase 문서**: -| Phase | 상태 | 경로 | -|-------|------|------| -| 1. 소스 분석 | 🟡 진행중 | `phase-1-source-analysis/` | -| 2. 타겟 분석 | ⚪ 대기 | `phase-2-target-analysis/` | -| 3. 매핑 설계 | ⚪ 대기 | `phase-3-mapping/` | - ---- - -### legacy-5130 - 레거시 분석 - -**경로**: `docs/projects/legacy-5130/` -**상태**: 📚 참조용 문서 -**용도**: 5130 레거시 시스템 모듈별 분석 - -**모듈별 분석 문서**: -| 문서 | 내용 | -|------|------| -| [00_OVERVIEW.md](./legacy-5130/00_OVERVIEW.md) | 시스템 개요 | -| [01_MATERIAL.md](./legacy-5130/01_MATERIAL.md) | 자재 관리 | -| [02_PRODUCT.md](./legacy-5130/02_PRODUCT.md) | 제품 관리 | -| [03_ESTIMATE.md](./legacy-5130/03_ESTIMATE.md) | 견적 관리 | -| [04_PRODUCTION.md](./legacy-5130/04_PRODUCTION.md) | 생산 관리 | -| [05_SHIPPING.md](./legacy-5130/05_SHIPPING.md) | 출하 관리 | -| [06_QUALITY.md](./legacy-5130/06_QUALITY.md) | 품질 관리 | -| [07_ACCOUNTING.md](./legacy-5130/07_ACCOUNTING.md) | 회계 관리 | -| [08_SAM_COMPARISON.md](./legacy-5130/08_SAM_COMPARISON.md) | SAM 비교 분석 | -| [draw-module.md](./legacy-5130/draw-module.md) | 도면 모듈 | - ---- - -### mng-mobile-responsive - 모바일 반응형 - -**경로**: `docs/projects/mng-mobile-responsive/` -**상태**: 🟡 진행중 -**목표**: mng 관리자 패널 모바일 반응형 개선 - -**문서**: -- [01-analysis.md](./mng-mobile-responsive/01-analysis.md) - 분석 -- [02-implementation-plan.md](./mng-mobile-responsive/02-implementation-plan.md) - 구현 계획 -- [06-excluded-menus.md](./mng-mobile-responsive/06-excluded-menus.md) - 제외 메뉴 -- [PROGRESS.md](./mng-mobile-responsive/PROGRESS.md) - 진행 현황 - ---- - -### auto-login - 자동 로그인 - -**경로**: `docs/projects/auto-login/` -**상태**: ⚪ 대기 -**목표**: 자동 로그인 기능 구현 - -**문서**: -- [PROGRESS.md](./auto-login/PROGRESS.md) - 진행 현황 - ---- - -### migration-5130-mng - 5130 → mng 마이그레이션 - -**경로**: `docs/projects/migration-5130-mng/` -**상태**: 🟡 진행중 -**목표**: 5130 기능을 mng로 통합 마이그레이션 - -**문서**: -- [MIGRATION_TRACKER.md](./migration-5130-mng/MIGRATION_TRACKER.md) - 마이그레이션 추적 - ---- - -### e-sign - 전자계약 서명 - -**경로**: `docs/projects/e-sign/` -**상태**: 🟢 v1.0 구현 완료 (2026-02-12) -**목표**: 모두싸인과 유사한 간편 전자계약 서명 솔루션 자체 구축 - -**핵심 문서**: -- [technical-design.md](./e-sign/technical-design.md) - 기술 설계 문서 -- [implementation-guide.md](./e-sign/implementation-guide.md) - 구현 가이드 - -**구현 범위**: -| 영역 | 수량 | -|------|------| -| DB 마이그레이션 | 4개 (esign_contracts, esign_signers, esign_sign_fields, esign_audit_logs) | -| API 모델 | 4개 | -| API 서비스 | 4개 | -| API 컨트롤러 | 2개 (16 엔드포인트) | -| MNG 컨트롤러 | 2개 (8 화면) | -| MNG 뷰 | 8개 (React 하이브리드) | - -**기술 스택**: Laravel 11 + React 18 + SignaturePad + PDF.js - -**참고 자료**: -- `esign-storyboard.pptx` - 화면 스토리보드 -- `storyboard-config.json` - 스토리보드 설정 - ---- - -### org-chart - 조직도 관리 - -**경로**: `docs/projects/org-chart/` -**상태**: 🟢 v1.0 구현 완료 (2026-03-06) -**목표**: 테넌트별 조직 구조를 시각적으로 관리하는 트리형 조직도 - -**핵심 문서**: -- [README.md](./org-chart/README.md) - 기술 문서 (아키텍처, API, DB, 프론트엔드 상세) - -**구현 범위**: - -| 영역 | 수량 | -|------|------| -| MNG 컨트롤러 메서드 | 7개 (RdController) | -| API 엔드포인트 | 6개 (조회, 배치, 해제, 순서변경, 숨기기) | -| DB 마이그레이션 | 1개 (departments.options JSON 추가) | -| 뷰 | 1개 (Alpine.js + SortableJS) | - -**기술 스택**: Alpine.js + SortableJS + 수동 DOM 렌더링 (x-for 미사용) - ---- - -### planning-design - 기획디자인 스토리보드 에디터 - -**경로**: `docs/projects/planning-design/` -**상태**: 🟢 v1.2 운영 중 (고도화 진행중) -**목표**: 브라우저 내 Notion/Figma 스타일 블록 에디터로 ERP 화면 기획서 작성 - -**핵심 문서**: -- [README.md](./planning-design/README.md) - 프로젝트 개요 및 구현 이력 - -**구현 범위**: - -| 영역 | 수량 | -|------|------| -| 블록 유형 | 15종 (텍스트/레이아웃/UI모형/미디어/체크리스트) | -| 편집 기능 | 올가미 선택, Undo/Redo, 복사/잘라내기, 서식 | -| 서식 시스템 | 글자색/배경색/크기/굵기/기울임/정렬/z-index | -| 작업 영역 | 사이드바/Description 접기/펼치기, 캔버스 폭 자동 확장 | -| 출력 | HTML 내보내기 + A4 인쇄 (좌표 기반 WYSIWYG) | - -**기술 스택**: Alpine.js + localStorage (서버 API 없음) - -**기술 스펙**: [features/rd/planning-design.md](../features/rd/planning-design.md) - ---- - -## 디렉토리 구조 - -``` -docs/projects/ -├── INDEX.md # 이 파일 -├── mes/ # MES/ERP 프로젝트 (핵심) -│ ├── 00_baseline/ # Phase 0 분석 -│ ├── v1-analysis/ # v1 분석 -│ ├── v2-analysis/ # v2 화면 분석 -│ └── phases/ # Phase별 진행 -├── quotation/ # 견적 기능 -│ ├── phase-1-5130-analysis/ -│ ├── phase-2-mng-analysis/ -│ ├── phase-3-implementation/ -│ └── screenshots/ -├── api-integration/ # React ↔ API 연동 -│ ├── phase-1-table-migration/ -│ ├── phase-2-menu-extraction/ -│ ├── phase-3-api-mapping/ -│ └── phase-4-integration/tc/ -├── 5130-migration/ # 품목 마이그레이션 -│ ├── phase-1-source-analysis/ -│ ├── phase-2-target-analysis/ -│ └── phase-3-mapping/ -├── legacy-5130/ # 레거시 분석 (참조용) -├── mng-mobile-responsive/ # 모바일 반응형 -├── auto-login/ # 자동 로그인 -├── migration-5130-mng/ # 5130→mng 마이그레이션 -├── e-sign/ # 전자계약 서명 (SAM E-Sign) -├── org-chart/ # 조직도 관리 -└── planning-design/ # 기획디자인 스토리보드 에디터 -``` - ---- - -## 관련 문서 - -- [docs/INDEX.md](../INDEX.md) - 전체 문서 인덱스 -- [docs/plans/index_plans.md](../plans/index_plans.md) - 기획 문서 인덱스 -- [docs/guides/PROJECT_DEVELOPMENT_POLICY.md](../guides/PROJECT_DEVELOPMENT_POLICY.md) - 공통 개발 정책 -- [CURRENT_WORKS.md](../../CURRENT_WORKS.md) - 현재 작업 - ---- - -**범례**: -- 🟢 완료 -- 🟡 진행중 -- ⚪ 대기 -- 📚 참조용 \ No newline at end of file diff --git a/sam/docs/projects/org-chart/README.md b/sam/docs/projects/org-chart/README.md deleted file mode 100644 index 238ce52..0000000 --- a/sam/docs/projects/org-chart/README.md +++ /dev/null @@ -1,317 +0,0 @@ -# 조직도 관리 시스템 - -> **작성일**: 2026-03-06 -> **상태**: 🟢 v1.0 구현 완료 -> **프로젝트**: MNG 전용 (Blade + Alpine.js + SortableJS) - ---- - -## 1. 개요 - -### 1.1 목적 - -테넌트별 조직 구조를 시각적으로 관리하는 트리형 조직도 시스템. -부서 계층 구조와 직원 배치를 드래그 앤 드롭으로 관리한다. - -### 1.2 주요 기능 - -| 기능 | 설명 | -|------|------| -| 트리형 조직도 | 회사 → 부서 → 하위부서 (무한 depth) 계층 표시 | -| 직원 배치 | 드래그 앤 드롭으로 직원을 부서에 배치/해제 | -| 부서 순서 변경 | 같은 레벨 내 부서 순서 드래그로 변경 | -| 부서 계층 이동 | 부서를 다른 부서 아래로 드래그하여 parent 변경 | -| 부서 숨기기 | 더블클릭 → 숨기기 버튼 → DB 저장 (영구) | -| 임원 필터링 | 대표이사/사장 등은 미배치 목록에서 제외 | - ---- - -## 2. 기술 스택 - -| 구분 | 기술 | -|------|------| -| 백엔드 | Laravel (MNG 프로젝트) | -| 프론트엔드 | Alpine.js + 수동 DOM 렌더링 | -| 드래그 앤 드롭 | SortableJS | -| 스타일 | Tailwind CSS + inline style | -| 데이터 저장 | MySQL `departments`, `employees` 테이블 | - ---- - -## 3. 아키텍처 - -### 3.1 렌더링 방식 - -> **핵심**: Alpine.js `x-for` 대신 수동 `innerHTML` 렌더링을 사용한다. - -SortableJS와 Alpine.js `x-for` 템플릿이 동시에 DOM을 조작하면 **이중 업데이트 버그**가 발생한다. -이를 해결하기 위해 부서 트리는 JavaScript로 HTML 문자열을 생성하고 `innerHTML`로 삽입한다. - -``` -Alpine.js 데이터 변경 - ↓ -renderTree() 호출 - ↓ -기존 SortableJS 인스턴스 destroy - ↓ -buildChildrenHtml(null, 0) → 재귀적 HTML 생성 - ↓ -$refs.deptTree.innerHTML = html - ↓ -$nextTick → initDeptSortables() + initEmpSortables() -``` - -### 3.2 이벤트 처리 - -수동 렌더링된 HTML에는 Alpine 디렉티브가 없으므로 **이벤트 위임(Event Delegation)** 패턴을 사용한다. - -``` -루트 div @click="handleClick($event)" - @dblclick="handleDblClick($event)" - ↓ -e.target.closest('[data-action]') 으로 액션 식별 - ↓ -data-action 값에 따라 분기: - - "unassign" → 직원 미배치 - - "hide-dept" → 부서 숨기기 - - "restore-dept" → 부서 복원 - - "dept-dblclick" → 더블클릭 시 숨기기 버튼 토글 -``` - -### 3.3 순환 참조 방지 - -부서를 자신의 하위로 드래그하면 무한 루프가 발생한다. -`isDescendant(ancestorId, targetId)` 재귀 함수로 이를 차단한다. - -```javascript -// 드래그 대상(dragId)의 자손인 곳으로는 이동 불가 -onMove: (evt) => { - const dragId = parseInt(evt.dragged.dataset.deptId); - const toPid = evt.to.dataset.parentId ? parseInt(evt.to.dataset.parentId) : null; - if (toPid === dragId || this.isDescendant(dragId, toPid)) return false; -} -``` - ---- - -## 4. 파일 구조 - -### 4.1 MNG 프로젝트 - -| 파일 | 역할 | -|------|------| -| `app/Http/Controllers/RdController.php` | 컨트롤러 (7개 메서드) | -| `app/Models/Tenants/Department.php` | 부서 모델 (`options` JSON cast) | -| `resources/views/rd/org-chart.blade.php` | 뷰 (Alpine.js + SortableJS) | -| `routes/web.php` | 라우트 (6개 엔드포인트) | - -### 4.2 API 프로젝트 - -| 파일 | 역할 | -|------|------| -| `database/migrations/2026_03_06_201500_add_options_to_departments_table.php` | `options` JSON 컬럼 추가 | - ---- - -## 5. API 엔드포인트 - -> 모든 엔드포인트는 `rd.` 네임 프리픽스 하위에 위치한다. - -| Method | Route | 컨트롤러 메서드 | 설명 | -|--------|-------|---------------|------| -| GET | `/rd/org-chart` | `orgChart` | 조직도 페이지 | -| POST | `/rd/org-chart/assign` | `orgChartAssign` | 직원 부서 배치 | -| POST | `/rd/org-chart/unassign` | `orgChartUnassign` | 직원 부서 해제 | -| POST | `/rd/org-chart/reorder` | `orgChartReorder` | 직원 일괄 이동 | -| POST | `/rd/org-chart/reorder-depts` | `orgChartReorderDepts` | 부서 순서/계층 변경 | -| POST | `/rd/org-chart/toggle-hide` | `orgChartToggleHide` | 부서 숨기기/표시 토글 | - -### 5.1 요청/응답 형식 - -**부서 배치** (`POST /rd/org-chart/assign`): -```json -{ "employee_id": 1, "department_id": 5 } -→ { "success": true } -``` - -**부서 순서 변경** (`POST /rd/org-chart/reorder-depts`): -```json -{ - "orders": [ - { "id": 1, "parent_id": null, "sort_order": 1 }, - { "id": 2, "parent_id": null, "sort_order": 2 }, - { "id": 3, "parent_id": 1, "sort_order": 1 } - ] -} -→ { "success": true } -``` - -**부서 숨기기** (`POST /rd/org-chart/toggle-hide`): -```json -{ "department_id": 5, "hidden": true } -→ { "success": true } -``` - ---- - -## 6. DB 구조 - -### 6.1 departments 테이블 (관련 컬럼) - -| 컬럼 | 타입 | 설명 | -|------|------|------| -| `id` | int | PK | -| `tenant_id` | int | 테넌트 FK | -| `parent_id` | int (nullable) | 상위 부서 (null = 최상위) | -| `name` | varchar | 부서명 | -| `code` | varchar | 부서 코드 | -| `is_active` | bool | 활성 여부 | -| `sort_order` | int | 정렬 순서 | -| `options` | json (nullable) | 확장 속성 | - -**`options` 키**: - -| 키 | 타입 | 설명 | -|----|------|------| -| `orgchart_hidden` | boolean | 조직도에서 숨김 여부 | - -### 6.2 employees 테이블 (관련 컬럼) - -| 컬럼 | 타입 | 설명 | -|------|------|------| -| `id` | int | PK | -| `tenant_id` | int | 테넌트 FK | -| `department_id` | int (nullable) | 소속 부서 (null = 미배치) | -| `display_name` | varchar | 표시 이름 | -| `position_label` | varchar | 직책/직급 | -| `employee_status` | enum | `active`, `leave`, `resigned` | - ---- - -## 7. 프론트엔드 구현 상세 - -### 7.1 Alpine.js 컴포넌트 (`orgChart()`) - -**데이터**: - -| 속성 | 타입 | 설명 | -|------|------|------| -| `departments` | Array | 전체 부서 목록 (서버에서 전달) | -| `employees` | Array | 전체 직원 목록 (서버에서 전달) | -| `hiddenDepts` | Set | 숨긴 부서 ID (DB에서 초기화) | -| `dblClickDept` | int/null | 더블클릭된 부서 ID (숨기기 버튼 표시용) | -| `execTitles` | Array | 임원 직책 목록 (`['대표이사', '사장', '부사장', '회장', '부회장']`) | - -**핵심 메서드**: - -| 메서드 | 설명 | -|--------|------| -| `renderTree()` | SortableJS 파괴 → HTML 재생성 → SortableJS 재초기화 | -| `buildChildrenHtml(parentId, level)` | 재귀적 자식 부서 HTML 생성 | -| `buildNodeHtml(dept, level)` | 단일 부서 카드 HTML (level별 스타일 차등) | -| `buildEmpHtml(emp, isLarge)` | 직원 카드 HTML | -| `isDeptHidden(deptId)` | 부서 또는 상위 부서가 숨김인지 재귀 체크 | -| `isDescendant(ancestorId, targetId)` | 순환 참조 방지 | -| `isExecutive(emp)` | 임원 여부 판별 | - -### 7.2 SortableJS 그룹 - -| 그룹 | 대상 | 핸들 | 기능 | -|------|------|------|------| -| `departments` | `.org-children`, `.org-drop-target` | `.dept-drag-handle` | 부서 순서/계층 변경 | -| `employees` | `.emp-zone`, `#unassigned-zone` | (전체) | 직원 배치/해제 | - -### 7.3 CSS 연결선 - -부서 간 연결선은 CSS `::before`/`::after` 의사 요소로 구현한다. - -``` - 부모 노드 - │ (vertical: div 1px × 24px) - ┌───────┼───────┐ (horizontal: ::before + ::after) - │ │ │ (vertical: div 1px × 24px) - 자식1 자식2 자식3 -``` - -| 선택자 | 역할 | -|--------|------| -| `.org-node-wrap` 내부 div (1px × 24px) | 세로 연결선 | -| `.org-node-wrap:not(:first-child)::before` | 왼쪽 가로선 (left:0 ~ right:50%) | -| `.org-node-wrap:not(:last-child)::after` | 오른쪽 가로선 (left:50% ~ right:0) | -| `:only-child` | 단일 자식이면 가로선 숨김 | - -### 7.4 부서 숨기기 UX 흐름 - -``` -① 부서 헤더 더블클릭 - ↓ -② dblClickDept = dept.id → renderTree() - ↓ -③ 헤더에 빨간 "숨기기" 버튼 표시 - ↓ -④ "숨기기" 클릭 - ↓ -⑤ hiddenDepts.add(id) → renderTree() → POST /toggle-hide (DB 저장) - ↓ -⑥ 해당 부서 + 하위 부서가 트리에서 제거 -⑦ "숨겨진 부서" 패널에 표시 - ↓ -⑧ 패널에서 👁 아이콘 클릭 → hiddenDepts.delete(id) → POST /toggle-hide -``` - -### 7.5 부서 레벨별 스타일 - -| Level | 색상 테마 | 너비 | 아이콘 | -|-------|---------|------|--------| -| 0 (최상위) | 보라 (`#7C3AED`) | 200px | `ri-building-2-line` | -| 1 (중간) | 인디고 (`#6366F1`) | 180px | `ri-git-branch-line` | -| 2+ (하위) | 회색 (`#6B7280`) | 160px | `ri-subtract-line` | - ---- - -## 8. 비즈니스 규칙 - -### 8.1 임원 필터링 - -미배치 직원 목록에서 다음 조건에 해당하면 제외: - -- `position_label`이 `['대표이사', '사장', '부사장', '회장', '부회장']` 중 하나 -- `display_name`이 테넌트의 `ceo_name`과 일치 - -> 이유: 조직도 최상단에 "대표이사 OOO"이 이미 표시되므로 중복 방지 - -### 8.2 부서 숨기기 - -- `departments.options` JSON의 `orgchart_hidden` 키로 저장 -- 숨긴 부서의 **하위 부서도 자동으로 숨겨짐** (`isDeptHidden` 재귀 체크) -- 숨겨진 부서 패널에는 **직접 숨긴 부서만** 표시 (자식은 부모 복원 시 같이 복원) -- 숨기기는 **조직도 표시 전용** — `is_active`와 무관하며, 부서 데이터에 영향 없음 - -### 8.3 직원 표시 형식 - -- 직책이 있으면: `{직책} {이름}` (예: "과장 전진선") -- 직책이 없으면: `{이름}` (예: "김보곤") - ---- - -## 9. 개발 이력 - -| 날짜 | 커밋 | 내용 | -|------|------|------| -| 2026-03-06 | `a12ee886` | CSS 연결선 수정 + 빈 드롭 타겟 숨김 | -| 2026-03-06 | `9fd72e49` | 부서 숨기기 기능 추가 (프론트 전용) | -| 2026-03-06 | `8c8fd5f6` | 대표이사 미배치 제외 + 숨긴 부서 연결선 제거 | -| 2026-03-06 | `81157a15` | 부서 숨기기 상태 DB 저장 (`options.orgchart_hidden`) | - ---- - -## 관련 문서 - -- [rules/department-tree-api.md](../../rules/department-tree-api.md) — 부서 트리 API 규칙 -- [rules/employee-api.md](../../rules/employee-api.md) — 직원 API 규칙 -- [system/database/hr.md](../../system/database/hr.md) — HR 테이블 스키마 -- [standards/options-column-policy.md](../../standards/options-column-policy.md) — options JSON 컬럼 정책 - ---- - -**최종 업데이트**: 2026-03-06 diff --git a/sam/docs/projects/planning-design/README.md b/sam/docs/projects/planning-design/README.md deleted file mode 100644 index 12dba75..0000000 --- a/sam/docs/projects/planning-design/README.md +++ /dev/null @@ -1,157 +0,0 @@ -# 기획디자인 스토리보드 에디터 - -> **시작일**: 2026-03-07 -> **상태**: 🟢 v1.2 운영 중 (고도화 진행중) -> **경로**: MNG `/rd/planning-design` -> **담당**: Claude Code + 개발팀 - ---- - -## 1. 프로젝트 개요 - -### 1.1 배경 - -ERP 화면 기획서(스토리보드)를 PowerPoint나 Figma 없이 **SAM 관리자 웹 내에서 직접 설계**할 수 있는 도구가 필요했다. 기획자와 개발자가 같은 플랫폼에서 화면을 설계하고, 즉시 HTML/인쇄 출력까지 가능한 올인원 솔루션을 목표로 했다. - -### 1.2 목표 - -- 브라우저 내 Notion/Figma 스타일 블록 에디터 구현 -- ERP 스토리보드 표준 양식 (메뉴트리 + 와이어프레임 + Description) 지원 -- 서버 API 없이 localStorage 기반 즉시 사용 가능 -- HTML 내보내기 및 좌표 기반 WYSIWYG 인쇄 - -### 1.3 기술 스택 - -| 항목 | 선택 | 이유 | -|------|------|------| -| 프레임워크 | Alpine.js | 서버 없이 반응형 SPA, 기존 MNG 스택과 일치 | -| 캔버스 | DOM absolute positioning | Canvas API보다 접근성 좋고 텍스트 편집 용이 | -| 저장 | localStorage | 서버 API 불필요, 즉시 사용 가능 | -| 내보내기 | HTML 생성 + window.print() | 별도 라이브러리 없이 브라우저 내장 기능 활용 | - ---- - -## 2. 구현 이력 - -### v1.0 — 기본 블록 에디터 (2026-03-07) - -| 커밋 | 내용 | -|------|------| -| `063d8c61` | 스토리보드 블록 Undo/Redo 기능 (Ctrl+Z/Y, 50단계 히스토리) | -| `78c8f3f8` | 페이지 복사 기능 (블록 ID 재생성) | -| `a27d9921` | placeholder 색상 옅게 + italic 스타일 | -| `08cc866a` | 블록 툴바를 단위업무 상단으로 이동 (기획서 보기 방해 제거) | -| `20e5ab78` | 메뉴/캔버스 경계 드래그 리사이즈 (80~400px) | -| `7785dfed` | 올가미(마퀴) 다중 선택 + 그룹 이동/복사/삭제 | -| `ff373c71` | 올가미 선택 동작 수정 (캔버스 빈 영역 판별 개선) | -| `95cd217c` | Ctrl+X 잘라내기 기능 (단일/다중) | -| `f4131df0` | Ctrl+X 후 Ctrl+Z 복구 수정 (히스토리 인덱스 보정) | -| `8ff84e7f` | Description 패널 리사이즈 + 번호 마커 블록 (D&D/툴바) | -| `ac5ae6eb` | 좌표 기반 인쇄 + HTML 내보내기 블록 좌표 배치 | - -### v1.1 — 서식 시스템 (2026-03-08) - -| 커밋 | 내용 | -|------|------| -| `dfbbd3a1` | 플로팅 서식 툴바 + 우클릭 컨텍스트 메뉴 추가 | -| `280bfddb` | 블록 서식 CSS 상속 수정 (자식 요소 color inherit) | - -### v1.2 — 작업 영역 극대화 (2026-03-08) - -| 커밋 | 내용 | -|------|------| -| `5e0f1a63` | 좌측 사이드바 접기/펼치기 버튼 추가 | -| `f1202731` | 메뉴트리/Description 패널 접기/펼치기 + 캔버스 폭 자동 확장 (1100→1400px) | -| `a38c017c` | 이미지 블록 업로드를 더블클릭으로 변경 (드래그 중 파일 창 오픈 방지) | - ---- - -## 3. 현재 기능 목록 - -### 3.1 블록 유형 (15종) - -| 분류 | 유형 | -|------|------| -| 텍스트 | Heading (H1), Heading2 (H2), Text, Code | -| 레이아웃 | Divider, Callout | -| 데이터 | Table | -| UI 모형 | Button, Input, Select, Card, Badges | -| 미디어 | Image, Marker (번호 뱃지) | -| 체크 | Todo (체크리스트) | - -### 3.2 편집 기능 - -- 자유 배치 캔버스 (드래그 이동, 핸들 리사이즈) -- 올가미 다중 선택 + 그룹 이동/복사/삭제 -- Undo/Redo (50단계) -- 복사/붙여넣기/잘라내기 (Ctrl+C/V/X) -- 전체 선택 (Ctrl+A) -- 더블클릭 인라인 편집 (contenteditable) -- 이미지 블록 더블클릭 업로드 (드래그 충돌 방지) - -### 3.3 서식 시스템 - -- 플로팅 서식 툴바: 글자색, 배경색, 크기, 굵기, 기울임, 정렬, z-index -- 우클릭 컨텍스트 메뉴: 복제/잘라내기/삭제/색상/정렬/레이어/서식 초기화 - -### 3.4 문서 관리 - -- 멀티 페이지 (추가/복사/삭제/이동) -- ERP 메뉴 트리 편집 (드래그 순서 변경) -- Description 패널 (기능 설명 + 번호 마커 D&D) -- 프리셋/커스텀 템플릿 - -### 3.6 작업 영역 극대화 - -- 좌측 사이드바(메뉴트리) 접기/펼치기 토글 -- Description 패널 접기/펼치기 토글 바 -- 패널 접힘 시 캔버스 폭 자동 확장 (1100px → 1400px) -- sb-editor 패딩 축소 (24px → 12px) - -### 3.5 출력 - -- HTML 파일 내보내기 (좌표 기반 WYSIWYG) -- 인쇄 미리보기 (A4 Landscape, 페이지 분할) - ---- - -## 4. 향후 로드맵 - -| 우선순위 | 기능 | 설명 | 상태 | -|---------|------|------|------| -| 🔴 필수 | DB 저장 | localStorage → DB 전환 (협업, 용량 해결) | ⚪ 대기 | -| 🔴 필수 | 스냅/그리드 정렬 | 블록 간 자석 가이드라인 | ⚪ 대기 | -| 🟡 중요 | 그룹핑 | 여러 블록을 하나의 그룹으로 묶기/풀기 | ⚪ 대기 | -| 🟡 중요 | 레이어 패널 | z-index 순서를 시각적으로 관리 | ⚪ 대기 | -| 🟡 중요 | 리치 텍스트 | 블록 내 부분 텍스트 서식 (인라인 B/I/색상) | ⚪ 대기 | -| 🟢 권장 | PDF 내보내기 | 서버사이드 PDF 생성 | ⚪ 대기 | -| 🟢 권장 | 버전 관리 | 명시적 스냅샷 저장 및 비교 | ⚪ 대기 | -| 🟢 권장 | 공유 링크 | 읽기 전용 공유 URL 생성 | ⚪ 대기 | - ---- - -## 5. 기술적 특이사항 - -### 5.1 단일 파일 아키텍처 - -모든 CSS + HTML + JavaScript가 `index.blade.php` 하나에 포함 (~4,430줄). 서버 API가 없고 localStorage만 사용하므로, 컨트롤러는 뷰만 반환한다. - -### 5.2 CSS 스타일 상속 문제 - -블록 자식 요소에 하드코딩된 `color`가 있어 부모의 인라인 스타일이 무시되는 문제를 CSS attribute selector(`[style*="color"]`)로 해결했다. 향후 블록 유형 추가 시 inherit 규칙도 함께 추가해야 한다. - -### 5.3 localStorage 용량 한계 - -이미지를 base64 Data URL로 저장하므로 대량 사용 시 5~10MB 한계에 도달할 수 있다. DB 저장 전환이 중장기 과제. - ---- - -## 6. 관련 문서 - -- [기술 스펙](../../features/rd/planning-design.md) — 데이터 구조, 블록 유형, CSS 상속 상세 -- [R&D 메뉴 개요](../../features/rd/README.md) — R&D 전체 메뉴 구조 -- [프로젝트 인덱스](../index_projects.md) — 전체 프로젝트 목록 - ---- - -**최종 업데이트**: 2026-03-08 diff --git a/sam/docs/rules/billing-policy.md b/sam/docs/rules/billing-policy.md deleted file mode 100644 index 56a5966..0000000 --- a/sam/docs/rules/billing-policy.md +++ /dev/null @@ -1,189 +0,0 @@ -# SAM 과금정책 — 내부용 (CONFIDENTIAL) - -> **작성일**: 2026-02-21 -> **상태**: 설계 확정 -> **열람 범위**: 내부 개발팀/관리층 전용 — 대외 공유 금지 - ---- - -## 문서 분리 안내 - -과금정책이 대상 독자별 3개 문서로 분리되었다. - -| 문서 | 대상 | 내용 | -|------|------|------| -| [고객 요금 안내](customer-pricing.md) | 고객 | 서비스 가격표, 과금 기준 | -| [영업파트너 수당 체계](partner-commission.md) | 영업파트너 | 수당률, 정산 프로세스 | -| **본 문서** (billing-policy.md) | 내부 개발팀/관리층 | 본사 원가, 마진율, 코드 참조 | - ---- - -## 1. 개요 - -### 1.1 목적 - -SAM 프로젝트의 과금정책 중 **본사 지출 원가**, **마진 구조**, **코드 참조**를 정리한다. -고객 공개용 요금과 영업파트너 수당 체계는 별도 문서로 분리되었다. - -### 1.2 적용범위 - -- 외부 서비스 이용 비용 (바로빌, Google, Anthropic) -- 마진 구조 및 가격 책정 배경 -- 코드 참조 (모델, 서비스, DB 테이블) - -### 1.3 용어 정의 - -| 용어 | 설명 | -|------|------| -| **개발비** | 서비스 도입 시 1회 납부하는 초기 비용 | -| **구독료** | 서비스 유지를 위한 월 정기 비용 | -| **토큰** | AI가 언어를 처리하는 최소 단위 (한글 ~1.5자 = 1토큰) | -| **MRR** | Monthly Recurring Revenue (월간 반복 매출) | - ---- - -## 2. 본사 지출 과금정책 (Company → Service Provider) - -본사가 외부 서비스 제공자에게 납입하는 비용이다. - -### 2.1 바로빌 API 비용 - -#### 월정액 서비스 - -| 서비스 | 월정액 | 비고 | -|--------|--------|------| -| 계좌조회 | 10,000원 | 고객 부담 | -| 카드내역 | 10,000원 | 고객 부담 | -| 홈택스 매입/매출 | 33,000원 (VAT 포함) | 코드브릿지엑스 지원 → 본사 부담 (무료) | - -> **참고**: 계좌조회/카드내역 월정액은 고객에게 전가한다. 홈택스는 본사가 흡수한다. - -#### 건별 과금 - -| 서비스 | 단가 | 비고 | -|--------|------|------| -| 전자세금계산서 발행 | 100원/건 | 원가 기준 | - -### 2.2 AI/클라우드 서비스 비용 - -#### 토큰 기반 과금 (LLM) - -| 제공자 | 모델 | 입력 단가 (USD/1M) | 출력 단가 (USD/1M) | 입력 (KRW/1M) | 출력 (KRW/1M) | -|--------|------|------------------:|------------------:|--------------:|--------------:| -| Google | Gemini 2.0 Flash | $0.10 | $0.40 | 140원 | 560원 | -| Anthropic | Claude 3 Haiku | $0.25 | $1.25 | 350원 | 1,750원 | - -#### 시간/작업 기반 과금 - -| 서비스 | 단가 (USD) | 단위 | KRW 환산 | -|--------|----------:|------|----------:| -| Google STT | $0.009 | 15초당 | 12.6원/15초 (약 50원/분) | -| Google GCS | $0.005 | 1,000건당 | 7원/1,000건 | -| Google FCM | 무료 | - | - | - -#### 환율 기준 - -- 기본 환율: **1,400원/USD** -- `ai_pricing_configs` 테이블에서 동적 관리 -- 캐시 TTL: 1시간 - -### 2.3 본사 지출 월간 예상 (테넌트 1개 기준) - -| 항목 | 최소 | 최대 | 비고 | -|------|-----:|-----:|------| -| 바로빌 홈택스 | 0원 | 0원 | 코드브릿지엑스 지원 | -| 세금계산서 원가 | ~5,000원 | ~10,000원 | 50~100건 기준 | -| AI 토큰 (Gemini) | ~100원 | ~5,000원 | 사용량 비례 | -| GCS/STT | ~50원 | ~2,000원 | 사용량 비례 | - ---- - -## 3. 고객 안내용 과금정책 - -> 고객 요금 상세는 **[고객 요금 안내](customer-pricing.md)** 문서를 참조한다. - ---- - -## 4. 내부 정산 정책 - -### 4.1 영업 수당 체계 - -> 수당률 및 정산 프로세스는 **[영업파트너 수당 체계](partner-commission.md)** 문서를 참조한다. - -### 4.2 마진 구조 - -- **회사 마진**: 개발비의 약 **67~75%** (가입 유형에 따라 변동) - - 개인 가입: 개발비의 약 72~75% (수당 25~28% 차감 후) - - 단체 가입: 개발비의 약 67% (수당 33% 차감 후) - -### 4.3 가격 책정 배경 - -- 내부 총 개발비 산정: **약 7,600만원** -- 구성: 개발비 2,000만원 + 장기 구독(약 7년) 및 금융 비용(4.6%) -- 중소기업 초기 투자 부담 분산 구조 - ---- - -## 5. 코드 참조 (개발자용) - -### 5.1 바로빌 과금 - -| 파일 | 내용 | -|------|------| -| `mng/app/Models/Barobill/BarobillSubscription.php` | `DEFAULT_MONTHLY_FEES` 월정액 상수 | -| `mng/app/Models/Barobill/BarobillBillingRecord.php` | `USAGE_UNIT_PRICES` 건별 단가 상수 | -| `mng/app/Models/Barobill/BarobillPricingPolicy.php` | 과금 정책 모델 + `calculateBilling()` | -| `mng/app/Services/Barobill/BarobillBillingService.php` | 월정액/건별 과금 처리 서비스 | -| `mng/app/Services/Barobill/BarobillUsageService.php` | 사용량 집계 및 과금 계산 | -| `mng/database/seeders/BarobillPricingPolicySeeder.php` | 과금 정책 시더 (5개 정책) | - -### 5.2 AI 가격/토큰 - -| 파일 | 내용 | -|------|------| -| `api/app/Models/Tenants/AiPricingConfig.php` | AI 단가 모델 + `getActivePricing()` | -| `api/app/Models/Tenants/AiTokenUsage.php` | 토큰 사용량 기록 모델 | -| `api/app/Services/AiReportService.php` | 토큰 비용 계산 로직 (`saveTokenUsage()`) | -| `api/database/migrations/2026_02_09_*_ai_pricing_configs.php` | AI 단가 테이블 + 시드 데이터 | -| `api/database/migrations/2026_02_07_*_ai_token_usages.php` | 토큰 사용량 테이블 | - -### 5.3 정산 관련 - -| 파일 | 내용 | -|------|------| -| `mng` 또는 `api` 정산 컨트롤러/서비스 | 영업수수료, 구독료, 컨설팅비 정산 | - -### 5.4 DB 테이블 참조 - -| 테이블 | 설명 | -|--------|------| -| `barobill_subscriptions` | 바로빌 월정액 구독 현황 | -| `barobill_billing_records` | 바로빌 월별 과금 내역 | -| `barobill_pricing_policies` | 바로빌 과금 정책 (무료 제공량, 추가 단가) | -| `ai_pricing_configs` | AI 제공자별 단가 설정 | -| `ai_token_usages` | AI 토큰 사용량 기록 | -| `ai_voice_recordings` | AI 음성 녹음 (STT 비용 발생) | -| `sales_commissions` | 영업수수료 정산 | - ---- - -## 6. 관련 문서 - -- [고객 요금 안내](customer-pricing.md) - 서비스 가격표 (고객 공개용) -- [영업파트너 수당 체계](partner-commission.md) - 수당률 및 정산 (파트너용) -- [단가 정책 (품목)](pricing-policy.md) - 품목 단가/원가 계산 -- [영업수수료정산](../features/settlement/sales-commissions.md) -- [구독료정산](../features/settlement/subscriptions.md) -- [컨설팅비용정산](../features/settlement/consulting-fees.md) -- [고객사정산](../features/settlement/customer-settlements.md) -- `sales/price/수당지급체계.md` - 수당 지급 체계 상세 -- `sales/policy/SAM_영업정책문서.md` - 영업 정책 상세 -- `sales/price/ref/토큰정책.md` - AI 토큰 고객 안내 가이드 - ---- - -> **공통 안내**: 본 문서에 명시된 모든 개발비 및 구독료는 **부가가치세(VAT) 별도** 금액이다. - ---- - -**최종 업데이트**: 2026-02-21 diff --git a/sam/docs/rules/billing-policy.pptx b/sam/docs/rules/billing-policy.pptx deleted file mode 100644 index 6a3f307..0000000 Binary files a/sam/docs/rules/billing-policy.pptx and /dev/null differ diff --git a/sam/docs/rules/customer-pricing.md b/sam/docs/rules/customer-pricing.md deleted file mode 100644 index 60a9ff2..0000000 --- a/sam/docs/rules/customer-pricing.md +++ /dev/null @@ -1,116 +0,0 @@ -# SAM 서비스 요금 안내 - -> **작성일**: 2026-02-21 -> **상태**: 설계 확정 - ---- - -## 1. 개요 - -### 1.1 목적 - -SAM 서비스 도입 시 고객에게 안내하는 요금 체계를 정리한다. - -### 1.2 용어 정의 - -| 용어 | 설명 | -|------|------| -| **개발비** | 서비스 도입 시 1회 납부하는 초기 비용 | -| **구독료** | 서비스 유지를 위한 월 정기 비용 | -| **토큰** | AI가 언어를 처리하는 최소 단위 (한글 ~1.5자 = 1토큰) | - ---- - -## 2. 기본 서비스 요금 - -### 2.1 제조업 기본 패키지 - -- **포함**: 품목관리 → 견적 → 수주 → 생산 → 출하 (ERP 인사/회계 무료 포함) -- **개발비**: 2,000만원 (VAT 별도) -- **구독료**: 50만원/월 (VAT 별도) - -### 2.2 개별 모듈 - -| 모듈명 | 개발비 (VAT 별도) | 구독료/월 (VAT 별도) | -|--------|------------------:|-----------------:| -| QR코드 관리 | 1,020만원 | 5만원 | -| 사진/출하 관리 | 1,920만원 | 10만원 | -| 검사/토큰 적용 | 1,020만원 | 5만원 | -| 이카운트 연동 | 1,920만원 | 10만원 | - -### 2.3 통합 패키지 - -| 패키지명 | 개발비 (VAT 별도) | 구독료/월 (VAT 별도) | -|---------|------------------:|-----------------:| -| 공사관리 패키지 | 4,000만원 | 20만원 | -| 공정/정부지원사업 | 8,000만원 | 40만원 | - ---- - -## 3. 추가 옵션 요금 - -| 옵션명 | 개발비 추가 (VAT 별도) | 구독료 추가/월 (VAT 별도) | -|--------|---------------------:|----------------------:| -| 생산공정 1개 추가 | 500만원 | 10만원 | -| 품질관리 (인정검사) | 2,000만원 | 50만원 | -| 사진 등록 | - | 10만원 | -| 챗봇/녹음/업무일지 | - | 각 20만원 | -| 연구소 연구노트 | - | 5만원 | -| 장비점검, 사무소 정비 | - | 5만원 | - -> **참고**: 품질관리(인정검사)에는 '장비점검, 사무소 정비' 기능이 기본 포함된다. - ---- - -## 4. 사용량 기반 추가 과금 - -기본 제공 한도 초과 시 실비 과금한다. - -| 항목 | 기본 제공 | 추가 과금 기준 | -|------|----------|--------------| -| 파일 저장 공간 | 100GB | 100GB당 **10만원/월** | -| AI 토큰 | 월 100만 토큰 | 1,000토큰 단위 실비 과금 | - -### AI 토큰 사용량 체감 (100만 토큰 기준) - -| 활용 시나리오 | 예상 처리량 | -|-------------|-----------| -| 음성 회의 요약 | 약 520분 (8.6시간) | -| 문서 자료 정리 (A4) | 약 300~400매 | -| 이메일/노트 분류 | 약 1,500~2,000건 | - -- 미사용 잔여 토큰은 이월되지 않는다 (매월 1일 갱신) -- 기본 제공량 80%, 100% 소진 시 자동 알림 발송 - ---- - -## 5. 바로빌 부가 서비스 요금 - -고객이 선택적으로 이용하는 바로빌 연동 서비스이다. - -| 서비스 | 과금 방식 | 기본 제공 | 추가 과금 | 부담 주체 | -|--------|---------|---------|---------|----------| -| 계좌조회 | 월정액 10,000원 | 1계좌 | 추가 1계좌당 10,000원 | 고객 | -| 카드내역 | 월정액 10,000원 | 5장 | 추가 1장당 5,000원 | 고객 | -| 홈택스 매입/매출 | 월 33,000원 | - | - | 본사 (무료) | -| 세금계산서 발행 | 건별 | 100건 | 추가 50건당 5,000원 | 고객 | - -> **과금 계산 예시**: -> - 법인카드 8장 등록 → (8-5) × 5,000 = 15,000원 추가 -> - 세금계산서 151건 → ceil((151-100)/50) × 5,000 = 10,000원 추가 - ---- - -## 6. 관련 문서 - -- [내부 과금정책](billing-policy.md) - 본사 지출 원가 및 코드 참조 (내부용) -- [영업파트너 수당 체계](partner-commission.md) - 수당률 및 정산 프로세스 (파트너용) -- [단가 정책 (품목)](pricing-policy.md) - 품목 단가/원가 계산 - ---- - -> **공통 안내**: 본 문서에 명시된 모든 개발비 및 구독료는 **부가가치세(VAT) 별도** 금액이다. - ---- - -**최종 업데이트**: 2026-02-21 diff --git a/sam/docs/rules/customer-pricing.pptx b/sam/docs/rules/customer-pricing.pptx deleted file mode 100644 index f96693b..0000000 Binary files a/sam/docs/rules/customer-pricing.pptx and /dev/null differ diff --git a/sam/docs/rules/partner-commission.md b/sam/docs/rules/partner-commission.md deleted file mode 100644 index 7917fe1..0000000 --- a/sam/docs/rules/partner-commission.md +++ /dev/null @@ -1,114 +0,0 @@ -# SAM 영업파트너 수당 체계 - -> **작성일**: 2026-02-21 -> **상태**: 설계 확정 - ---- - -## 1. 개요 - -### 1.1 목적 - -영업파트너가 알아야 할 수당 체계 및 정산 프로세스를 안내한다. - -### 1.2 기본 원칙 - -- 수당은 **개발비에 대해서만** 지급한다 -- 구독료는 플랫폼 유지보수 및 클라우드 인프라 비용으로 활용되며 수당 대상이 아니다 -- 기준금액은 개발비의 50%이며, 2단계(1차/2차) 분할 지급한다 - ---- - -## 2. 가입 유형별 수당률 - -| 가입 유형 | 파트너/단체 수당 | 매니저 수당 | 협업지원금(유치자) | **본사 총 지급률** | -|-----------|:--------------:|:----------:|:-----------------:|:----------------:| -| **개인 가입** | 20% | 5% | 3% | **28%** | -| **단체 가입** | 30% | 0% | 3% | **33%** | - -- **협업지원금**: 유치자(parent)가 자신이 유치한 하위 파트너의 매출에서 3%를 수령하는 내부 제도 -- 1단계까지만 적용 (유치자 → 하위 파트너, 그 이상 상위로는 올라가지 않음) -- 단체 가입 시 매니저 수당은 0% -- 단체 가입 시 수수료율은 개발비의 33% (VAT 별도) - ---- - -## 3. 수당 산정 예시 - -### 3.1 기준금액 100만원 기준 - -| 가입 유형 | 파트너/단체 | 매니저 | 협업지원금 | 본사 총 지급 | -|-----------|----------:|-------:|----------:|------------:| -| 개인 (유치자 있음) | 200,000원 | 50,000원 | 30,000원 | **280,000원 (28%)** | -| 개인 (유치자 없음) | 200,000원 | 50,000원 | 0원 | 250,000원 (25%) | -| 단체 | 300,000원 | 0원 | 30,000원 | **330,000원 (33%)** | - -### 3.2 제조업 기본 패키지 (개발비 2,000만원) 기준 - -**개인 가입:** - -| 항목 | 금액 | -|------|-----:| -| 판매자(파트너) 수당 | 400만원 (20%) | -| 매니저 수당 | 100만원 (5%) | -| 협업지원금(유치자) | 60만원 (3%) | - -**단체 가입:** - -| 항목 | 금액 | -|------|-----:| -| 단체 수당 | 600만원 (30%) | -| 매니저 수당 | 0원 (0%) | -| 협업지원금(유치자) | 60만원 (3%) | - ---- - -## 4. 수당 지급 프로세스 - -``` -┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ -│ 1. 계약 및 입금 │ → │ 2. 수당 확정 │ → │ 3. 지급 │ -│ │ │ │ │ │ -│ 개발비 전액 │ │ 매월 정산일에 │ │ 파트너 등록 │ -│ 완납 확인 │ │ 건별 수당 확정 │ │ 계좌로 지급 │ -└─────────────────┘ └─────────────────┘ └─────────────────┘ -``` - -- **지급 시점**: 개발비 입금 완료 확인 후 익월 정산일 - ---- - -## 5. 추가 옵션별 수당 참고 - -개발비가 있는 옵션만 수당 대상이다. 서비스 요금 상세는 [고객 요금 안내](customer-pricing.md)를 참조한다. - -| 옵션명 | 개발비 (VAT 별도) | 판매자 수당 (20%) | -|--------|------------------:|------------------:| -| 생산공정 1개 추가 | 500만원 | 100만원 | -| 품질관리 (인정검사) | 2,000만원 | 400만원 | - -> **참고**: 구독료만 있는 옵션(사진 등록, 챗봇/녹음/업무일지 등)은 수당 대상이 아니다. - ---- - -## 6. 기타 정책 - -- **계약 유지**: 장기 구독을 전제로 한 초기 비용 할인 정책이므로, 중도 해지 시 별도의 위약금 규정이 적용될 수 있다 -- **구독료**: 플랫폼 유지보수 및 클라우드 인프라 비용으로 활용되며, 수당 지급 대상이 아니다 - ---- - -## 7. 관련 문서 - -- [고객 요금 안내](customer-pricing.md) - 서비스 요금 상세 (고객용) -- [내부 과금정책](billing-policy.md) - 본사 지출 원가 및 코드 참조 (내부용) -- `sales/price/수당지급체계.md` - 수당 지급 체계 원본 -- `sales/policy/SAM_영업정책문서.md` - 영업 정책 상세 - ---- - -> **공통 안내**: 본 문서에 명시된 모든 개발비 및 구독료는 **부가가치세(VAT) 별도** 금액이다. - ---- - -**최종 업데이트**: 2026-02-21 diff --git a/sam/docs/rules/partner-commission.pptx b/sam/docs/rules/partner-commission.pptx deleted file mode 100644 index ff69d4a..0000000 Binary files a/sam/docs/rules/partner-commission.pptx and /dev/null differ diff --git a/sam/docs/rules/slides/billing-policy/slide-01.html b/sam/docs/rules/slides/billing-policy/slide-01.html deleted file mode 100644 index 8d81f7c..0000000 --- a/sam/docs/rules/slides/billing-policy/slide-01.html +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - -
-
- -

SAM

-
-
-

CONFIDENTIAL

-
-
- - -
-

INTERNAL USE ONLY

-

SAM 과금정책

-

본사 지출 원가 · 마진 구조 · 코드 참조

-
- - -
-
-

COST PER TENANT

-

~1만원/월

-

테넌트당 월 원가

-
-
-

OPERATING MARGIN

-

67~75%

-

영업이익률

-
-
-

SCALE ADVANTAGE

-

MC → 0

-

스케일 시 한계비용

-
-
- - -
-
-

SCOPE

-

내부 개발팀 / 관리층

-
-
-

DATE

-

2026. 02

-
-
-

WARNING

-

대외 공유 금지

-
-
- - diff --git a/sam/docs/rules/slides/billing-policy/slide-02.html b/sam/docs/rules/slides/billing-policy/slide-02.html deleted file mode 100644 index 863fc46..0000000 --- a/sam/docs/rules/slides/billing-policy/slide-02.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - -
-
-
-

OVERVIEW

-
-

과금정책 3분할 체계

-
-
-

CONFIDENTIAL

-
-
- - -
- -
-
-

FOR CUSTOMER

-
-

고객용

-
-

customer-pricing.md

-
-

서비스 가격표, 과금 기준

-
-

고객에게 직접 전달 가능

-
-
- - -
-
-

FOR PARTNER

-
-

파트너용

-
-

partner-commission.md

-
-

수당률, 정산 프로세스

-
-

영업파트너 제공용

-
-
- - -
-
-

INTERNAL ONLY

-
-

내부용 (본 문서)

-
-

billing-policy.md

-
-

원가, 마진, 코드참조

-
-

대외 공유 금지

-
-
-
- - -
-

본 문서는 내부 개발팀/관리층 전용입니다. 고객 및 파트너에게 공유하지 마세요.

-
- - -
-

SAM 내부 과금정책 | CONFIDENTIAL

-

02

-
- - diff --git a/sam/docs/rules/slides/billing-policy/slide-03.html b/sam/docs/rules/slides/billing-policy/slide-03.html deleted file mode 100644 index b1e7126..0000000 --- a/sam/docs/rules/slides/billing-policy/slide-03.html +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - - -
-
-
-

COST

-
-

바로빌 API 원가 분석

-
-

03

-
- - -
- -
-

월정액 서비스

- -
-

서비스

-

월정액

-

처리 방식

-
- -
-

계좌조회

-

10,000원

-

고객 부담 (전가)

-
- -
-

카드내역

-

10,000원

-

고객 부담 (전가)

-
- -
-

홈택스 매입/매출

-

33,000원

-

본사 흡수 (코드브릿지엑스 → 무료)

-
-
- - -
- -
-

건별 과금

- -
-

서비스

-

원가

-
-
-

세금계산서 발행

-

100원/건

-
- -
-

고객 과금: 5,000원/50건

-

마진: 4,900원 (98%)

-
-
- - -
-

핵심 요약

-
-
-

계좌/카드 → 고객 전가, 홈택스 → 코드브릿지엑스 지원으로 본사 원가 0원

-
-
-
-

본사 실질 부담: 세금계산서 원가만 (5,000~10,000원/월)

-
-
-
-
- - -
-

SAM 내부 과금정책 | CONFIDENTIAL

-

03

-
- - diff --git a/sam/docs/rules/slides/billing-policy/slide-04.html b/sam/docs/rules/slides/billing-policy/slide-04.html deleted file mode 100644 index 89ea645..0000000 --- a/sam/docs/rules/slides/billing-policy/slide-04.html +++ /dev/null @@ -1,142 +0,0 @@ - - - - - - - - -
-
-
-

COST

-
-

AI / 클라우드 원가 분석

-
-

04

-
- - -
- -
-
-

토큰 기반 과금 (LLM)

-
-

환율 1,400원/USD

-
-
- - -
-
-

Google Gemini 2.0 Flash

-
-
-
-

입력 /1M 토큰

-

$0.10 → 140원

-
-
-

출력 /1M 토큰

-

$0.40 → 560원

-
-
-
-

초저비용 AI — 100만 토큰 처리해도 700원

-
-
- - -
-
-

Anthropic Claude 3 Haiku

-
-
-
-

입력 /1M 토큰

-

$0.25 → 350원

-
-
-

출력 /1M 토큰

-

$1.25 → 1,750원

-
-
-
-

고품질 AI — 100만 토큰에도 약 2,100원

-
-
-
- - -
-

시간/작업 기반 과금

- - -
-
-

Google STT

-

$0.009 / 15초

-
-
-

~50원/분

-

1시간 녹음 처리 = 3,000원

-
-
- - -
-
-

Google GCS

-

$0.005 / 1,000건

-
-
-

7원/1,000건

-

사실상 무료 수준

-
-
- - -
-
-

Google FCM (푸시알림)

-

무제한

-
-
-

무료

-

완전 무료

-
-
- - -
-

핵심 인사이트

-

LLM 토큰 비용은 건당 1원 미만 수준. 클라우드 인프라 비용도 무시 가능한 수준으로, AI 기능이 수익 마진에 미치는 영향이 극히 작음.

-
-
-
- - -
-

ai_pricing_configs 테이블에서 동적 관리

-

캐시 TTL 1시간

-
- - -
-

SAM 내부 과금정책 | CONFIDENTIAL

-

04

-
- - diff --git a/sam/docs/rules/slides/billing-policy/slide-05.html b/sam/docs/rules/slides/billing-policy/slide-05.html deleted file mode 100644 index 377697e..0000000 --- a/sam/docs/rules/slides/billing-policy/slide-05.html +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - - - -
-
-
-

MARGIN

-
-

마진 구조 + 가격 책정 배경

-
-

05

-
- - -
- -
-
-

MARGIN STRUCTURE

-

회사 영업이익률

-

67~75%

-
-
-
-

개인 가입

-

72~75% (수당 25~28%)

-
-
-

단체 가입

-

~67% (수당 33%)

-
-
-
-

SaaS 업계 평균 마진 60% 대비 높은 수익성

-
-
- - -
-
-

PRICE BACKGROUND

-

내부 총 개발비 산정

-

7,600만원

-
-
-
-
-

개발비 2,000만원 + 장기 구독 약 7년

-
-
-
-

금융 비용 4.6% 포함

-
-
-
-

중소기업 초기 투자 부담 분산 구조

-
-
-
-
- - -
-

본사 지출 월간 예상 (테넌트 1개)

-
-
-

바로빌 홈택스

-

0원

-
-
-

세금계산서

-

5,000~10,000원

-
-
-

AI 토큰

-

100~5,000원

-
-
-

GCS/STT

-

50~2,000원

-
-
-
-

합계 최대

-

~17,000원/월

-
-
-
-

구독료 50만원 대비 원가율 3.4% — 스케일 시 한계비용 0에 수렴

-
-
- - -
-

SAM 내부 과금정책 | CONFIDENTIAL

-

05

-
- - diff --git a/sam/docs/rules/slides/billing-policy/slide-06.html b/sam/docs/rules/slides/billing-policy/slide-06.html deleted file mode 100644 index 923547d..0000000 --- a/sam/docs/rules/slides/billing-policy/slide-06.html +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - - - -
-
-
-

CODE REF

-
-

코드 참조 — 소스 파일

-
-

06

-
- - -
- -
-
-
-

바로빌 과금

-
-

6개 파일

-
-
- -
-
-

BarobillSubscription.php

-

DEFAULT_MONTHLY_FEES 상수

-
-
-

BarobillBillingRecord.php

-

USAGE_UNIT_PRICES 상수

-
-
-

BarobillPricingPolicy.php

-

calculateBilling() 메서드

-
-
-

BarobillBillingService.php

-

월정액/건별 과금 처리

-
-
-

BarobillUsageService.php

-

사용량 집계

-
-
-

BarobillPricingPolicySeeder.php

-

5개 정책 시더

-
-
-
- - -
-
-
-

AI 가격/토큰

-
-

5개 파일

-
-
- -
-
-

AiPricingConfig.php

-

getActivePricing()

-
-
-

AiTokenUsage.php

-

토큰 사용량 기록

-
-
-

AiReportService.php

-

saveTokenUsage()

-
-
-

ai_pricing_configs 마이그레이션

-

AI 단가 테이블

-
-
-

ai_token_usages 마이그레이션

-

토큰 사용량 테이블

-
-
- - -
-

모든 과금 상수와 정책은 소스 코드에 정의되며, DB 시더/마이그레이션으로 초기 데이터가 관리됩니다.

-
-
-
- - -
-

SAM 내부 과금정책 | CONFIDENTIAL

-

06

-
- - diff --git a/sam/docs/rules/slides/billing-policy/slide-07.html b/sam/docs/rules/slides/billing-policy/slide-07.html deleted file mode 100644 index 7a5a772..0000000 --- a/sam/docs/rules/slides/billing-policy/slide-07.html +++ /dev/null @@ -1,128 +0,0 @@ - - - - - - - - -
-
-
-

CODE REF

-
-

코드 참조 — DB 테이블

-
-

07

-
- - -
- -
-

테이블

-

카테고리

-

설명

-
- - -
-

barobill_subscriptions

-
-
-

바로빌

-
-
-

바로빌 월정액 구독 현황

-
- - -
-

barobill_billing_records

-
-
-

바로빌

-
-
-

바로빌 월별 과금 내역

-
- - -
-

barobill_pricing_policies

-
-
-

바로빌

-
-
-

과금 정책 (무료 제공량, 추가 단가)

-
- - -
-

ai_pricing_configs

-
-
-

AI

-
-
-

AI 제공자별 단가 설정

-
- - -
-

ai_token_usages

-
-
-

AI

-
-
-

AI 토큰 사용량 기록

-
- - -
-

ai_voice_recordings

-
-
-

AI

-
-
-

AI 음성 녹음 (STT 비용 발생)

-
- - -
-

sales_commissions

-
-
-

영업

-
-
-

영업수수료 정산

-
-
- - -
-

모든 테이블은 tenant_id 기반 Multi-tenant 구조이며, API 프로젝트(/home/aweso/sam/api)에서 마이그레이션을 관리합니다.

-
- - -
-

SAM 내부 과금정책 | CONFIDENTIAL

-

07

-
- - diff --git a/sam/docs/rules/slides/customer-pricing/slide-01.html b/sam/docs/rules/slides/customer-pricing/slide-01.html deleted file mode 100644 index e20a544..0000000 --- a/sam/docs/rules/slides/customer-pricing/slide-01.html +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - -
-
- -

SAM

-
-
-

SERVICE PRICING 2026

-
-
- - -
-

SMART AUTOMATION MANAGEMENT

-

SAM 서비스 요금 안내

-

제조 현장의 디지털 전환, SAM 하나로 완성합니다

-
- - -
-
-

80% UP

-

업무 자동화율 향상

-
-
-

30% DOWN

-

인건비 절감 효과

-
-
-

100%

-

실시간 현황 파악

-
-
- - -
-
-

COMPANY

-

(주)코드브릿지엑스

-
-
-

DATE

-

2026. 02

-
-
-

NOTE

-

VAT 별도

-
-
-

01 / 07

-
-
- - \ No newline at end of file diff --git a/sam/docs/rules/slides/customer-pricing/slide-02.html b/sam/docs/rules/slides/customer-pricing/slide-02.html deleted file mode 100644 index 7a6d142..0000000 --- a/sam/docs/rules/slides/customer-pricing/slide-02.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - -
- -
-
-

CONTENTS

-
-

목차

-

SAM 서비스의 투명한 요금 체계를 한눈에 확인하세요

-
- - -
- -
-
-

01

-
-
-

기본 서비스 요금

-

제조업 패키지, 개별 모듈, 통합 패키지

-
-
- -
-
-

02

-
-
-

추가 옵션 요금

-

생산공정 추가, 품질관리, 챗봇, 연구노트

-
-
- -
-
-

03

-
-
-

사용량 기반 과금

-

파일 저장 공간, AI 토큰 사용량

-
-
- -
-
-

04

-
-
-

바로빌 부가서비스

-

계좌조회, 카드내역, 세금계산서 발행

-
-
-
-
- - -
-

SAM 서비스 요금 안내 | (주)코드브릿지엑스

-

02 / 07

-

모든 금액 VAT 별도

-
- - \ No newline at end of file diff --git a/sam/docs/rules/slides/customer-pricing/slide-03.html b/sam/docs/rules/slides/customer-pricing/slide-03.html deleted file mode 100644 index 925e39a..0000000 --- a/sam/docs/rules/slides/customer-pricing/slide-03.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - - -
-
-
-

SECTION 01

-
-

기본 서비스 요금

-
-

03 / 07

-
- - -
- - -
-
-
-
-

BEST SELLER

-
-
-

BASIC

-
-
-

제조업 기본 패키지

-

품목관리 → 견적 → 수주 → 생산 → 출하

-
-

ERP 인사/회계 무료 포함

-
-
-
-
-
-

개발비 (1회)

-

2,000만원

-
-
-

구독료 (월)

-

50만원

-
-
-
-

하루 약 1.6만원으로 제조 ERP 완성

-
-
-
- - -
- -

개별 모듈

- -
-

모듈명

-

개발비

-

구독/월

-
- -
-

QR코드 관리

-

1,020만원

-

5만원

-
- -
-

사진/출하 관리

-

1,920만원

-

10만원

-
- -
-

검사/토큰 적용

-

1,020만원

-

5만원

-
- -
-

이카운트 연동

-

1,920만원

-

10만원

-
- - -

통합 패키지

- -
-

패키지명

-

개발비

-

구독/월

-
- -
-

공사관리 패키지

-

4,000만원

-

20만원

-
- -
-

공정/정부지원사업

-

8,000만원

-

40만원

-
-
-
- - -
-

SAM 서비스 요금 안내 | (주)코드브릿지엑스

-

모든 금액 VAT 별도

-
- - \ No newline at end of file diff --git a/sam/docs/rules/slides/customer-pricing/slide-04.html b/sam/docs/rules/slides/customer-pricing/slide-04.html deleted file mode 100644 index 154d62c..0000000 --- a/sam/docs/rules/slides/customer-pricing/slide-04.html +++ /dev/null @@ -1,163 +0,0 @@ - - - - - - - - -
-
-
-

SECTION 02

-
-

추가 옵션 요금

-
-

04 / 07

-
- - -
- -
- -
-
-

생산공정 1개 추가

-

생산 라인별 개별 공정 확장

-
-
-
-

개발비

-

500만원

-
-
-

구독/월

-

10만원

-
-
-
- - -
-
-
-

품질관리 (인정검사)

-
-
-

품질 인증 필수!

-
-

ISO 인증 대응 필수 모듈

-
-
-
-

개발비

-

2,000만원

-
-
-

구독/월

-

50만원

-
-
-
- - -
-
-

사진 등록

-

제품/공정 사진 관리 기능

-
-
-
-

개발비

-

-

-
-
-

구독/월

-

10만원

-
-
-
-
- - -
- -
-
-

챗봇 / 녹음 / 업무일지

-

AI 기반 업무 보조 도구 3종

-
-
-
-

개발비

-

-

-
-
-

구독/월

-

각 20만원

-
-
-
- - -
-
-

연구소 연구노트

-

R&D 기록 및 지식재산 관리

-
-
-
-

개발비

-

-

-
-
-

구독/월

-

5만원

-
-
-
- - -
-
-

장비점검 / 사무소 정비

-

설비 유지보수 이력 관리

-
-
-
-

개발비

-

-

-
-
-

구독/월

-

5만원

-
-
-
-
-
- - -
-

참고 품질관리(인정검사)에는 장비점검/사무소 정비 기능이 기본 포함됩니다.

-
- - -
-

SAM 서비스 요금 안내 | (주)코드브릿지엑스

-

모든 금액 VAT 별도

-
- - \ No newline at end of file diff --git a/sam/docs/rules/slides/customer-pricing/slide-05.html b/sam/docs/rules/slides/customer-pricing/slide-05.html deleted file mode 100644 index 03b55af..0000000 --- a/sam/docs/rules/slides/customer-pricing/slide-05.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - -
-
-
-

SECTION 03

-
-

사용량 기반 추가 과금

-
-

05 / 07

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

F

-
-

파일 저장 공간

-
-
-

기본 제공

-

100GB

-
-
-
-

초과 시

-

100GB당 10만원/월

-
-
- - -
-
-
-

AI

-
-

AI 토큰

-
-
-

기본 제공

-

100만 토큰/월

-
-
-
-

초과 시

-

실비 정산

-
-
-
- - -
-

AI 100만 토큰, 이만큼 쓸 수 있습니다

-

대부분의 중소 제조업에서 충분한 사용량

- - -
-
-
-

음성 회의 요약

-

하루 30분씩 매일 회의해도 한 달 충분

-
-

520

-
-
- - -
-
-
-

문서 자동 정리

-

매일 15장씩 처리해도 여유

-
-

300~400매(A4)

-
-
- - -
-
-
-

이메일/노트 자동 분류

-

하루 75건 자동 분류 가능

-
-

2,000

-
-
- -
-

미사용 토큰 이월 불가 | 80% / 100% 소진 시 자동 알림

-
-
-
- - -
-

SAM 서비스 요금 안내 | (주)코드브릿지엑스

-

모든 금액 VAT 별도

-
- - \ No newline at end of file diff --git a/sam/docs/rules/slides/customer-pricing/slide-06.html b/sam/docs/rules/slides/customer-pricing/slide-06.html deleted file mode 100644 index e3c9461..0000000 --- a/sam/docs/rules/slides/customer-pricing/slide-06.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - -
-
-
-

SECTION 04

-
-

바로빌 부가서비스

-
-

06 / 07

-
- - -
- -
-

서비스

-

과금 방식

-

기본 제공

-

추가 과금

-

부담

-
- - -
-

계좌조회

-

월정액 10,000원

-

1계좌

-

추가 1계좌당 10,000원

-
-
-

고객

-
-
-
- - -
-

카드내역

-

월정액 10,000원

-

5장

-

추가 1장당 5,000원

-
-
-

고객

-
-
-
- - -
-

홈택스 매입/매출

-

월 33,000원

-

-

-

-

-
-
-

SAM 무료!

-
-
-
- - -
-

세금계산서 발행

-

건별

-

100건

-

추가 50건당 5,000원

-
-
-

고객

-
-
-
-
- - -
-

과금 계산 예시

-
- -
-

법인카드 8장 등록 시

-

(8 - 5) x 5,000 = 15,000원 추가

-
- -
-

세금계산서 151건 발행 시

-

ceil((151-100)/50) x 5,000 = 10,000원 추가

-
-
-
- - -
-

SAM 서비스 요금 안내 | (주)코드브릿지엑스

-

모든 금액 VAT 별도

-
- - \ No newline at end of file diff --git a/sam/docs/rules/slides/customer-pricing/slide-07.html b/sam/docs/rules/slides/customer-pricing/slide-07.html deleted file mode 100644 index b7ebd6e..0000000 --- a/sam/docs/rules/slides/customer-pricing/slide-07.html +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - -
- -

SAM

-
- - -
-

지금 SAM과 함께 시작하세요

-

제조 현장의 모든 흐름을 하나의 플랫폼에서 관리합니다

-
-
-

ERP + MES 통합

-
-
-

AI 기반 업무 자동화

-
-
-

실시간 현황 대시보드

-
-
-
- - -
-
-

COMPANY

-

(주)코드브릿지엑스

-
-
-

SYSTEM

-

Smart Automation Management

-
-
-

CONTACT

-

담당 영업파트너 또는 본사

-
-
-
-

모든 금액 VAT 별도

-
-

07 / 07

-
-
- - \ No newline at end of file diff --git a/sam/docs/rules/slides/partner-commission/slide-01.html b/sam/docs/rules/slides/partner-commission/slide-01.html deleted file mode 100644 index 1a7624d..0000000 --- a/sam/docs/rules/slides/partner-commission/slide-01.html +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - -
-
- -

SAM

-
-
-

PARTNER COMMISSION GUIDE

-
-
- - -
-

SALES PARTNER COMMISSION

-

SAM 영업파트너
수당 체계

-

Smart Automation Management

-

업계 최고 수준 수당률, 함께 성장하는 파트너십

-
- - -
-
-

33%

-

최대 수당률

-
-
-

660만원

-

개발비 2,000만원 기준

-
-
-

무제한

-

누적 파트너 수익

-
-
- - -
-
-

COMPANY

-

(주)코드브릿지엑스

-
-
-

DATE

-

2026. 02

-
-
-

NOTE

-

VAT 별도

-
-
- - \ No newline at end of file diff --git a/sam/docs/rules/slides/partner-commission/slide-02.html b/sam/docs/rules/slides/partner-commission/slide-02.html deleted file mode 100644 index b7ce596..0000000 --- a/sam/docs/rules/slides/partner-commission/slide-02.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - -
-
-
-

SECTION 01

-
-

수당 지급 3대 원칙

-
-

02

-
- - -
- -
-
-

1

-
-

개발비 기반

-

수당은 개발비에 대해서만 지급합니다.

-

구독료는 인프라 비용으로 활용되며 수당 대상이 아닙니다.

-
-
-

개발비 = 수당 대상

-
-
-
- - -
-
-

2

-
-

기준금액 50% 적용

-

개발비의 50%를 기준금액으로 산정합니다.

-

기준금액에 수당률을 적용하여 2단계 분할 지급합니다.

-
-
-

2단계 분할 지급

-
-
-
- - -
-
-

3

-
-

투명한 정산

-

매월 정산일에 건별 수당 확정합니다.

-

익월 파트너 등록 계좌로 입금합니다.

-
-
-

매월 정산 + 익월 지급

-
-
-
-
- - -
-

명확한 기준, 신뢰할 수 있는 파트너십

-
- - -
-

SAM 영업파트너 수당 체계 | (주)코드브릿지엑스

-

02

-

VAT 별도

-
- - \ No newline at end of file diff --git a/sam/docs/rules/slides/partner-commission/slide-03.html b/sam/docs/rules/slides/partner-commission/slide-03.html deleted file mode 100644 index ce86831..0000000 --- a/sam/docs/rules/slides/partner-commission/slide-03.html +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - - - -
-
-
-

SECTION 02

-
-

가입 유형별 수당률

-
-

03

-
- - -
- -
-
-

개인 가입

-
-

총 28%

-
-
- - -
-

28%

-
- - -
-
-

파트너 수당

-

20%

-
-
-

매니저 수당

-

5%

-
-
-

협업지원금(유치자)

-

3%

-
-
- -
-

매니저와 유치자를 통한 추가 수익 구조

-
-
- - -
-
-

단체 가입

-
-

총 33%

-
-
- - -
-

33%

-
- - -
-
-

단체 수당

-

30%

-
-
-

매니저

-

0%

-
-
-

협업지원금(유치자)

-

3%

-
-
- -
-

단체 가입 시 최고 수당률!

-
-
-
- - -
-

유치자 수당은 하위 파트너 1단계까지 적용

-

|

-

단체 가입 시 수수료율 개발비의 33% (VAT 별도)

-
- - -
-

SAM 영업파트너 수당 체계 | (주)코드브릿지엑스

-

03

-

VAT 별도

-
- - \ No newline at end of file diff --git a/sam/docs/rules/slides/partner-commission/slide-04.html b/sam/docs/rules/slides/partner-commission/slide-04.html deleted file mode 100644 index 72c5b0f..0000000 --- a/sam/docs/rules/slides/partner-commission/slide-04.html +++ /dev/null @@ -1,180 +0,0 @@ - - - - - - - - -
-
-
-

SECTION 03

-
-

수당 산정 시뮬레이션

-
-

04

-
- - -
-

기준금액 100만원 기준

- - -
-
-

가입 유형

-
-
-

파트너/단체

-
-
-

매니저

-
-
-

협업지원금

-
-
-

총 지급

-
-
- - -
-
-

개인 (유치자O)

-
-
-

200,000원

-
-
-

50,000원

-
-
-

30,000원

-
-
-

280,000원 (28%)

-
-
- - -
-
-

개인 (유치자X)

-
-
-

200,000원

-
-
-

50,000원

-
-
-

0원

-
-
-

250,000원 (25%)

-
-
- - -
-
-

단체

-
-
-

300,000원

-
-
-

0원

-
-
-

30,000원

-
-
-

330,000원 (33%)

-
-
-
- - -
-
-

제조업 기본 패키지 (개발비 2,000만원) 실제 수당

-
-

실전 시뮬레이션

-
-
- -
- -
-

개인 가입

-
-

판매자(파트너)

-

400만원

-
-
-

매니저

-

100만원

-
-
-

협업지원금

-

60만원

-
-
-
-

총 560만원 수익!

-
-
-
- - -
-
-

단체 가입

-
-

BEST

-
-
-
-

단체

-

600만원

-
-
-

매니저

-

0원

-
-
-

협업지원금

-

60만원

-
-
-
-

총 660만원 수익!

-
-
-
-
-
- - -
-

SAM 영업파트너 수당 체계 | (주)코드브릿지엑스

-

04

-

VAT 별도

-
- - \ No newline at end of file diff --git a/sam/docs/rules/slides/partner-commission/slide-05.html b/sam/docs/rules/slides/partner-commission/slide-05.html deleted file mode 100644 index de4844e..0000000 --- a/sam/docs/rules/slides/partner-commission/slide-05.html +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - - -
-
-
-

SECTION 04

-
-

수당 지급 프로세스

-
-

05

-
- - -
- -
-
-

1

-
-

계약 및 입금

-

개발비 전액 완납 확인

-
- - -
-

-
- - -
-
-

2

-
-

수당 확정

-

매월 정산일 건별 수당 확정

-
- - -
-

-
- - -
-
-

3

-
-

지급

-

파트너 등록 계좌로 입금

-
-
- - -
-
-

추가 옵션 수당 참고

-
-

개발비가 있는 옵션만 수당 대상

-
-
- -
- -
-

생산공정 추가

-
-

개발비

-

500만원

-
-
-

판매자 수당

-

100만원

-
-
- - -
-

품질관리 인정검사

-
-

개발비

-

2,000만원

-
-
-

판매자 수당

-

400만원

-
-
- - -
-

구독료만 있는 옵션

-
-

개발비

-

없음

-
-
-

판매자 수당

-

비대상

-
-
-
-
- - -
-

SAM 영업파트너 수당 체계 | (주)코드브릿지엑스

-

05

-

VAT 별도

-
- - \ No newline at end of file diff --git a/sam/docs/rules/slides/partner-commission/slide-06.html b/sam/docs/rules/slides/partner-commission/slide-06.html deleted file mode 100644 index 4c69874..0000000 --- a/sam/docs/rules/slides/partner-commission/slide-06.html +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - -
-
- -

SAM

-
-

06

-
- - -
-

PARTNERSHIP

-

지금, SAM 파트너로
함께하세요

-

제조업 디지털 전환 시장, 폭발적 성장 중

-

대한민국 제조업 디지털 전환, 당신이 이끄는 비즈니스 기회

-
- - -
-
-

33%

-

최대 수당률

-
-
-

660만원

-

건당 최대 수익

-
-
-

무제한

-

누적 수익 상한

-
-
- - -
-
-
-

COMPANY

-

(주)코드브릿지엑스

-
-
-

SYSTEM

-

Smart Automation Management

-
-
-

CONTACT

-

본사 정산팀

-
-
-

모든 금액 VAT 별도

-
- - \ No newline at end of file diff --git a/sam/docs/rules/slides/usage-plan/SAM_활용방안.pptx b/sam/docs/rules/slides/usage-plan/SAM_활용방안.pptx deleted file mode 100644 index ed996ef..0000000 Binary files a/sam/docs/rules/slides/usage-plan/SAM_활용방안.pptx and /dev/null differ diff --git a/sam/docs/rules/slides/usage-plan/convert.cjs b/sam/docs/rules/slides/usage-plan/convert.cjs deleted file mode 100644 index b35464a..0000000 --- a/sam/docs/rules/slides/usage-plan/convert.cjs +++ /dev/null @@ -1,31 +0,0 @@ -const path = require('path'); -module.paths.unshift(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/node_modules')); - -const html2pptx = require(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/html2pptx.js')); -const PptxGenJS = require('pptxgenjs'); - -async function main() { - const pres = new PptxGenJS(); - pres.defineLayout({ name: 'CUSTOM_16x9', width: 10, height: 5.625 }); - pres.layout = 'CUSTOM_16x9'; - pres.author = '(주)코드브릿지엑스'; - pres.subject = 'SAM 활용방안 - AI 자동화로 중소 제조업을 혁신하다'; - - const slideDir = __dirname; - const slideFiles = [ - 'slide-01.html', 'slide-02.html', 'slide-03.html', - 'slide-04.html', 'slide-05.html', 'slide-06.html', 'slide-07.html' - ]; - - for (const file of slideFiles) { - const htmlPath = path.join(slideDir, file); - console.log(`Converting: ${file}`); - await html2pptx(htmlPath, pres); - } - - const outputPath = path.join(slideDir, 'SAM_활용방안.pptx'); - await pres.writeFile({ fileName: outputPath }); - console.log(`\nPPTX saved: ${outputPath}`); -} - -main().catch(err => { console.error(err); process.exit(1); }); diff --git a/sam/docs/rules/slides/usage-plan/slide-01.html b/sam/docs/rules/slides/usage-plan/slide-01.html deleted file mode 100644 index bfa9d9f..0000000 --- a/sam/docs/rules/slides/usage-plan/slide-01.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - -
-
-
- -
-

SAM PROJECT

-
- -

SAM 활용방안

-

AI 자동화로 중소 제조업을 혁신하다

- -

방화셔터 제조업 실증 | 80% 공통화 전략 | Multi-tenant SaaS 플랫폼

- -
-
-

코어 모델 실증

-
-
-

AI 자동화

-
-
-

다산업군 확장

-
-
-
- -
-

SAM 활용방안 | (주)코드브릿지엑스 | 2026.03

-
- - diff --git a/sam/docs/rules/slides/usage-plan/slide-02.html b/sam/docs/rules/slides/usage-plan/slide-02.html deleted file mode 100644 index c16747f..0000000 --- a/sam/docs/rules/slides/usage-plan/slide-02.html +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - -
-

왜 SAM인가? — Before / After

-

중소 제조업의 현실과 SAM이 제시하는 변화

-
- -
-
-
-
- -
-

Before — 기존 방식

-
-

Excel 수기 관리

-

데이터 유실, 버전 혼란, 실시간 공유 불가

-

ERP 도입비 수천만원

-

중소기업에 과도한 초기 투자 부담

-

업체별 커스텀 6개월+

-

도입까지 긴 시간, 업데이트 어려움

-

부서간 정보 단절

-

영업/생산/경영 각자 관리, 의사결정 지연

-
- -
-
-
- -
-

After — SAM 도입 후

-
-

시스템 기반 통합 관리

-

실시간 데이터 공유, 단일 진실 공급원(SSOT)

-

월 구독 SaaS

-

초기 비용 최소화, 사용한 만큼 지불

-

멀티테넌시 즉시 입주

-

설정만으로 바로 사용, 지속적 업데이트

-

영업~출고 원스톱 자동화

-

AI가 연결하는 End-to-End 프로세스

-
-
- -
-

SAM 활용방안 | (주)코드브릿지엑스

-

2 / 7

-
- - diff --git a/sam/docs/rules/slides/usage-plan/slide-03.html b/sam/docs/rules/slides/usage-plan/slide-03.html deleted file mode 100644 index 07e9995..0000000 --- a/sam/docs/rules/slides/usage-plan/slide-03.html +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - - -
-

전체 프로세스 — 영업에서 출고까지

-

6단계 비즈니스 플로우와 AI 자동화 포인트

-
- -
-
-

01

-

영업

-

고객 DB 자동분류

-
-

-
-

02

-

상담

-

STT 음성 기록

-
-

-
-

03

-

견적서

-

AI 자동 산출

-
-

-
-

04

-

수주서

-

자동 전환

-
-

-
-

05

-

작업공정

-

AI 공정 최적화

-
-

-
-

06

-

출고

-

배송 자동화

-
-
- -
-

경동/주일 실증 현황

-
-
-

단계

-

구현 기능

-

상태

-

AI 적용

-
-
-

영업관리

-

고객/거래처 CRM

-

운영중

-

고객 분류 자동화

-
-
-

상담/문의

-

상담 이력, 음성 입력

-

운영중

-

STT 음성→텍스트

-
-
-

견적서

-

견적 작성/승인/발송

-

운영중

-

AI 견적 산출 (개발중)

-
-
-

수주서

-

견적→수주 연동

-

운영중

-

자동 전환 프로세스

-
-
-

작업공정

-

BOM, 공정 관리

-

개발중

-

AI 공정 최적화 (계획)

-
-
-

출고/배송

-

출고 지시, 배송 추적

-

계획

-

물류 자동화 (계획)

-
-
-
- -
-

SAM 활용방안 | (주)코드브릿지엑스

-

3 / 7

-
- - diff --git a/sam/docs/rules/slides/usage-plan/slide-04.html b/sam/docs/rules/slides/usage-plan/slide-04.html deleted file mode 100644 index d6fb551..0000000 --- a/sam/docs/rules/slides/usage-plan/slide-04.html +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - -
-

80% 공통화론 — 핵심 설득 논거

-

중소 제조업 업무의 80%는 업종과 무관하게 동일하다

-
- -
-
-

공통 업무

-
-
-

80% — 영업, 회계, 인사, 재고, 문서, 품질

-
-
-
-
-

커스텀

-
-
-

20%

-
-
-
-

커스텀 20% = 상품 마스터, 견적 계산식, 공정 시퀀스

-
- -
-

업종별 확장 시나리오

-
-
-

업종

-

공통 (80%)

-

커스텀 (20%)

-

난이도

-
-
-

방화셔터

-

영업, 견적, 수주, 회계, 인사

-

셔터 규격 계산, 설치 공정

-

실증완료

-
-
-

블라인드

-

영업, 견적, 수주, 회계, 인사

-

원단/슬랫 규격, 재단 공정

-

즉시가능

-
-
-

금속가공

-

영업, 견적, 수주, 회계, 인사

-

소재/두께 단가표, CNC 공정

-

단기적용

-
-
-

식품제조

-

영업, 견적, 수주, 회계, 인사

-

레시피 관리, HACCP, 유통기한

-

중기적용

-
-
-

전자부품

-

영업, 견적, 수주, 회계, 인사

-

PCB BOM, SMT 공정, 검사

-

중기적용

-
-
- -
-

"상품만 바꾸면 새로운 제조업이 된다. 영업, 회계, 인사, 재고 — 이 80%는 이미 완성되어 있다."

-
-
- -
-

SAM 활용방안 | (주)코드브릿지엑스

-

4 / 7

-
- - diff --git a/sam/docs/rules/slides/usage-plan/slide-05.html b/sam/docs/rules/slides/usage-plan/slide-05.html deleted file mode 100644 index 87cf510..0000000 --- a/sam/docs/rules/slides/usage-plan/slide-05.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - -
-

멀티테넌시 — 하나의 플랫폼, 다수의 기업

-

tenant_id 기반 데이터 격리로 안전하게 다수 기업을 서비스

-
- -
-
-
-
-

A 기업 (경동)

-
-
-

B 기업 (주일)

-
-
-

C 기업 (금속)

-
-
-

D 기업 (식품)

-
-
-

▼ ▼ ▼ ▼

-
-

SAM 플랫폼

-
-

공유: 코드 100%

-

격리: 데이터 100%

-

기반: tenant_id

-
-
-
- -
-
-
-
-

비용 절감

-
-

하나의 코드베이스로 N개 기업 서비스. 기업이 늘어도 개발비 동일.

-
-
-
-
-

즉시 입주

-
-

tenant_id 발급 + 기본 설정. 별도 개발 없이 수일 내 사용.

-
-
-
-
-

데이터 격리

-
-

모든 쿼리에 tenant_id 자동 적용. A기업과 B기업 데이터 완전 분리.

-
-
-
- -
-

SAM 활용방안 | (주)코드브릿지엑스

-

5 / 7

-
- - diff --git a/sam/docs/rules/slides/usage-plan/slide-06.html b/sam/docs/rules/slides/usage-plan/slide-06.html deleted file mode 100644 index ea16e8a..0000000 --- a/sam/docs/rules/slides/usage-plan/slide-06.html +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - -
-

AI 자동화 현황 & 로드맵

-

구현 완료된 AI 기능과 향후 계획

-
- -
-
-
-
-

구현 완료

-
-
-
-

AI 재무 분석

-

CEO 대시보드에서 매출/비용/손익 AI 분석. Claude API로 자연어 인사이트 제공.

-
-
-

STT 음성 입력

-

상담 메모, 현장 보고를 음성 입력. 자동 텍스트 변환 후 시스템 기록.

-
-
-

Claude Code 개발 자동화

-

SAM 시스템을 Claude Code로 개발. 코드 생성, 리뷰, 배포 자동화.

-
-
- -
-
-
-

향후 계획

-
-
-
-

AI 견적 자동 생성

-

고객 요구사항 입력 시 과거 데이터 기반 최적 견적 자동 산출.

-
-
-

AI 공정 최적화

-

생산 데이터 분석으로 최적 공정 순서, 자재 배치 제안.

-
-
-

AI 고객 상담

-

FAQ 자동 응답, 견적 문의 자동 접수. 필요 시 담당자 연결.

-
-
-
- -
-

"공정의 다양성은 천차만별. 이를 AI와 데이터로 정복하는 것이 SAM의 연구 과제다."

-
- -
-

SAM 활용방안 | (주)코드브릿지엑스

-

6 / 7

-
- - diff --git a/sam/docs/rules/slides/usage-plan/slide-07.html b/sam/docs/rules/slides/usage-plan/slide-07.html deleted file mode 100644 index ed9da70..0000000 --- a/sam/docs/rules/slides/usage-plan/slide-07.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - -
-

로드맵 & 비전

-

방화셔터에서 시작하여 모든 중소 제조업으로

-
- -
-
- -
-
-
-

Phase 1

-

코어 실증

-

2025~2026 상반기

-
-

진행중

-
-
-

경동/주일 방화셔터 제조업에서 전 프로세스 실증. 영업→출고 파이프라인 완성.

-
- -
-
-
-

Phase 2

-

3~5사 확장

-

2026 하반기

-
-

계획

-
-
-

블라인드, 금속가공 등 유사 제조업 3~5사에 멀티테넌시 확장.

-
- -
-
-
-

Phase 3

-

AI 고도화

-

2027

-
-

계획

-
-
-

AI 견적 자동 산출, AI 공정 최적화, AI 고객 상담 순차 적용.

-
- -
-
-
-

Phase 4

-

다산업군 플랫폼

-

2028~

-
-

비전

-
-
-

식품, 전자부품 등 다양한 제조업종. 중소 제조업 표준 SaaS.

-
-
- -
-

"방화셔터에서 시작하여, 모든 중소 제조업의 디지털 전환을 이끄는 SAM"

-

AI 자동화 + 멀티테넌시 + 80% 공통화 = 중소 제조업 혁신 플랫폼 | (주)코드브릿지엑스

-
- -
-

7 / 7

-
- - diff --git a/sam/docs/system/ai-automation-vision.md b/sam/docs/system/ai-automation-vision.md deleted file mode 100644 index 18534a5..0000000 --- a/sam/docs/system/ai-automation-vision.md +++ /dev/null @@ -1,174 +0,0 @@ -# SAM 활용방안 — AI 자동화 비전 - -> **작성일**: 2026-03-02 -> **상태**: 설계 확정 -> **대상**: CEO, 경영진, 전 직원 -> **관련 페이지**: MNG 관리자 → Claude Code → 활용방안 - ---- - -## 1. 개요 - -### 1.1 목적 - -SAM(Smart Automation Management)은 방화셔터 제조업(경동기업, 주일기업)을 코어 모델로 실증한 차세대 ERP/MES 통합 시스템이다. 이 문서는 SAM의 장기 비전과 AI 자동화 전략을 기술한다. - -### 1.2 핵심 논지 - -> "중소 제조업 업무의 80%는 업종과 무관하게 동일하다. 상품만 바꾸면 새로운 제조업이 된다." - -| 항목 | 내용 | -|------|------| -| **코어 모델** | 방화셔터 제조업 (경동/주일 실증 완료) | -| **확장 전략** | 80% 공통 프로세스 + 20% 상품 커스텀 | -| **최종 목표** | Multi-tenant SaaS 플랫폼 (다산업군) | - ---- - -## 2. Before / After — 왜 SAM인가 - -### 2.1 기존 방식의 문제 - -| 문제 | 상세 | -|------|------| -| Excel 수기 관리 | 데이터 유실, 버전 혼란, 실시간 공유 불가 | -| ERP 도입비 수천만원 | 중소기업에 과도한 초기 투자 부담 | -| 업체별 커스텀 6개월+ | 도입까지 긴 시간, 업데이트 어려움 | -| 부서간 정보 단절 | 영업/생산/경영 각자 관리, 의사결정 지연 | - -### 2.2 SAM 도입 후 - -| 개선 | 상세 | -|------|------| -| 시스템 기반 통합 관리 | 실시간 데이터 공유, 단일 진실 공급원(SSOT) | -| 월 구독 SaaS | 초기 비용 최소화, 사용한 만큼 지불 | -| 멀티테넌시 즉시 입주 | 설정만으로 바로 사용, 지속적 업데이트 | -| 영업~출고 원스톱 자동화 | AI가 연결하는 End-to-End 프로세스 | - ---- - -## 3. 전체 프로세스 — 영업에서 출고까지 - -``` -영업 → 상담 → 견적서 → 수주서 → 작업공정 → 출고 - (01) (02) (03) (04) (05) (06) -``` - -### 3.1 각 단계별 AI 자동화 포인트 - -| 단계 | 구현 기능 | AI 적용 | 상태 | -|------|----------|---------|------| -| 영업관리 | 고객/거래처 CRM | 고객 분류 자동화 | 운영중 | -| 상담/문의 | 상담 이력, 음성 입력 | STT 음성→텍스트 변환 | 운영중 | -| 견적서 | 견적 작성/승인/발송 | AI 견적 자동 산출 | 운영중 (AI 개발중) | -| 수주서 | 견적→수주 연동 | 자동 전환 프로세스 | 운영중 | -| 작업공정 | BOM, 공정 관리 | AI 공정 최적화 | 개발중 | -| 출고/배송 | 출고 지시, 배송 추적 | 물류 자동화 | 계획 | - ---- - -## 4. 80% 공통화론 - -### 4.1 업무 구성 비율 - -``` -공통 업무 ██████████████████████████████████████████ 80% -커스텀 ██████████ 20% -``` - -- **공통 80%**: 영업/CRM, 회계/재무, 인사/근태, 재고관리, 문서/전자결재, 품질관리 -- **커스텀 20%**: 상품 마스터, 견적 계산식, 공정 시퀀스 (업종마다 다른 부분) - -### 4.2 업종별 확장 시나리오 - -| 업종 | 공통 (80%) | 커스텀 (20%) | 난이도 | -|------|-----------|-------------|--------| -| 방화셔터 | 영업, 견적, 수주, 회계, 인사 | 셔터 규격 계산, 설치 공정 | 실증완료 | -| 블라인드 | 영업, 견적, 수주, 회계, 인사 | 원단/슬랫 규격, 재단 공정 | 즉시가능 | -| 금속가공 | 영업, 견적, 수주, 회계, 인사 | 소재/두께 단가표, CNC 공정 | 단기적용 | -| 식품제조 | 영업, 견적, 수주, 회계, 인사 | 레시피 관리, HACCP, 유통기한 | 중기적용 | -| 전자부품 | 영업, 견적, 수주, 회계, 인사 | PCB BOM, SMT 공정, 검사 | 중기적용 | - ---- - -## 5. 멀티테넌시 구조 - -``` -┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ -│ A 기업 │ │ B 기업 │ │ C 기업 │ │ D 기업 │ -│ (경동기업) │ │ (주일기업) │ │ (금속가공) │ │ (식품제조) │ -└────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ - │ │ │ │ - └─────────────┴──────┬──────┴─────────────┘ - │ - ┌─────────▼─────────┐ - │ SAM 플랫폼 │ - │ │ - │ 공유: 코드 100% │ - │ 격리: 데이터 100% │ - │ (tenant_id 기반) │ - └───────────────────┘ -``` - -### 5.1 핵심 이점 - -| 이점 | 상세 | -|------|------| -| **비용 절감** | 하나의 코드베이스로 N개 기업 서비스. 기업이 늘어도 개발비 동일 | -| **즉시 입주** | 새 기업 추가 = tenant_id 발급 + 기본 설정. 별도 개발 없이 수일 내 사용 | -| **데이터 격리** | 모든 쿼리에 tenant_id 자동 적용. A기업이 B기업 데이터에 접근 불가 | - ---- - -## 6. AI 자동화 현황 & 로드맵 - -### 6.1 구현 완료 - -| 기능 | 상세 | -|------|------| -| **AI 재무 분석** | CEO 대시보드에서 매출/비용/손익 AI 분석. Claude API로 자연어 인사이트 제공 | -| **STT 음성 입력** | 상담 메모, 현장 보고를 음성으로 입력. 자동 텍스트 변환 후 시스템 기록 | -| **Claude Code 개발 자동화** | SAM 시스템 자체를 Claude Code로 개발. 코드 생성, 리뷰, 테스트, 배포 자동화 | - -### 6.2 향후 계획 - -| 기능 | 상세 | -|------|------| -| **AI 견적 자동 생성** | 고객 요구사항 입력 시 과거 데이터 기반으로 최적 견적 자동 산출 | -| **AI 공정 최적화** | 생산 데이터 분석으로 최적 공정 순서, 자재 배치 제안. 불량률 예측 및 사전 경고 | -| **AI 고객 상담** | FAQ 자동 응답, 견적 문의 자동 접수. 사람의 개입이 필요한 경우만 담당자 연결 | - -> "공정의 다양성은 천차만별. 이를 AI와 데이터로 정복하는 것이 SAM의 연구 과제다." - ---- - -## 7. 로드맵 — 4단계 비전 - -| Phase | 제목 | 기간 | 상태 | 핵심 목표 | -|-------|------|------|------|----------| -| **Phase 1** | 코어 실증 | 2025~2026 상반기 | 진행중 | 경동/주일 방화셔터에서 영업→출고 전 프로세스 실증 | -| **Phase 2** | 3~5사 확장 | 2026 하반기 | 계획 | 블라인드, 금속가공 등 유사 제조업 멀티테넌시 확장 | -| **Phase 3** | AI 고도화 | 2027 | 계획 | AI 견적 자동 산출, 공정 최적화, 고객 상담 순차 적용 | -| **Phase 4** | 다산업군 플랫폼 | 2028~ | 비전 | 식품, 전자부품 등 다양한 업종. 중소 제조업 표준 SaaS | - ---- - -## 결론 - -> "방화셔터에서 시작하여, 모든 중소 제조업의 디지털 전환을 이끄는 SAM" - -**AI 자동화 + 멀티테넌시 + 80% 공통화 = 중소 제조업 혁신 플랫폼** - ---- - -## 관련 문서 - -| 문서 | 설명 | -|------|------| -| [SAM 프로젝트 개요](../SAM_PROJECT_OVERVIEW_FOR_AI.md) | 기술적 개요 | -| [스케일링 로드맵](scaling-roadmap.md) | 10,000 테넌트 기술 스케일링 | -| [보안 정책](security-policy.md) | 보안 아키텍처 | - ---- - -**최종 업데이트**: 2026-03-02 diff --git a/sam/docs/system/database/codebridge-separation.md b/sam/docs/system/database/codebridge-separation.md deleted file mode 100644 index 9022cbe..0000000 --- a/sam/docs/system/database/codebridge-separation.md +++ /dev/null @@ -1,443 +0,0 @@ -# codebridge DB 분리 - -> **작성일**: 2026-03-07 -> **상태**: 로컬/개발 서버 적용 완료, **운영 서버 코드 revert 상태 — DB 선행 작업 필요** -> **최종 수정**: 2026-03-09 — API 사용 테이블 점검, 로컬/개발 samdb 삭제 완료, 운영 코드 revert - ---- - -## 1. 개요 - -### 1.1 목적 - -SAM 프로젝트의 DB를 **서비스용**과 **내부 관리용**으로 분리한다. - -- **samdb**: React 서비스가 사용하는 테이블 (수주, 견적, 생산, 거래처 등) -- **codebridge**: MNG(관리자 패널)에서만 사용하는 코드브릿지엑스 내부 관리 테이블 - -### 1.2 핵심 원칙 - -- codebridge DB에 테이블을 복사한 후, samdb에서 해당 테이블을 **삭제**하여 실질적 분리 -- MNG 모델에 `$connection = 'codebridge'`를 설정하여 읽기 대상 DB만 변경 -- React/API 서비스에는 **영향 없음** -- 개발 서버: samdb에서 59개 테이블 삭제 완료 (백업: `/home/pro/backup/sam_backup_20260309.sql.gz`) - -### 1.3 분리 기준 - -| 분류 | 대상 DB | 기준 | -|------|---------|------| -| React 서비스 테이블 | samdb (유지) | React 프론트엔드 또는 API에서 사용 | -| MNG 전용 테이블 | codebridge (이동) | MNG에서만 사용, React/API 미참조 | -| 공통 테이블 | samdb (유지) | 양쪽 모두 사용 (users, tenants 등) | -| **API 사용 테이블** | **samdb (유지 필수)** | **API에 모델/서비스/컨트롤러 존재 — 이동 시 데이터 불일치 발생** | - -> **경고: API에서 모델/서비스/컨트롤러로 참조하는 테이블을 codebridge로 이동하면, API는 samdb에 쓰고 MNG는 codebridge에서 읽게 되어 데이터 불일치가 발생한다. 절대 이동 금지.** - ---- - -## 2. codebridge 테이블 목록 (59개) - -> 2026-03-09 점검: API 프로젝트 전체 코드 조사를 통해 API에서 사용하는 22개 테이블을 제외함. 제외된 테이블은 [3절](#3-api-사용-테이블--samdb-유지-필수-22개) 참조. -> Equipment 하위 테이블 4개 추가 (FK 의존성으로 equipments와 동일 DB 필수). - -### Admin (9) - -| 테이블 | 설명 | -|--------|------| -| `admin_api_flows` | API 플로우 정의 | -| `admin_api_flow_runs` | API 플로우 실행 이력 | -| `admin_pm_daily_logs` | PM 일일 로그 | -| `admin_pm_daily_log_entries` | PM 일일 로그 항목 | -| `admin_pm_issues` | PM 이슈 | -| `admin_pm_projects` | PM 프로젝트 | -| `admin_pm_tasks` | PM 태스크 | -| `admin_roadmap_milestones` | 로드맵 마일스톤 | -| `admin_roadmap_plans` | 로드맵 계획 | - -### DevTools (5) - -| 테이블 | 설명 | 비고 | -|--------|------|------| -| `admin_api_bookmarks` | API 북마크 | 기존명 `api_bookmarks` | -| `admin_api_deprecations` | API 지원종료 관리 | 기존명 `api_deprecations` | -| `admin_api_environments` | API 환경 설정 | 기존명 `api_environments` | -| `admin_api_histories` | API 호출 이력 | 기존명 `api_histories` | -| `admin_api_templates` | API 템플릿 | 기존명 `api_templates` | - -### Sales (17) - -| 테이블 | 설명 | -|--------|------| -| `sales_partners` | 영업 파트너 | -| `sales_managers` | 영업 담당자 | -| `sales_manager_documents` | 영업 담당자 문서 | -| `sales_commissions` | 영업 수당 | -| `sales_commission_details` | 영업 수당 상세 | -| `sales_consultations` | 영업 상담 | -| `sales_contract_products` | 계약 제품 | -| `sales_products` | 영업 제품 | -| `sales_product_categories` | 영업 제품 카테고리 | -| `sales_prospects` | 영업 전망 | -| `sales_prospect_consultations` | 전망 상담 | -| `sales_prospect_products` | 전망 제품 | -| `sales_prospect_scenarios` | 전망 시나리오 | -| `sales_records` | 영업 실적 | -| `sales_scenario_checklists` | 시나리오 체크리스트 | -| `sales_tenant_managements` | 테넌트 영업 관리 | -| `tenant_prospects` | 테넌트 전망 | - -### Finance (9) - -| 테이블 | 설명 | -|--------|------| -| `condolence_expenses` | 경조사비 | -| `consulting_fees` | 컨설팅비 | -| `corporate_cards` | 법인카드 | -| `corporate_card_prepayments` | 법인카드 선결제 | -| `customer_settlements` | 고객 정산 | -| `daily_fund_memos` | 일일 자금 메모 | -| `daily_fund_transactions` | 일일 자금 거래 | -| `incomes` | 수입 | -| `vat_records` | 부가세 기록 | - -### ESign (2) - -| 테이블 | 설명 | -|--------|------| -| `esign_field_templates` | 전자서명 필드 템플릿 | -| `esign_field_template_items` | 전자서명 필드 항목 | - -> esign_contracts, esign_audit_logs, esign_sign_fields, esign_signers는 API에서 전자계약 기능으로 사용 중 → samdb 유지 - -### Equipment (6) - -| 테이블 | 설명 | -|--------|------| -| `equipments` | 설비 | -| `equipment_processes` | 설비 공정 | -| `equipment_inspections` | 설비 점검 (FK → equipments) | -| `equipment_inspection_details` | 설비 점검 상세 (FK → equipment_inspections) | -| `equipment_inspection_templates` | 설비 점검 템플릿 (FK → equipments) | -| `equipment_repairs` | 설비 수리 (FK → equipments) | - -> Equipment 하위 4개 테이블은 `equipments`에 FK 의존하므로 반드시 동일 DB에 있어야 한다. - -### HR (1) - -| 테이블 | 설명 | -|--------|------| -| `business_income_payments` | 사업소득 지급 | - -> income_tax_brackets는 API IncomeTaxBracketSeeder에서 초기 데이터 관리 → samdb 유지 - -### System (1) - -| 테이블 | 설명 | -|--------|------| -| `ai_configs` | AI 설정 | - -> ai_pricing_configs, ai_token_usages는 API 모델에서 직접 사용 → samdb 유지 - -### 기타 (9) - -| 테이블 | 설명 | 비고 | -|--------|------|------| -| `biz_cert` | 사업자등록증 | 문서 기존명 `biz_certs` → 실제 테이블명 (단수) | -| `cm_songs` | R&D 곡 관리 | | -| `construction_site_photos` | 시공 현장 사진 | | -| `construction_site_photo_rows` | 시공 사진 행 | | -| `admin_meeting_logs` | 회의 로그 | 문서 기존명 `meeting_logs` → 실제 테이블명 | -| `meeting_minutes` | 회의록 | | -| `meeting_minute_segments` | 회의록 세그먼트 | | -| `interview_knowledges` | 면접 지식 | | -| `sales_records` | 매출 기록 | | - ---- - -## 3. API 사용 테이블 — samdb 유지 필수 (22개) - -> **경고: 아래 테이블은 API 프로젝트에서 모델/서비스/컨트롤러/시더로 직접 참조한다. 절대 codebridge로 이동 금지.** -> -> **2026-03-09 점검**: sam/api 프로젝트 전체 코드 (모델, 컨트롤러, 서비스, 라우트, 시더) 조사 완료. - -### Barobill (12) — 전체 samdb 유지 - -| 테이블 | API 사용처 | 사유 | -|--------|-----------|------| -| `barobill_billing_records` | BarobillBillingService | 과금 기록 CRUD | -| `barobill_members` | BarobillUsageService | 회원사 사용량 집계 | -| `barobill_monthly_summaries` | BarobillBillingService | 월별 집계 갱신 | -| `barobill_pricing_policies` | BarobillUsageService | 과금 계산 | -| `bank_sync_statuses` | BankSyncStatus 모델 | 동기화 상태 추적 | -| `bank_transactions` | BankTransactionController | 은행 거래 조회/분개 | -| `bank_transaction_overrides` | BankTransactionOverride 모델 | 거래 재정의 | -| `bank_transaction_splits` | BankTransactionController | 은행 거래 분개 | -| `card_transaction_amount_logs` | CardTransactionAmountLog 모델 | 금액 수정 이력 + FK → card_transactions | -| `card_transaction_hides` | CardTransactionHide 모델 | 거래 숨김 + FK → card_transactions | -| `hometax_invoices` | BarobillUsageService | 세금계산서 사용량 집계 | -| `hometax_invoice_journals` | HometaxInvoiceJournal 모델 | 세금계산서 분개 + FK → hometax_invoices | - -> **핵심**: API의 BarobillController, BarobillSettingController, BarobillService, EntertainmentService가 바로빌 테이블을 직접 참조. `barobill_card_transactions` (samdb 유지)와 FK로 연결된 자식 테이블도 분리 불가. - -### ESign (4) — API 전자계약 기능 - -| 테이블 | API 사용처 | 사유 | -|--------|-----------|------| -| `esign_contracts` | EsignContractController, EsignService | 전자계약 CRUD | -| `esign_audit_logs` | EsignService | 감사 추적 기록 | -| `esign_sign_fields` | EsignService | 서명 위치 데이터 | -| `esign_signers` | EsignService | 서명자 정보/인증 | - -### Audit (2) — API 전사 감사 시스템 - -| 테이블 | API 사용처 | 사유 | -|--------|-----------|------| -| `audit_logs` | AuditLog 모델, AuditLogService, AuditRollbackService | 전사 DML 감사 | -| `trigger_audit_logs` | TriggerAuditLog 모델, TriggerAuditLogController, RegenerateAuditTriggers 명령 | DB 트리거 감사 + 파티셔닝 관리 | - -### DevTools (1) - -| 테이블 | API 사용처 | 사유 | -|--------|-----------|------| -| `api_request_logs` | ApiRequestLog 모델, SystemStatService | API 통계 집계 | - -### System (2) - -| 테이블 | API 사용처 | 사유 | -|--------|-----------|------| -| `ai_pricing_configs` | AiPricingConfig 모델 | AI 서비스 비용 계산 (캐시 기반) | -| `ai_token_usages` | AiTokenUsage 모델 | 멀티테넌트 AI 토큰 사용량 추적 | - -### HR (1) - -| 테이블 | API 사용처 | 사유 | -|--------|-----------|------| -| `income_tax_brackets` | IncomeTaxBracketSeeder | 소득세 구간 초기 데이터 관리 | - ---- - -## 4. 적용 현황 - -### 4.1 환경별 상태 - -| 환경 | codebridge DB | 테이블 복사 | samdb 삭제 | .env 설정 | MNG 코드 | 상태 | -|------|:---:|:---:|:---:|:---:|:---:|------| -| **로컬 Docker** | O | 100개 | **58개 삭제** | O | O (develop) | ✅ 정상 작동, samdb 265개 | -| **개발 서버** | O | 101개 | **63개 삭제** | O | O (develop) | ✅ 정상 작동, samdb 265개 | -| **운영 서버** | **X** | **X** | **X** | **X** | **revert됨** | ⚠️ DB 선행 작업 후 코드 재배포 필요 | - -> **2026-03-09 작업 내역**: -> - API 사용 테이블 22개: codebridge 이동 대상에서 제외 → samdb 유지 -> - `finance_*` 17개 + `barobill_companies` 1개: codebridge에 없는 유령 테이블 → samdb에서만 삭제 -> - Equipment 하위 4개 테이블: FK 의존성으로 codebridge 이동 대상에 추가 (55→59개) -> - **개발 서버 samdb에서 63개 테이블 DROP 완료** (59개 + DevTools 실제 테이블명 4개 추가분) -> - **로컬 samdb에서 58개 테이블 DROP 완료** → 로컬/개발 265개로 동기화 -> - 로컬에 `quality_documents` 등 4개 테이블 구조 동기화 (개발서버에서 복사) -> - 백업: `/home/pro/backup/sam_backup_20260309.sql.gz` (6.3MB) -> -> **테이블명 불일치 발견 (수정 완료)**: -> - `api_bookmarks` → 실제: `admin_api_bookmarks` -> - `meeting_logs` → 실제: `admin_meeting_logs` -> - `biz_certs` → 실제: `biz_cert` (단수형) -> - DevTools 4개: `api_deprecations` → `admin_api_deprecations`, `api_environments` → `admin_api_environments`, `api_histories` → `admin_api_histories`, `api_templates` → `admin_api_templates` -> -> **운영 서버 revert 사유 (2026-03-09)**: -> - MNG main에 codebridge 코드 2건 cherry-pick → Jenkins 배포됨 (빌드 #456, #457) -> - 운영 서버에 codebridge DB가 없는 상태에서 코드 배포 → **59개 모델 사용 페이지 오류 발생 위험** -> - kent가 main에서 revert 2건 push → 운영 서버 정상 복구 -> - **교훈: 운영 서버는 반드시 DB 선행 작업(1~2단계) 완료 후 코드 배포(3단계)** - -### 4.2 코드 변경 사항 - -**config/database.php** — `codebridge` connection 추가: - -```php -'codebridge' => [ - 'driver' => 'mysql', - 'host' => env('CODEBRIDGE_DB_HOST', env('DB_HOST', '127.0.0.1')), - 'port' => env('CODEBRIDGE_DB_PORT', env('DB_PORT', '3306')), - 'database' => env('CODEBRIDGE_DB_DATABASE', 'codebridge'), - 'username' => env('CODEBRIDGE_DB_USERNAME', env('DB_USERNAME')), - 'password' => env('CODEBRIDGE_DB_PASSWORD', env('DB_PASSWORD')), - // ... (mysql 기본 설정과 동일) -], -``` - -**.env** — 추가 설정: - -``` -CODEBRIDGE_DB_DATABASE=codebridge -``` - -**MNG 모델** — `$connection` 속성 추가 (codebridge 59개만): - -```php -class SalesPartner extends Model -{ - protected $connection = 'codebridge'; // 추가 - protected $table = 'sales_partners'; - // ... -} -``` - -> **주의**: API 사용 테이블 22개에 해당하는 MNG 모델은 `$connection = 'codebridge'`를 설정하지 않는다. 기본 samdb connection을 사용해야 API와 동일한 데이터를 참조한다. - -### 4.3 samdb 테이블 삭제 절차 (개발 서버 완료) - -> Sales 테이블 그룹은 FK 상호 참조가 있어 `FOREIGN_KEY_CHECKS = 0`으로 일괄 삭제. - -```sql --- FK 체크 비활성화 (Sales, Equipment 등 FK 체인 테이블) -SET FOREIGN_KEY_CHECKS = 0; - --- 59개 테이블 DROP (codebridge에 복제 완료 확인 후) -DROP TABLE IF EXISTS admin_api_flows, admin_api_flow_runs, ...; - -SET FOREIGN_KEY_CHECKS = 1; -``` - -> **롤백**: 백업에서 특정 테이블만 복원 가능 -> ```bash -> gunzip < /home/pro/backup/sam_backup_20260309.sql.gz | mysql -u codebridge -p sam -> ``` - ---- - -## 5. 운영 서버 적용 절차 (미완료) - -> **전제**: 운영 서버 SSH 접근 + DB root 권한 필요 -> **현재 상태**: 운영 서버 main 코드는 revert 상태 (codebridge 코드 없음). DB 작업 완료 후 코드 재배포 필요. -> **⚠️ 교훈**: 2026-03-09에 DB 없이 코드만 배포하여 장애 위험 발생 → **반드시 DB 선행 후 코드 배포** - -### 순서 (반드시 1 → 2 → 3 → 4 → 5 순서로) - -**1단계: 운영 sam DB 백업** - -```bash -# 운영 서버 접속 후 -mysqldump -u codebridge -p'[운영PW]' sam --single-transaction > ~/backup/sam_backup_$(date +%Y%m%d).sql -gzip ~/backup/sam_backup_$(date +%Y%m%d).sql -``` - -**2단계: codebridge DB 생성 + 59개 테이블 복사** - -```bash -# DB 생성 -mysql -u root -p -e "CREATE DATABASE IF NOT EXISTS codebridge CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" - -# DB 계정 권한 부여 -mysql -u root -p -e "GRANT ALL PRIVILEGES ON codebridge.* TO 'codebridge'@'localhost'; FLUSH PRIVILEGES;" - -# sam에서 59개 테이블 구조+데이터 복사 -mysqldump -u codebridge -p sam \ - admin_api_flows admin_api_flow_runs \ - admin_pm_daily_logs admin_pm_daily_log_entries admin_pm_issues admin_pm_projects admin_pm_tasks \ - admin_roadmap_milestones admin_roadmap_plans \ - admin_api_bookmarks admin_api_deprecations admin_api_environments admin_api_histories admin_api_templates \ - sales_partners sales_managers sales_manager_documents sales_commissions sales_commission_details \ - sales_consultations sales_contract_products sales_products sales_product_categories \ - sales_prospects sales_prospect_consultations sales_prospect_products sales_prospect_scenarios \ - sales_records sales_scenario_checklists sales_tenant_managements tenant_prospects \ - condolence_expenses consulting_fees corporate_cards corporate_card_prepayments \ - customer_settlements daily_fund_memos daily_fund_transactions incomes vat_records \ - esign_field_templates esign_field_template_items \ - equipments equipment_process equipment_inspections equipment_inspection_details \ - equipment_inspection_templates equipment_repairs \ - business_income_payments ai_configs \ - biz_cert cm_songs construction_site_photos construction_site_photo_rows \ - admin_meeting_logs meeting_minutes meeting_minute_segments \ - interview_knowledge \ - | mysql -u codebridge -p codebridge -``` - -**3단계: .env 설정** - -```bash -echo 'CODEBRIDGE_DB_DATABASE=codebridge' >> /home/webservice/mng/.env -cd /home/webservice/mng && php artisan config:clear -``` - -**4단계: MNG 코드 재배포 (main cherry-pick)** - -> develop에 codebridge 코드가 있으므로, revert 커밋 이후 develop의 최신 커밋을 cherry-pick. -> 또는 develop의 해당 커밋을 다시 cherry-pick하여 main에 push. - -```bash -# 로컬에서 실행 -cd /home/aweso/sam/mng -git checkout main && git pull origin main -git cherry-pick -git push origin main -git checkout develop -``` - -**5단계: 동작 확인 + samdb 테이블 삭제 (선택)** - -MNG 관리자 페이지에서 영업관리, 설비, 재무 등 주요 메뉴 동작 확인 후, 문제없으면 sam DB에서 59개 테이블 삭제. - -```sql -SET FOREIGN_KEY_CHECKS = 0; -DROP TABLE IF EXISTS - admin_api_flows, admin_api_flow_runs, - admin_pm_daily_logs, admin_pm_daily_log_entries, admin_pm_issues, admin_pm_projects, admin_pm_tasks, - admin_roadmap_milestones, admin_roadmap_plans, - admin_api_bookmarks, admin_api_deprecations, admin_api_environments, admin_api_histories, admin_api_templates, - sales_partners, sales_managers, sales_manager_documents, sales_commissions, sales_commission_details, - sales_consultations, sales_contract_products, sales_products, sales_product_categories, - sales_prospects, sales_prospect_consultations, sales_prospect_products, sales_prospect_scenarios, - sales_records, sales_scenario_checklists, sales_tenant_managements, tenant_prospects, - condolence_expenses, consulting_fees, corporate_cards, corporate_card_prepayments, - customer_settlements, daily_fund_memos, daily_fund_transactions, incomes, vat_records, - esign_field_templates, esign_field_template_items, - equipments, equipment_process, equipment_inspections, equipment_inspection_details, - equipment_inspection_templates, equipment_repairs, - business_income_payments, ai_configs, - biz_cert, cm_songs, construction_site_photos, construction_site_photo_rows, - admin_meeting_logs, meeting_minutes, meeting_minute_segments, - interview_knowledge; -SET FOREIGN_KEY_CHECKS = 1; -``` - -> **⚠️ 핵심 주의사항**: -> - 반드시 **1→2→3→4** 순서 (DB 먼저, 코드 나중) -> - 4단계(코드 배포) 전에 3단계(.env)까지 완료되어야 함 -> - 5단계(samdb 삭제)는 4단계 동작 확인 후 선택적 수행 - ---- - -## 6. 아키텍처 다이어그램 - -``` - React (사용자) - | - API 서버 (Laravel) - | - ┌─────┴─────┐ - | | - samdb sam_stat - (서비스 DB) (통계 DB) - | - | (공통 + API 사용 테이블: users, tenants, barobill_*, esign_*, audit_* 등) - | - MNG (관리자) - | - ┌─────┴─────┐ - | | - samdb codebridge - (공통 참조) (MNG 전용 59개) -``` - -- **React → API → samdb**: 서비스 트래픽 (수주, 견적, 생산, 바로빌, 전자서명 등) -- **MNG → samdb**: 공통 테이블 (users, tenants, menus) + API 사용 테이블 22개 참조 -- **MNG → codebridge**: MNG 전용 데이터 (영업관리, 재무, 설비, PM 도구 등) - ---- - -## 관련 문서 - -- [database/README.md](README.md) — DB 스키마 전체 현황 -- [codebridge-db-separation-plan.md](/home/aweso/sam/docs/plans/codebridge-db-separation-plan.md) — 분리 작업 계획서 (plans/) - ---- - -**최종 업데이트**: 2026-03-09 (운영 revert 반영, 적용 절차 5단계로 개정)