chore(release): 7.0.9 출시 준비 — 출시일자 정렬·공개 배포물 정합 결함 정리
7.0.9 릴리즈 사전 점검에서 공개 배포물에 실릴 결함을 전수 정리한다. 출시일자: 이번 사이클에 버전이 오르거나 새로 추가된 대상 10건의 CHANGELOG 출시일을 실제 공개일로 정렬. 결제 3종은 직전 릴리즈 페이로드로 이미 나갔으므로 제외했다. 내부 역할 호칭: 공개 배포물 26파일 49곳을 중립 표현으로 치환. 이미 공개된 페이로드에는 실질 0건이라 이번 릴리즈가 첫 유입이었다. 최초 출시 규격: 신규 플러그인과 그 언어팩의 CHANGELOG 를 선례 규격으로 재구성. 작성 중 확인되지 않은 서술 2건은 코드 실측으로 교정했다. 번들 ja 언어팩: 번역 값에 남은 한글 40건 정정. 같은 용어가 세 갈래로 갈려 있던 표기도 함께 통일했다. 정정값의 근거는 저장소가 이미 갖고 있었다 — 테스트가 정답으로 단언하는 값과 배포물이 어긋난 상태였다. 재발 방지: 원인은 번역 생성기의 용어집 미등록이므로 출력만 고치면 다음 빌드에서 되살아난다. 용어집에 8건을 등록하고, 규정 3건과 잔존 검출 룰을 신설했다. 룰은 수정 전 배포물로 red 가 되는지를 픽스처로 고정해 판정기가 모집단에 닿는지를 증명한다.
This commit is contained in:
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며,
|
형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며,
|
||||||
[Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다.
|
[Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다.
|
||||||
|
|
||||||
## [7.0.9] - 2026-08-22
|
## [7.0.9] - 2026-08-24
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
|||||||
@@ -492,7 +492,20 @@ G7 는 일본어 번들 언어팩 12종을 공식 제공합니다. ko 원본을
|
|||||||
- 통화/숫자 단위 변환 금지 (런타임 처리)
|
- 통화/숫자 단위 변환 금지 (런타임 처리)
|
||||||
- 공식체(です·ます) 강제, 친근체 금지
|
- 공식체(です·ます) 강제, 친근체 금지
|
||||||
- 한글 미포함 value(영문/숫자/기호만) 는 번역 스킵 → 원문 유지
|
- 한글 미포함 value(영문/숫자/기호만) 는 번역 스킵 → 원문 유지
|
||||||
- 고정 용어집 50항목으로 일관성 강제 (예: `관리자 → 管理者`, `장바구니 → カート`)
|
- 고정 용어집으로 일관성 강제 (예: `관리자 → 管理者`, `장바구니 → カート`)
|
||||||
|
|
||||||
|
### 용어집 등록 의무
|
||||||
|
|
||||||
|
번역 결과의 표기는 고정 용어집이 정한다. 용어집에 없는 도메인 용어는 어간만 번역되어
|
||||||
|
**원본 로케일 문자가 값에 그대로 남는다** — 예외도 오류도 나지 않고, 키 대칭 검사도 값은 보지 않으므로
|
||||||
|
그 로케일로 화면을 열기 전까지 드러나지 않는다.
|
||||||
|
|
||||||
|
- 새 도메인 용어를 도입하면 번역 빌드 **전에** 용어집에 등록한다
|
||||||
|
- 이미 생성된 값을 손으로 고쳤다면 용어집도 함께 고친다 — 용어집을 두면 다음 키에서 같은 오역이 되풀이된다
|
||||||
|
- 같은 용어는 팩 전체에서 한 표기로 통일한다 (용어집이 단일 출처)
|
||||||
|
|
||||||
|
정적 검사가 번역 값의 원본 로케일 문자 잔존을 검출한다. 매니페스트와 CHANGELOG,
|
||||||
|
그리고 한국어 주석은 대상이 아니다.
|
||||||
|
|
||||||
### 설치 및 활성화
|
### 설치 및 활성화
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며,
|
형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며,
|
||||||
[Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다.
|
[Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다.
|
||||||
|
|
||||||
## [1.0.8] - 2026-08-22
|
## [1.0.8] - 2026-08-24
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,13 @@
|
|||||||
형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며,
|
형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며,
|
||||||
[Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다.
|
[Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다.
|
||||||
|
|
||||||
|
## [1.1.3] - 2026-08-24
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- 배송업체 이름(한진·롯데·로젠)이 일본어 화면에서 "택배" 부분만 한국어로 표시되던 문제를 수정했습니다. 관리자 배송정책 화면과 초기 배송업체 데이터 모두 일본어 표기로 통일했습니다.
|
||||||
|
- 모듈 소개 문구의 제품명이 한국어로 표시되던 문제를 수정했습니다.
|
||||||
|
|
||||||
## [1.1.2] - 2026-08-22
|
## [1.1.2] - 2026-08-22
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
+3
-3
@@ -16,9 +16,9 @@
|
|||||||
},
|
},
|
||||||
"carrier": {
|
"carrier": {
|
||||||
"cj": "CJ大韓通運",
|
"cj": "CJ大韓通運",
|
||||||
"hanjin": "韓進택배",
|
"hanjin": "ハンジン宅配",
|
||||||
"lotte": "ロッテ택배",
|
"lotte": "ロッテ宅配",
|
||||||
"logen": "ロジェン택배",
|
"logen": "ロジェン宅配",
|
||||||
"ups": "UPS",
|
"ups": "UPS",
|
||||||
"fedex": "FedEx",
|
"fedex": "FedEx",
|
||||||
"dhl": "DHL",
|
"dhl": "DHL",
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
"en": "G7 module (sirsoft-ecommerce) Japanese language pack (bundled)",
|
"en": "G7 module (sirsoft-ecommerce) Japanese language pack (bundled)",
|
||||||
"ja": "G7 モジュール (sirsoft-ecommerce) 日本語 言語パック(バンドル)"
|
"ja": "G7 モジュール (sirsoft-ecommerce) 日本語 言語パック(バンドル)"
|
||||||
},
|
},
|
||||||
"version": "1.1.2",
|
"version": "1.1.3",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scope": "module",
|
"scope": "module",
|
||||||
"target_identifier": "sirsoft-ecommerce",
|
"target_identifier": "sirsoft-ecommerce",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"name": "eコマース",
|
"name": "eコマース",
|
||||||
"description": "그누보드7 eコマース モジュール - 商品、注文、決済管理"
|
"description": "グヌボード7 eコマース モジュール - 商品、注文、決済管理"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
"name": "CJ大韓通運"
|
"name": "CJ大韓通運"
|
||||||
},
|
},
|
||||||
"hanjin": {
|
"hanjin": {
|
||||||
"name": "韓進택배"
|
"name": "ハンジン宅配"
|
||||||
},
|
},
|
||||||
"lotte": {
|
"lotte": {
|
||||||
"name": "ロッテ택배"
|
"name": "ロッテ宅配"
|
||||||
},
|
},
|
||||||
"logen": {
|
"logen": {
|
||||||
"name": "ロジェン택배"
|
"name": "ロジェン宅配"
|
||||||
},
|
},
|
||||||
"ups": {
|
"ups": {
|
||||||
"name": "UPS"
|
"name": "UPS"
|
||||||
|
|||||||
@@ -4,8 +4,15 @@
|
|||||||
형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며,
|
형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며,
|
||||||
[Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다.
|
[Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다.
|
||||||
|
|
||||||
## [1.0.0] - 2026-07-28
|
## [1.0.0] - 2026-08-24
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- 비즈뿌리오 메시징 플러그인(sirsoft-message_bizppurio)의 일본어 번들 언어팩을 제공합니다. 환경설정·알림톡 템플릿 작성/검수 신청/승인 관리·템플릿 통합 관리·발송 이력 화면과 발송 결과 안내가 일본어 로케일에서 자연스럽게 표시됩니다. 템플릿 작성 시 입력값 오류 안내도 항목 이름까지 일본어로 표시됩니다. 알림 편집 창에 통합된 알림톡 템플릿·문자(SMS) 섹션의 제목·안내·승인 여부 배지(승인됨/미승인)와 검수자 전달 의견 입력란의 라벨·안내도 일본어로 표시됩니다.
|
- 비즈뿌리오 메시지 발송 플러그인(sirsoft-message_bizppurio)의 일본어 번들 언어팩 초기 제공
|
||||||
|
- 관리자 환경설정 문구(비즈뿌리오 아이디·비밀번호·발신번호·알림톡 발신프로필키·결과 수신 주소, 검수 모드와 운영 전환 경고)의 일본어 번역
|
||||||
|
- 알림 편집 창에 통합된 알림톡 템플릿·문자(SMS) 섹션의 제목·안내 문구와 승인 여부 배지(승인됨 / 미승인)의 일본어 번역
|
||||||
|
- 검수자 전달 의견 입력란의 라벨·안내 문구의 일본어 번역
|
||||||
|
- 알림톡 템플릿 작성·검수 신청·승인 관리 화면 문구의 일본어 번역
|
||||||
|
- 템플릿 통합 관리 화면과 발송 이력 화면 문구의 일본어 번역
|
||||||
|
- 발송 결과 안내 문구의 일본어 번역
|
||||||
|
- 템플릿 작성 시 입력값 오류 안내의 일본어 번역 — 항목 이름까지 일본어로 표시됩니다.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ビズプリオ メッセージ発送",
|
"name": "ビズプリオ メッセージ発送",
|
||||||
"description": "ビズプリオ 連動 SMS/LMS・カカオ アラート톡 発送プラグインです。",
|
"description": "ビズプリオ 連動 SMS/LMS・カカオ アラートトーク 発送プラグインです。",
|
||||||
"settings": {
|
"settings": {
|
||||||
"title": "ビズプリオ メッセージ発送 設定",
|
"title": "ビズプリオ メッセージ発送 設定",
|
||||||
"description": "ビズプリオ 連動情報と発送 設定を管理します。",
|
"description": "ビズプリオ 連動情報と発送 設定を管理します。",
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
"account_notice": "検査と運用は別の ビズプリオ アカウントで運営することをお勧めします。"
|
"account_notice": "検査と運用は別の ビズプリオ アカウントで運営することをお勧めします。"
|
||||||
},
|
},
|
||||||
"live_mode_warning_title": "運用環境で発送されます",
|
"live_mode_warning_title": "運用環境で発送されます",
|
||||||
"live_mode_warning_body": "検査モードがオフになっているため、実際の顧客にSMS・アラート톡が発送され、発送費用が請求されます。検査段階では検査モードをオンにしてください。",
|
"live_mode_warning_body": "検査モードがオフになっているため、実際の顧客にSMS・アラートトークが発送され、発送費用が請求されます。検査段階では検査モードをオンにしてください。",
|
||||||
"sections": {
|
"sections": {
|
||||||
"api": {
|
"api": {
|
||||||
"title": "API 連動",
|
"title": "API 連動",
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
},
|
},
|
||||||
"sending": {
|
"sending": {
|
||||||
"title": "発送 設定",
|
"title": "発送 設定",
|
||||||
"description": "文字・アラート톡発送に使用する発信情報です。"
|
"description": "文字・アラートトーク発送に使用する発信情報です。"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fields": {
|
"fields": {
|
||||||
@@ -49,16 +49,16 @@
|
|||||||
},
|
},
|
||||||
"sender_number": {
|
"sender_number": {
|
||||||
"label": "発信番号",
|
"label": "発信番号",
|
||||||
"hint": "文字・アラート톡発送に使用する発信電話番号です。"
|
"hint": "文字・アラートトーク発送に使用する発信電話番号です。"
|
||||||
},
|
},
|
||||||
"sender_key": {
|
"sender_key": {
|
||||||
"label": "アラート톡 発信プロファイル キー",
|
"label": "アラートトーク 発信プロフィール キー",
|
||||||
"hint": "アラート톡 発送・テンプレート確認に使用する発信プロファイル キー(40文字)です。"
|
"hint": "アラートトーク 発送・テンプレート確認に使用する発信プロフィール キー(40文字)です。"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"report": {
|
"report": {
|
||||||
"section_title": "レポート受信 設定",
|
"section_title": "レポート受信 設定",
|
||||||
"hint": "ビズプリオ は文字・アラート톡発送後、成功/失敗の結果をこのアドレスに転送(URL PUSH)するレポート受信方式を提供します。以下のアドレスを ビズプリオ ビジネスチーム(または管理コンソールのレポート受信 設定)に登録してください。",
|
"hint": "ビズプリオ は文字・アラートトーク発送後、成功/失敗の結果をこのアドレスに転送(URL PUSH)するレポート受信方式を提供します。以下のアドレスを ビズプリオ ビジネスチーム(または管理コンソールのレポート受信 設定)に登録してください。",
|
||||||
"note": "登録すると発送結果が履歴に自動記録され、実際に到達したかどうかを確認できます。登録前は発送リクエストまで確認され、最終結果(成功/失敗)は更新されません。",
|
"note": "登録すると発送結果が履歴に自動記録され、実際に到達したかどうかを確認できます。登録前は発送リクエストまで確認され、最終結果(成功/失敗)は更新されません。",
|
||||||
"copy": "コピー",
|
"copy": "コピー",
|
||||||
"copied": "レポート受信アドレスがクリップボードにコピーされました。"
|
"copied": "レポート受信アドレスがクリップボードにコピーされました。"
|
||||||
@@ -68,12 +68,12 @@
|
|||||||
"templates": "通知テンプレート管理"
|
"templates": "通知テンプレート管理"
|
||||||
},
|
},
|
||||||
"preparation": {
|
"preparation": {
|
||||||
"intro": "文字・カカオ アラート톡を発送するには、まず ビズプリオ コンソールで以下の事前準備を完了する必要があります。",
|
"intro": "文字・カカオ アラートトークを発送するには、まず ビズプリオ コンソールで以下の事前準備を完了する必要があります。",
|
||||||
"sms_label": "文字(SMS/LMS)",
|
"sms_label": "文字(SMS/LMS)",
|
||||||
"sms_sender": "発信番号を登録してください。",
|
"sms_sender": "発信番号を登録してください。",
|
||||||
"kakao_label": "カカオ アラート톡",
|
"kakao_label": "カカオ アラートトーク",
|
||||||
"kakao_channel": "카카오톡 ビジネスチャネルを作成し、発信プロファイルを登録してください。",
|
"kakao_channel": "カカオトーク ビジネスチャネルを作成し、発信プロフィールを登録してください。",
|
||||||
"kakao_template": "アラームトークテンプレートは管理者の通知設定(ビズプリオタブ)で作成して審査を申請します。",
|
"kakao_template": "アラートトークテンプレートは管理者の通知設定(ビズプリオタブ)で作成して審査を申請します。",
|
||||||
"kakao_apikey": "カスタマーセンターに API キーをリクエストしてください。",
|
"kakao_apikey": "カスタマーセンターに API キーをリクエストしてください。",
|
||||||
"console_link": "ビズプリオ コンソールを開く"
|
"console_link": "ビズプリオ コンソールを開く"
|
||||||
}
|
}
|
||||||
@@ -90,14 +90,14 @@
|
|||||||
"test_mode": "検査モードです — 実際の発送は行われません。"
|
"test_mode": "検査モードです — 実際の発送は行われません。"
|
||||||
},
|
},
|
||||||
"dispatch_result": {
|
"dispatch_result": {
|
||||||
"column_header": "文字・アラート톡 結果",
|
"column_header": "文字・アラートトーク 結果",
|
||||||
"inspection_label": "検査",
|
"inspection_label": "検査",
|
||||||
"low_balance": "残高不足",
|
"low_balance": "残高不足",
|
||||||
"fallback": "SMS 代替発送 {status}",
|
"fallback": "SMS 代替発送 {status}",
|
||||||
"detail_title": "文字・アラート톡 発送 結果",
|
"detail_title": "文字・アラートトーク 発送 結果",
|
||||||
"channel_label": "発送チャネル: {channel}",
|
"channel_label": "発送チャネル: {channel}",
|
||||||
"sent_content_label": "実際の発送内容",
|
"sent_content_label": "実際の発送内容",
|
||||||
"sent_content_hint": "アラート톡 は承認確定されたテンプレート内容で発送され、上記の\"本文\"と異なる場合があります。"
|
"sent_content_hint": "アラートトーク は承認確定されたテンプレート内容で発送され、上記の\"本文\"と異なる場合があります。"
|
||||||
},
|
},
|
||||||
"editor": {
|
"editor": {
|
||||||
"data_source": {
|
"data_source": {
|
||||||
@@ -105,7 +105,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"template": {
|
"template": {
|
||||||
"tab_guide": "各通知の[編集]でアラームトークのテンプレートとSMS本文をまとめて作成し、審査を申請してください。カカオの承認後にアラームトークが自動送信され、代替SMS・SMS単独送信も同じ画面で設定します。",
|
"tab_guide": "各通知の[編集]でアラートトークのテンプレートとSMS本文をまとめて作成し、審査を申請してください。カカオの承認後にアラートトークが自動送信され、代替SMS・SMS単独送信も同じ画面で設定します。",
|
||||||
"status": {
|
"status": {
|
||||||
"unwritten": "未作成",
|
"unwritten": "未作成",
|
||||||
"draft": "作成中",
|
"draft": "作成中",
|
||||||
@@ -117,12 +117,12 @@
|
|||||||
"dormant": "休眠"
|
"dormant": "休眠"
|
||||||
},
|
},
|
||||||
"row": {
|
"row": {
|
||||||
"alimtalk_label": "アラームトーク",
|
"alimtalk_label": "アラートトーク",
|
||||||
"requested_on": "{date} 申請",
|
"requested_on": "{date} 申請",
|
||||||
"synced_on": "{date} 同期",
|
"synced_on": "{date} 同期",
|
||||||
"alimtalk_enabled": "送信を使用",
|
"alimtalk_enabled": "送信を使用",
|
||||||
"btn_view_reason": "理由を表示",
|
"btn_view_reason": "理由を表示",
|
||||||
"btn_compose": "アラームトークテンプレート作成",
|
"btn_compose": "アラートトークテンプレート作成",
|
||||||
"btn_edit": "編集",
|
"btn_edit": "編集",
|
||||||
"btn_edit_approved": "編集 (承認取り消し)",
|
"btn_edit_approved": "編集 (承認取り消し)",
|
||||||
"btn_request": "審査申請",
|
"btn_request": "審査申請",
|
||||||
@@ -144,7 +144,7 @@
|
|||||||
"alimtalk_disabled": "送信停止中"
|
"alimtalk_disabled": "送信停止中"
|
||||||
},
|
},
|
||||||
"form": {
|
"form": {
|
||||||
"modal_title": "アラームトークテンプレート — {name}",
|
"modal_title": "アラートトークテンプレート — {name}",
|
||||||
"rejected_banner": "却下されたテンプレートです。以下の理由を確認し、修正後に再度申請してください。",
|
"rejected_banner": "却下されたテンプレートです。以下の理由を確認し、修正後に再度申請してください。",
|
||||||
"sender_profile": "発信プロフィール",
|
"sender_profile": "発信プロフィール",
|
||||||
"sender_profile_placeholder": "発信プロフィール選択(参考用)",
|
"sender_profile_placeholder": "発信プロフィール選択(参考用)",
|
||||||
@@ -207,17 +207,17 @@
|
|||||||
"request_comment_placeholder": "例: #{name}=山田太郎, #{order_number}=20260823-0001",
|
"request_comment_placeholder": "例: #{name}=山田太郎, #{order_number}=20260823-0001",
|
||||||
"request_comment_hint": "審査申請時にカカオの審査担当者へ一緒に送られます(任意・500文字以内)。カカオの審査ガイドは本文の変数ごとに例示値を求めるため、変数ごとの例を書いておくと差し戻しを減らせます。保存はされず、申請時にのみ送信されます。",
|
"request_comment_hint": "審査申請時にカカオの審査担当者へ一緒に送られます(任意・500文字以内)。カカオの審査ガイドは本文の変数ごとに例示値を求めるため、変数ごとの例を書いておくと差し戻しを減らせます。保存はされず、申請時にのみ送信されます。",
|
||||||
"saved_toast": "通知テンプレートを保存しました。",
|
"saved_toast": "通知テンプレートを保存しました。",
|
||||||
"requested_toast": "審査を申請しました。承認されるとアラームトーク送信が開始されます。"
|
"requested_toast": "審査を申請しました。承認されるとアラートトーク送信が開始されます。"
|
||||||
},
|
},
|
||||||
"sms": {
|
"sms": {
|
||||||
"modal_title": "SMS本文 — {name}",
|
"modal_title": "SMS本文 — {name}",
|
||||||
"hint": "代替SMSとSMS単独送信に共通で使用する本文です。#{변수} は送信時に自動置換されます。",
|
"hint": "代替SMSとSMS単独送信に共通で使用する本文です。#{変数} は送信時に自動置換されます。",
|
||||||
"btn_save": "保存",
|
"btn_save": "保存",
|
||||||
"saved_toast": "SMS本文を保存しました。"
|
"saved_toast": "SMS本文を保存しました。"
|
||||||
},
|
},
|
||||||
"cancel_approval": {
|
"cancel_approval": {
|
||||||
"modal_title": "承認取り消しの確認",
|
"modal_title": "承認取り消しの確認",
|
||||||
"warning": "「{name}」テンプレートの承認を取り消すと、直ちにこの通知のアラームトーク送信が停止されます。(代替SMS・SMS単独送信はSMS設定に従って継続されます。)修正後に再度審査を申請して承認を受けると、アラームトーク送信が再開されます。",
|
"warning": "「{name}」テンプレートの承認を取り消すと、直ちにこの通知のアラートトーク送信が停止されます。(代替SMS・SMS単独送信はSMS設定に従って継続されます。)修正後に再度審査を申請して承認を受けると、アラートトーク送信が再開されます。",
|
||||||
"btn_confirm": "承認を取り消して編集",
|
"btn_confirm": "承認を取り消して編集",
|
||||||
"done_toast": "承認を取り消しました。修正後に再度審査を申請してください。"
|
"done_toast": "承認を取り消しました。修正後に再度審査を申請してください。"
|
||||||
},
|
},
|
||||||
@@ -230,9 +230,9 @@
|
|||||||
"not_approved": "未承認"
|
"not_approved": "未承認"
|
||||||
},
|
},
|
||||||
"section": {
|
"section": {
|
||||||
"alimtalk_title": "アラームトークテンプレート",
|
"alimtalk_title": "アラートトークテンプレート",
|
||||||
"sms_title": "SMS",
|
"sms_title": "SMS",
|
||||||
"alimtalk_enabled": "アラームトーク送信を使用",
|
"alimtalk_enabled": "アラートトーク送信を使用",
|
||||||
"locked_hint": "審査中または承認済みのテンプレートは内容を変更できません。変更するには先に[申請取消]または[編集(承認取消)]を押してください。",
|
"locked_hint": "審査中または承認済みのテンプレートは内容を変更できません。変更するには先に[申請取消]または[編集(承認取消)]を押してください。",
|
||||||
"saved_toast": "通知テンプレートを保存しました。",
|
"saved_toast": "通知テンプレートを保存しました。",
|
||||||
"loading": "テンプレートを読み込み中…"
|
"loading": "テンプレートを読み込み中…"
|
||||||
@@ -248,7 +248,7 @@
|
|||||||
"btn_edit": "編集",
|
"btn_edit": "編集",
|
||||||
"btn_delete": "削除",
|
"btn_delete": "削除",
|
||||||
"empty": "登録されたビズプリオ通知テンプレートがありません。",
|
"empty": "登録されたビズプリオ通知テンプレートがありません。",
|
||||||
"empty_hint": "管理者の通知設定のビズプリオタブでアラームトークテンプレートを作成するか、SMSを設定するとここに表示されます。",
|
"empty_hint": "管理者の通知設定のビズプリオタブでアラートトークテンプレートを作成するか、SMSを設定するとここに表示されます。",
|
||||||
"sms_only": "単独",
|
"sms_only": "単独",
|
||||||
"sms_fallback": "代替",
|
"sms_fallback": "代替",
|
||||||
"owner": {
|
"owner": {
|
||||||
@@ -259,7 +259,7 @@
|
|||||||
"columns": {
|
"columns": {
|
||||||
"notification": "通知",
|
"notification": "通知",
|
||||||
"owner": "所属",
|
"owner": "所属",
|
||||||
"status": "アラームトークステータス",
|
"status": "アラートトークステータス",
|
||||||
"sms": "SMS",
|
"sms": "SMS",
|
||||||
"requested_at": "申請日",
|
"requested_at": "申請日",
|
||||||
"synced_at": "同期",
|
"synced_at": "同期",
|
||||||
@@ -275,11 +275,11 @@
|
|||||||
},
|
},
|
||||||
"templates": {
|
"templates": {
|
||||||
"readiness": {
|
"readiness": {
|
||||||
"title": "アラームトークテンプレートを使用するには、以下の設定が必要です",
|
"title": "アラートトークテンプレートを使用するには、以下の設定が必要です",
|
||||||
"go_settings": "環境設定に移動",
|
"go_settings": "環境設定に移動",
|
||||||
"missing_label": "未設定項目",
|
"missing_label": "未設定項目",
|
||||||
"api_key_missing": "カカオ管理API キー",
|
"api_key_missing": "カカオ管理API キー",
|
||||||
"sender_key_missing": "アラームトーク送信プロフィールキー",
|
"sender_key_missing": "アラートトーク送信プロフィールキー",
|
||||||
"note": "上記項目を環境設定タブで入力すると、テンプレートの作成・審査申請が可能になります。実際の送信は検査モードをオフにして運用に切り替えた後、承認されたテンプレートのみ使用できます。"
|
"note": "上記項目を環境設定タブで入力すると、テンプレートの作成・審査申請が可能になります。実際の送信は検査モードをオフにして運用に切り替えた後、承認されたテンプレートのみ使用できます。"
|
||||||
},
|
},
|
||||||
"list": {
|
"list": {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며,
|
형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며,
|
||||||
[Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다.
|
[Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다.
|
||||||
|
|
||||||
## [1.0.7] - 2026-08-22
|
## [1.0.7] - 2026-08-24
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,12 @@
|
|||||||
형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며,
|
형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며,
|
||||||
[Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다.
|
[Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다.
|
||||||
|
|
||||||
|
## [1.1.2] - 2026-08-24
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- 첫 화면 소개 문구의 제품명이 한국어로 표시되던 문제를 수정했습니다.
|
||||||
|
|
||||||
## [1.1.1] - 2026-08-19
|
## [1.1.1] - 2026-08-19
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"welcome": {
|
"welcome": {
|
||||||
"title": "いらっしゃいませ!",
|
"title": "いらっしゃいませ!",
|
||||||
"description": "그누보드7 コミュニティへようこそ。",
|
"description": "グヌボード7 コミュニティへようこそ。",
|
||||||
"login_prompt": "ログインしてコミュニティに参加してください。",
|
"login_prompt": "ログインしてコミュニティに参加してください。",
|
||||||
"greeting": "こんにちは、{{name}}さん!"
|
"greeting": "こんにちは、{{name}}さん!"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
"en": "G7 template (sirsoft-basic) Japanese language pack (bundled)",
|
"en": "G7 template (sirsoft-basic) Japanese language pack (bundled)",
|
||||||
"ja": "G7 テンプレート (sirsoft-basic) 日本語 言語パック(バンドル)"
|
"ja": "G7 テンプレート (sirsoft-basic) 日本語 言語パック(バンドル)"
|
||||||
},
|
},
|
||||||
"version": "1.1.1",
|
"version": "1.1.2",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scope": "template",
|
"scope": "template",
|
||||||
"target_identifier": "sirsoft-basic",
|
"target_identifier": "sirsoft-basic",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며,
|
형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며,
|
||||||
[Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다.
|
[Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다.
|
||||||
|
|
||||||
## [1.1.0] - 2026-08-22
|
## [1.1.0] - 2026-08-24
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며,
|
형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며,
|
||||||
[Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다.
|
[Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다.
|
||||||
|
|
||||||
## [1.2.0] - 2026-08-22
|
## [1.2.0] - 2026-08-24
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며,
|
형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며,
|
||||||
[Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다.
|
[Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다.
|
||||||
|
|
||||||
## [1.1.0] - 2026-08-22
|
## [1.1.0] - 2026-08-24
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
|||||||
@@ -4,13 +4,48 @@
|
|||||||
형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며,
|
형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며,
|
||||||
[Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다.
|
[Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다.
|
||||||
|
|
||||||
## [1.0.0] - 2026-07-28
|
## [1.0.0] - 2026-08-24
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- 비즈뿌리오 연동 환경설정 화면과 문자(SMS/LMS)·카카오 알림톡 발송 채널을 추가했습니다. 회원가입·주문 등 코어 알림에 자동 연결되며, 검수/운영 환경을 구분해 운영합니다.
|
#### 문자·알림톡 발송
|
||||||
- 알림 설정 화면의 '비즈뿌리오' 통합 탭에서 각 알림의 [편집]을 누르면 알림 템플릿 편집 창 안에서 카카오 알림톡 템플릿을 직접 작성해 검수를 신청하고, 승인되면 그 내용으로 자동 발송됩니다. 기본형·부가정보형·채널추가형·복합형과 강조표기·이미지·아이템리스트 등 카카오 전 유형과 버튼·바로연결을 지원하며, 검수 결과는 30분 주기로 자동 확인되고 편집 창의 [새로고침]으로 즉시 확인할 수 있습니다. 검수 신청 시 변수 예시값 등 검수자에게 전달할 의견을 함께 적어 보낼 수 있으며, 반려되면 사유를 같은 창에서 확인하고 수정 후 다시 신청합니다. 알림 목록의 각 행에는 승인 여부(승인됨 / 미승인·세부 상태)와 문자 설정 요약이 표시됩니다. 게시판·이커머스 알림 설정 화면에서도 동일하게 동작합니다.
|
|
||||||
- 같은 편집 창에서 알림별 대체 SMS(알림톡 실패 시)·SMS 단독 발송 여부와 문자 본문을 함께 설정하고, 하단 [저장] 한 번으로 알림톡 템플릿·문자 설정·수신자 규칙을 모두 저장합니다. 문자 본문은 언어별로 입력하며 회원이 사용하는 언어로 발송됩니다(해당 언어가 비어 있으면 기본 언어로 발송). [SMS 단독]을 선택한 알림은 템플릿이 승인되어 있어도 알림톡을 보내지 않고 문자로만 발송합니다. 검수중·승인된 템플릿은 내용이 잠기며, 승인 취소는 즉시 알림톡 발송이 중단됨을 같은 창에서 확인한 뒤 진행합니다.
|
- 비즈뿌리오 연동 문자(SMS/LMS)·카카오 알림톡 발송 플러그인 최초 릴리즈. 회원가입·주문 등 코어 알림에 자동 연결되어 메일과 같은 방식으로 발송됩니다.
|
||||||
|
- 비즈뿌리오 계정 정보와 발신번호를 입력하는 환경설정 화면을 제공합니다.
|
||||||
|
- 검수 환경과 운영 환경을 구분해 운영합니다. 설치 직후에는 검수 환경이 기본이며, 환경설정에서 운영 환경으로 전환하면 그때부터 실제 고객에게 발송됩니다.
|
||||||
|
|
||||||
|
#### 알림톡 템플릿 작성·검수
|
||||||
|
|
||||||
|
- 알림 설정의 '비즈뿌리오' 통합 탭에서 각 알림의 [편집]을 누르면, 알림 템플릿 편집 창 안에서 카카오 알림톡 템플릿을 직접 작성해 검수를 신청할 수 있습니다.
|
||||||
|
- 승인된 템플릿은 그 내용으로 자동 발송됩니다. 승인 전에는 알림톡이 발송되지 않습니다.
|
||||||
|
- 기본형·부가정보형·채널추가형·복합형과 강조표기·이미지·아이템리스트 등 카카오 전 유형을 지원하며, 버튼과 바로연결도 함께 등록할 수 있습니다.
|
||||||
|
- 검수 결과는 30분 주기로 자동 확인되며, 편집 창의 [새로고침]으로 즉시 확인할 수 있습니다.
|
||||||
|
- 검수를 신청할 때 변수 예시값처럼 검수자에게 전달할 의견을 함께 적어 보낼 수 있습니다.
|
||||||
|
- 반려되면 사유를 같은 창에서 확인하고 수정 후 다시 신청합니다.
|
||||||
|
- 알림 목록의 각 행에 승인 여부(승인됨 / 미승인·세부 상태)와 문자 설정 요약이 표시됩니다.
|
||||||
|
- 게시판·이커머스의 알림 설정 화면에서도 동일하게 동작합니다.
|
||||||
|
|
||||||
|
#### 문자(SMS) 설정
|
||||||
|
|
||||||
|
- 같은 편집 창에서 알림별로 알림톡 실패 시 대체 SMS 사용 여부, SMS 단독 발송 여부, 문자 본문을 함께 설정합니다.
|
||||||
|
- 하단 [저장] 한 번으로 알림톡 템플릿·문자 설정·수신자 규칙이 모두 저장됩니다.
|
||||||
|
- 문자 본문은 언어별로 입력하며 회원이 사용하는 언어로 발송됩니다. 해당 언어가 비어 있으면 기본 언어로 발송됩니다.
|
||||||
|
- [SMS 단독]을 선택한 알림은 템플릿이 승인되어 있어도 알림톡을 보내지 않고 문자로만 발송합니다.
|
||||||
|
- 검수중·승인된 템플릿은 내용이 잠깁니다. 승인 취소는 즉시 알림톡 발송이 중단됨을 같은 창에서 확인한 뒤 진행합니다.
|
||||||
|
|
||||||
|
#### 템플릿 관리
|
||||||
|
|
||||||
- 플러그인 설정의 '알림 템플릿 관리' 화면에서 모든 알림의 템플릿 상태를 한눈에 보고 검색·필터·수정·삭제할 수 있습니다.
|
- 플러그인 설정의 '알림 템플릿 관리' 화면에서 모든 알림의 템플릿 상태를 한눈에 보고 검색·필터·수정·삭제할 수 있습니다.
|
||||||
- 비즈뿌리오 webhook 으로 발송 결과를 수신해 "알림 발송 이력" 화면에 성공/실패와 사유를 기록하며, 지갑 잔액 부족 등으로 발송이 막히면 관리자에게 알립니다. 요청 과다로 인한 일시적 발송 실패도 사유가 표시됩니다.
|
- 좁은 화면에서는 목록이 카드 형태로 전환되어 모바일에서도 상태를 확인할 수 있습니다.
|
||||||
- 플러그인을 삭제하면 추가했던 발송 채널이 함께 정리되고, 재설치 시 자동 복원됩니다.
|
|
||||||
|
#### 발송 결과·이력
|
||||||
|
|
||||||
|
- 비즈뿌리오 webhook 으로 발송 결과를 수신해 "알림 발송 이력" 화면에 성공/실패와 사유를 기록합니다.
|
||||||
|
- 지갑 잔액 부족 등으로 발송이 막히면 관리자에게 알립니다.
|
||||||
|
- 요청 과다로 인한 일시적 발송 실패도 사유가 함께 표시됩니다.
|
||||||
|
|
||||||
|
#### 안내
|
||||||
|
|
||||||
|
- 플러그인을 삭제하면 추가했던 발송 채널이 함께 정리되고, 재설치하면 자동 복원됩니다.
|
||||||
|
- 한국어·영어를 기본 제공하며, 일본어는 번들 언어팩으로 제공됩니다.
|
||||||
|
- 코어 7.0.6 이상이 필요합니다.
|
||||||
|
|||||||
+4
-4
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"extension_point": "notification_definition_row_footer",
|
"extension_point": "notification_definition_row_footer",
|
||||||
"comment": "알림 설정 '비즈뿌리오' 통합 탭의 각 알림 행 하단 상태 요약(PO 결정 2026-08-23 — 버튼 없음, 조작은 코어 [편집] 모달로 일원화). activeChannel==='alimtalk'(통합 탭 정체성)일 때만 노출. 요약 데이터는 bizppurioTemplates(각 탭 오버레이가 등록·조회, GET templates/map)에서 def.type 으로 읽는다. 1줄: 알림톡 승인 2단 배지 + 신청/동기화일 + 발송 사용 여부 / 2줄: 문자(SMS) 대체·단독 사용 여부 + 본문 미리보기.",
|
"comment": "알림 설정 '비즈뿌리오' 통합 탭의 각 알림 행 하단 상태 요약(제품 결정 2026-08-23 — 버튼 없음, 조작은 코어 [편집] 모달로 일원화). activeChannel==='alimtalk'(통합 탭 정체성)일 때만 노출. 요약 데이터는 bizppurioTemplates(각 탭 오버레이가 등록·조회, GET templates/map)에서 def.type 으로 읽는다. 1줄: 알림톡 승인 2단 배지 + 신청/동기화일 + 발송 사용 여부 / 2줄: 문자(SMS) 대체·단독 사용 여부 + 본문 미리보기.",
|
||||||
"priority": 320,
|
"priority": 320,
|
||||||
"components": [
|
"components": [
|
||||||
{
|
{
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
{
|
{
|
||||||
"type": "basic",
|
"type": "basic",
|
||||||
"name": "Span",
|
"name": "Span",
|
||||||
"comment": "승인 여부 2단 배지(PO 결정 2026-08-23): 1차 = 승인됨/미승인, 2차(괄호) = 세부 상태(미작성·작성중·검수중·반려·휴면·중지·차단). approved 는 세부 없이 단독 표기.",
|
"comment": "승인 여부 2단 배지(제품 결정 2026-08-23): 1차 = 승인됨/미승인, 2차(괄호) = 세부 상태(미작성·작성중·검수중·반려·휴면·중지·차단). approved 는 세부 없이 단독 표기.",
|
||||||
"props": {
|
"props": {
|
||||||
"className": "{{'inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs font-medium flex-shrink-0 ' + ((((bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]) && (bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]?.has_content)) ? bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]?.status : 'unwritten') === 'approved' ? 'bg-green-100 dark:bg-green-900 text-green-700 dark:text-green-200' : (((bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]) && (bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]?.has_content)) ? bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]?.status : 'unwritten') === 'requested' ? 'bg-amber-100 dark:bg-amber-900 text-amber-700 dark:text-amber-200' : (((bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]) && (bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]?.has_content)) ? bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]?.status : 'unwritten') === 'rejected' ? 'bg-red-100 dark:bg-red-800 text-red-700 dark:text-red-100' : ((((bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]) && (bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]?.has_content)) ? bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]?.status : 'unwritten') === 'stopped' || (((bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]) && (bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]?.has_content)) ? bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]?.status : 'unwritten') === 'blocked') ? 'border border-red-400 dark:border-red-500 text-red-600 dark:text-red-400' : (((bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]) && (bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]?.has_content)) ? bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]?.status : 'unwritten') === 'dormant' ? 'bg-orange-100 dark:bg-orange-900 text-orange-700 dark:text-orange-200' : 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300')}}"
|
"className": "{{'inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs font-medium flex-shrink-0 ' + ((((bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]) && (bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]?.has_content)) ? bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]?.status : 'unwritten') === 'approved' ? 'bg-green-100 dark:bg-green-900 text-green-700 dark:text-green-200' : (((bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]) && (bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]?.has_content)) ? bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]?.status : 'unwritten') === 'requested' ? 'bg-amber-100 dark:bg-amber-900 text-amber-700 dark:text-amber-200' : (((bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]) && (bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]?.has_content)) ? bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]?.status : 'unwritten') === 'rejected' ? 'bg-red-100 dark:bg-red-800 text-red-700 dark:text-red-100' : ((((bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]) && (bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]?.has_content)) ? bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]?.status : 'unwritten') === 'stopped' || (((bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]) && (bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]?.has_content)) ? bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]?.status : 'unwritten') === 'blocked') ? 'border border-red-400 dark:border-red-500 text-red-600 dark:text-red-400' : (((bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]) && (bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]?.has_content)) ? bizppurioTemplates?.data?.templates?.[extensionPointProps.definition?.type]?.status : 'unwritten') === 'dormant' ? 'bg-orange-100 dark:bg-orange-900 text-orange-700 dark:text-orange-200' : 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300')}}"
|
||||||
},
|
},
|
||||||
@@ -115,7 +115,7 @@
|
|||||||
"id": "bizppurio_row_sms_fallback",
|
"id": "bizppurio_row_sms_fallback",
|
||||||
"type": "basic",
|
"type": "basic",
|
||||||
"name": "Div",
|
"name": "Div",
|
||||||
"comment": "fallback_sms 상태 배지 — 사용(초록)/미사용(회색). 문구 대신 배지(PO 지시 2026-08-23, 행의 활성·기본·승인 배지와 일관).",
|
"comment": "fallback_sms 상태 배지 — 사용(초록)/미사용(회색). 문구 대신 배지(제품 결정 2026-08-23, 행의 활성·기본·승인 배지와 일관).",
|
||||||
"props": {
|
"props": {
|
||||||
"className": "flex-center gap-1 flex-shrink-0"
|
"className": "flex-center gap-1 flex-shrink-0"
|
||||||
},
|
},
|
||||||
@@ -143,7 +143,7 @@
|
|||||||
"id": "bizppurio_row_sms_only",
|
"id": "bizppurio_row_sms_only",
|
||||||
"type": "basic",
|
"type": "basic",
|
||||||
"name": "Div",
|
"name": "Div",
|
||||||
"comment": "sms_only 상태 배지 — 사용(초록)/미사용(회색). 문구 대신 배지(PO 지시 2026-08-23, 행의 활성·기본·승인 배지와 일관).",
|
"comment": "sms_only 상태 배지 — 사용(초록)/미사용(회색). 문구 대신 배지(제품 결정 2026-08-23, 행의 활성·기본·승인 배지와 일관).",
|
||||||
"props": {
|
"props": {
|
||||||
"className": "flex-center gap-1 flex-shrink-0"
|
"className": "flex-center gap-1 flex-shrink-0"
|
||||||
},
|
},
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"target_layout": "admin_board_settings",
|
"target_layout": "admin_board_settings",
|
||||||
"comment": "[게시판 면 — notification_tab_core.json 과 동일 패턴, target/컴포넌트 id 만 게시판 전용] 알림 설정 '비즈뿌리오' 통합 탭 오버레이(#597 §3.3, PO 결정 2026-08-23 개정). ① 탭 상단 상태 배너(문제 있을 때만: readiness/테스트 모드) + 안내 박스 ② 요약 데이터소스 bizppurioTemplates(GET templates/map)는 탭 진입 시 init_actions 로 조회 — 행 하단 상태 요약(notification_row_footer.json)과 [편집] 모달 섹션(notification_template_form_sections.json)이 공유한다 ③ 작성 셀렉트용 카테고리·발신프로필 데이터소스. 알림톡 작성/검수/SMS 본문 편집 UI 는 코어 [편집] 모달에 주입되므로 이 오버레이는 더 이상 모달을 등록하지 않는다.",
|
"comment": "[게시판 면 — notification_tab_core.json 과 동일 패턴, target/컴포넌트 id 만 게시판 전용] 알림 설정 '비즈뿌리오' 통합 탭 오버레이(#597 §3.3, 제품 결정 2026-08-23 개정). ① 탭 상단 상태 배너(문제 있을 때만: readiness/테스트 모드) + 안내 박스 ② 요약 데이터소스 bizppurioTemplates(GET templates/map)는 탭 진입 시 init_actions 로 조회 — 행 하단 상태 요약(notification_row_footer.json)과 [편집] 모달 섹션(notification_template_form_sections.json)이 공유한다 ③ 작성 셀렉트용 카테고리·발신프로필 데이터소스. 알림톡 작성/검수/SMS 본문 편집 UI 는 코어 [편집] 모달에 주입되므로 이 오버레이는 더 이상 모달을 등록하지 않는다.",
|
||||||
"data_sources": [
|
"data_sources": [
|
||||||
{
|
{
|
||||||
"id": "bizppurioTemplates",
|
"id": "bizppurioTemplates",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"target_layout": "admin_settings",
|
"target_layout": "admin_settings",
|
||||||
"comment": "알림 설정 '비즈뿌리오' 통합 탭 오버레이(#597 §3.3, PO 결정 2026-08-23 개정). ① 탭 상단 상태 배너(문제 있을 때만: readiness/테스트 모드) + 안내 박스 ② 요약 데이터소스 bizppurioTemplates(GET templates/map)는 탭 진입 시 init_actions 로 조회 — 행 하단 상태 요약(notification_row_footer.json)과 [편집] 모달 섹션(notification_template_form_sections.json)이 공유한다 ③ 작성 셀렉트용 카테고리·발신프로필 데이터소스. 알림톡 작성/검수/SMS 본문 편집 UI 는 코어 [편집] 모달에 주입되므로 이 오버레이는 더 이상 모달을 등록하지 않는다.",
|
"comment": "알림 설정 '비즈뿌리오' 통합 탭 오버레이(#597 §3.3, 제품 결정 2026-08-23 개정). ① 탭 상단 상태 배너(문제 있을 때만: readiness/테스트 모드) + 안내 박스 ② 요약 데이터소스 bizppurioTemplates(GET templates/map)는 탭 진입 시 init_actions 로 조회 — 행 하단 상태 요약(notification_row_footer.json)과 [편집] 모달 섹션(notification_template_form_sections.json)이 공유한다 ③ 작성 셀렉트용 카테고리·발신프로필 데이터소스. 알림톡 작성/검수/SMS 본문 편집 UI 는 코어 [편집] 모달에 주입되므로 이 오버레이는 더 이상 모달을 등록하지 않는다.",
|
||||||
"data_sources": [
|
"data_sources": [
|
||||||
{
|
{
|
||||||
"id": "bizppurioTemplates",
|
"id": "bizppurioTemplates",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"target_layout": "admin_ecommerce_settings",
|
"target_layout": "admin_ecommerce_settings",
|
||||||
"comment": "[이커머스 면 — notification_tab_core.json 과 동일 패턴, target/컴포넌트 id 만 이커머스 전용] 알림 설정 '비즈뿌리오' 통합 탭 오버레이(#597 §3.3, PO 결정 2026-08-23 개정). ① 탭 상단 상태 배너(문제 있을 때만: readiness/테스트 모드) + 안내 박스 ② 요약 데이터소스 bizppurioTemplates(GET templates/map)는 탭 진입 시 init_actions 로 조회 — 행 하단 상태 요약(notification_row_footer.json)과 [편집] 모달 섹션(notification_template_form_sections.json)이 공유한다 ③ 작성 셀렉트용 카테고리·발신프로필 데이터소스. 알림톡 작성/검수/SMS 본문 편집 UI 는 코어 [편집] 모달에 주입되므로 이 오버레이는 더 이상 모달을 등록하지 않는다.",
|
"comment": "[이커머스 면 — notification_tab_core.json 과 동일 패턴, target/컴포넌트 id 만 이커머스 전용] 알림 설정 '비즈뿌리오' 통합 탭 오버레이(#597 §3.3, 제품 결정 2026-08-23 개정). ① 탭 상단 상태 배너(문제 있을 때만: readiness/테스트 모드) + 안내 박스 ② 요약 데이터소스 bizppurioTemplates(GET templates/map)는 탭 진입 시 init_actions 로 조회 — 행 하단 상태 요약(notification_row_footer.json)과 [편집] 모달 섹션(notification_template_form_sections.json)이 공유한다 ③ 작성 셀렉트용 카테고리·발신프로필 데이터소스. 알림톡 작성/검수/SMS 본문 편집 UI 는 코어 [편집] 모달에 주입되므로 이 오버레이는 더 이상 모달을 등록하지 않는다.",
|
||||||
"data_sources": [
|
"data_sources": [
|
||||||
{
|
{
|
||||||
"id": "bizppurioTemplates",
|
"id": "bizppurioTemplates",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"extension_point": "notification_template_form_footer_actions",
|
"extension_point": "notification_template_form_footer_actions",
|
||||||
"comment": "코어 알림 템플릿 [편집] 모달 푸터에 주입되는 통합 저장 버튼(PO 결정 2026-08-23 — 저장은 하나로). 채널 메타 hidden_template_editor 로 코어 [저장]/[미리보기]가 숨겨진 자리에서, [저장] 한 번으로 ① 알림톡 템플릿(draft/rejected 만 내용 갱신) + 발송 설정·SMS 본문 ② 수신자 규칙이 바뀐 경우에만 코어 채널 템플릿을 순차 저장한다(앞 단계 실패 시 중단). [저장 후 검수 신청]은 알림톡 본문이 있고 수정 가능한 상태에서만 노출된다 — 카카오 검수는 알림톡 템플릿만 대상이며 SMS 는 검수 없이 즉시 반영된다. 더블클릭 재진입은 click if + disabled 로 막고, 중복 검수 신청의 SSoT 는 서버 원자 선점이다.",
|
"comment": "코어 알림 템플릿 [편집] 모달 푸터에 주입되는 통합 저장 버튼(제품 결정 2026-08-23 — 저장은 하나로). 채널 메타 hidden_template_editor 로 코어 [저장]/[미리보기]가 숨겨진 자리에서, [저장] 한 번으로 ① 알림톡 템플릿(draft/rejected 만 내용 갱신) + 발송 설정·SMS 본문 ② 수신자 규칙이 바뀐 경우에만 코어 채널 템플릿을 순차 저장한다(앞 단계 실패 시 중단). [저장 후 검수 신청]은 알림톡 본문이 있고 수정 가능한 상태에서만 노출된다 — 카카오 검수는 알림톡 템플릿만 대상이며 SMS 는 검수 없이 즉시 반영된다. 더블클릭 재진입은 click if + disabled 로 막고, 중복 검수 신청의 SSoT 는 서버 원자 선점이다.",
|
||||||
"priority": 320,
|
"priority": 320,
|
||||||
"components": [
|
"components": [
|
||||||
{
|
{
|
||||||
|
|||||||
+3
-3
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"extension_point": "notification_template_form_sections",
|
"extension_point": "notification_template_form_sections",
|
||||||
"comment": "코어 알림 템플릿 [편집] 모달 본문에 주입되는 비즈뿌리오 섹션(PO 결정 2026-08-23 — 행 하단 별도 버튼/모달 폐지, 편집 모달 통합). 3면(코어/게시판/이커머스)이 같은 extension_point 를 노출하므로 파일 1본으로 공유한다. ① 알림톡 템플릿: 승인 2단 배지 + 상태 액션(새로고침/신청 취소/승인 취소 후 수정/휴면 해제) + 작성 폼(draft/rejected) 또는 잠금 요약 ② 문자(SMS): 대체/단독 토글 + 로케일별 본문(검수 대상 아님). 저장은 notification_template_form_footer_actions 의 통합 [저장]이 담당한다. 상태는 _global.bz_tpl_modal / bz_sms_modal / bz_tpl_ui / bz_tpl_upload 에 담고 섹션 마운트(lifecycle.onMount) 시 요약 맵(bizppurioTemplates)으로 시딩한다. 코어 제목/본문 입력은 채널 메타 hidden_template_editor 로 코어 모달이 스스로 숨긴다.",
|
"comment": "코어 알림 템플릿 [편집] 모달 본문에 주입되는 비즈뿌리오 섹션(제품 결정 2026-08-23 — 행 하단 별도 버튼/모달 폐지, 편집 모달 통합). 3면(코어/게시판/이커머스)이 같은 extension_point 를 노출하므로 파일 1본으로 공유한다. ① 알림톡 템플릿: 승인 2단 배지 + 상태 액션(새로고침/신청 취소/승인 취소 후 수정/휴면 해제) + 작성 폼(draft/rejected) 또는 잠금 요약 ② 문자(SMS): 대체/단독 토글 + 로케일별 본문(검수 대상 아님). 저장은 notification_template_form_footer_actions 의 통합 [저장]이 담당한다. 상태는 _global.bz_tpl_modal / bz_sms_modal / bz_tpl_ui / bz_tpl_upload 에 담고 섹션 마운트(lifecycle.onMount) 시 요약 맵(bizppurioTemplates)으로 시딩한다. 코어 제목/본문 입력은 채널 메타 hidden_template_editor 로 코어 모달이 스스로 숨긴다.",
|
||||||
"priority": 320,
|
"priority": 320,
|
||||||
"components": [
|
"components": [
|
||||||
{
|
{
|
||||||
@@ -195,7 +195,7 @@
|
|||||||
{
|
{
|
||||||
"type": "basic",
|
"type": "basic",
|
||||||
"name": "Span",
|
"name": "Span",
|
||||||
"comment": "승인 여부 2단 배지(PO 결정 2026-08-23): 1차 = 승인됨/미승인, 2차(괄호) = 세부 상태(미작성·작성중·검수중·반려·휴면·중지·차단). approved 는 세부 없이 단독 표기.",
|
"comment": "승인 여부 2단 배지(제품 결정 2026-08-23): 1차 = 승인됨/미승인, 2차(괄호) = 세부 상태(미작성·작성중·검수중·반려·휴면·중지·차단). approved 는 세부 없이 단독 표기.",
|
||||||
"props": {
|
"props": {
|
||||||
"className": "{{'inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs font-medium flex-shrink-0 ' + ((((_global.bz_tpl_modal?.id) && (_global.bz_tpl_modal?.has_content)) ? (_global.bz_tpl_modal?.status ?? 'draft') : 'unwritten') === 'approved' ? 'bg-green-100 dark:bg-green-900 text-green-700 dark:text-green-200' : (((_global.bz_tpl_modal?.id) && (_global.bz_tpl_modal?.has_content)) ? (_global.bz_tpl_modal?.status ?? 'draft') : 'unwritten') === 'requested' ? 'bg-amber-100 dark:bg-amber-900 text-amber-700 dark:text-amber-200' : (((_global.bz_tpl_modal?.id) && (_global.bz_tpl_modal?.has_content)) ? (_global.bz_tpl_modal?.status ?? 'draft') : 'unwritten') === 'rejected' ? 'bg-red-100 dark:bg-red-800 text-red-700 dark:text-red-100' : ((((_global.bz_tpl_modal?.id) && (_global.bz_tpl_modal?.has_content)) ? (_global.bz_tpl_modal?.status ?? 'draft') : 'unwritten') === 'stopped' || (((_global.bz_tpl_modal?.id) && (_global.bz_tpl_modal?.has_content)) ? (_global.bz_tpl_modal?.status ?? 'draft') : 'unwritten') === 'blocked') ? 'border border-red-400 dark:border-red-500 text-red-600 dark:text-red-400' : (((_global.bz_tpl_modal?.id) && (_global.bz_tpl_modal?.has_content)) ? (_global.bz_tpl_modal?.status ?? 'draft') : 'unwritten') === 'dormant' ? 'bg-orange-100 dark:bg-orange-900 text-orange-700 dark:text-orange-200' : 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300')}}"
|
"className": "{{'inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs font-medium flex-shrink-0 ' + ((((_global.bz_tpl_modal?.id) && (_global.bz_tpl_modal?.has_content)) ? (_global.bz_tpl_modal?.status ?? 'draft') : 'unwritten') === 'approved' ? 'bg-green-100 dark:bg-green-900 text-green-700 dark:text-green-200' : (((_global.bz_tpl_modal?.id) && (_global.bz_tpl_modal?.has_content)) ? (_global.bz_tpl_modal?.status ?? 'draft') : 'unwritten') === 'requested' ? 'bg-amber-100 dark:bg-amber-900 text-amber-700 dark:text-amber-200' : (((_global.bz_tpl_modal?.id) && (_global.bz_tpl_modal?.has_content)) ? (_global.bz_tpl_modal?.status ?? 'draft') : 'unwritten') === 'rejected' ? 'bg-red-100 dark:bg-red-800 text-red-700 dark:text-red-100' : ((((_global.bz_tpl_modal?.id) && (_global.bz_tpl_modal?.has_content)) ? (_global.bz_tpl_modal?.status ?? 'draft') : 'unwritten') === 'stopped' || (((_global.bz_tpl_modal?.id) && (_global.bz_tpl_modal?.has_content)) ? (_global.bz_tpl_modal?.status ?? 'draft') : 'unwritten') === 'blocked') ? 'border border-red-400 dark:border-red-500 text-red-600 dark:text-red-400' : (((_global.bz_tpl_modal?.id) && (_global.bz_tpl_modal?.has_content)) ? (_global.bz_tpl_modal?.status ?? 'draft') : 'unwritten') === 'dormant' ? 'bg-orange-100 dark:bg-orange-900 text-orange-700 dark:text-orange-200' : 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300')}}"
|
||||||
},
|
},
|
||||||
@@ -2404,7 +2404,7 @@
|
|||||||
"id": "bizppurio_tpl_request_comment",
|
"id": "bizppurio_tpl_request_comment",
|
||||||
"type": "basic",
|
"type": "basic",
|
||||||
"name": "Div",
|
"name": "Div",
|
||||||
"comment": "검수자 전달 의견 — kapi template/request 의 comment(≤500). 카카오 심사 가이드가 요구하는 변수 예시값 등을 검수자에게 전할 유일한 통로(PO 결정 2026-08-23 §18.7). 신청 시에만 전송되며 행에 저장되지 않는다.",
|
"comment": "검수자 전달 의견 — kapi template/request 의 comment(≤500). 카카오 심사 가이드가 요구하는 변수 예시값 등을 검수자에게 전할 유일한 통로(제품 결정 2026-08-23 §18.7). 신청 시에만 전송되며 행에 저장되지 않는다.",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"type": "basic",
|
"type": "basic",
|
||||||
|
|||||||
+1
-1
@@ -221,7 +221,7 @@ describe('A-2 결과 컬럼 주입 — 렌더', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('검수 모드 발송 건은 상태 라벨(발송중) 대신 검수 라벨을 렌더한다', async () => {
|
it('검수 모드 발송 건은 상태 라벨(발송중) 대신 검수 라벨을 렌더한다', async () => {
|
||||||
// is_test_mode=true 이면 status='sent'(발송중)이어도 검수 라벨로 대체 표시한다(PO 확정 —
|
// is_test_mode=true 이면 status='sent'(발송중)이어도 검수 라벨로 대체 표시한다(제품 결정 —
|
||||||
// "발송중" 문구 자체가 검수 모드에서는 오해 소지라 배지 병기가 아니라 라벨 교체).
|
// "발송중" 문구 자체가 검수 모드에서는 오해 소지라 배지 병기가 아니라 라벨 교체).
|
||||||
const utils = createLayoutTest(buildProbe(), { componentRegistry: registry as any, locale: 'ko' });
|
const utils = createLayoutTest(buildProbe(), { componentRegistry: registry as any, locale: 'ko' });
|
||||||
utils.mockApi('notificationLogs', { response: logs([4]) });
|
utils.mockApi('notificationLogs', { response: logs([4]) });
|
||||||
|
|||||||
+2
-2
@@ -11,7 +11,7 @@
|
|||||||
* 반대로 데이터소스 id 는 치환 없이도 3면 동일해야 한다 — notification_row_footer.json 과
|
* 반대로 데이터소스 id 는 치환 없이도 3면 동일해야 한다 — notification_row_footer.json 과
|
||||||
* notification_template_form_sections.json(전역 매칭, 3면 공유 1본)이 이 이름들을 공유 참조하기 때문이다.
|
* notification_template_form_sections.json(전역 매칭, 3면 공유 1본)이 이 이름들을 공유 참조하기 때문이다.
|
||||||
* 편집 UI(작성 폼·SMS·저장)는 코어 [편집] 모달의 extension_point 에 주입되는 공유 1본이라
|
* 편집 UI(작성 폼·SMS·저장)는 코어 [편집] 모달의 extension_point 에 주입되는 공유 1본이라
|
||||||
* 면 패리티 대상이 아니다(PO 결정 2026-08-23).
|
* 면 패리티 대상이 아니다(제품 결정 2026-08-23).
|
||||||
*
|
*
|
||||||
* 세 오버레이가 전문 동일하다는 것이 board/ecommerce 면의 화면 효과를 떠받치는 근거다 —
|
* 세 오버레이가 전문 동일하다는 것이 board/ecommerce 면의 화면 효과를 떠받치는 근거다 —
|
||||||
* core 면에서 단언한 것들(탭 통합·행 하단 UI·업로드 잠금·SMS 언어 탭)이 두 면에도 있다는
|
* core 면에서 단언한 것들(탭 통합·행 하단 UI·업로드 잠금·SMS 언어 탭)이 두 면에도 있다는
|
||||||
@@ -70,7 +70,7 @@ const normalizedCore = JSON.stringify(stripComments(coreOverlay));
|
|||||||
/** 3면 공유 이름(치환 없이 동일해야 하는 축) */
|
/** 3면 공유 이름(치환 없이 동일해야 하는 축) */
|
||||||
const SHARED_DATA_SOURCE_IDS = ['bizppurioTemplates', 'bizppurioCategories', 'bizppurioProfiles'];
|
const SHARED_DATA_SOURCE_IDS = ['bizppurioTemplates', 'bizppurioCategories', 'bizppurioProfiles'];
|
||||||
// 모달·전역 상태(bz_*)는 오버레이가 아니라 3면 공유 1본(notification_template_form_sections.json /
|
// 모달·전역 상태(bz_*)는 오버레이가 아니라 3면 공유 1본(notification_template_form_sections.json /
|
||||||
// _footer_actions.json)이 소유한다(PO 결정 2026-08-23 — 편집 모달 통합). 오버레이는 모달을 등록하지 않는다.
|
// _footer_actions.json)이 소유한다(제품 결정 2026-08-23 — 편집 모달 통합). 오버레이는 모달을 등록하지 않는다.
|
||||||
|
|
||||||
describe.each(FIXTURES)('$label 오버레이 — 3면 패리티', ({ label, overlay, targetLayout, targetId, idPrefix }) => {
|
describe.each(FIXTURES)('$label 오버레이 — 3면 패리티', ({ label, overlay, targetLayout, targetId, idPrefix }) => {
|
||||||
it(`target_layout=${targetLayout} 이고 extension_point 키가 없다(overlay 전용)`, () => {
|
it(`target_layout=${targetLayout} 이고 extension_point 키가 없다(overlay 전용)`, () => {
|
||||||
|
|||||||
+4
-4
@@ -5,7 +5,7 @@
|
|||||||
// (§14.2 T7) — 리터럴 비교는 조건을 잘못 고쳐도 기대값을 함께 고치면 green 이라 회귀를
|
// (§14.2 T7) — 리터럴 비교는 조건을 잘못 고쳐도 기대값을 함께 고치면 green 이라 회귀를
|
||||||
// 잡지 못한다.
|
// 잡지 못한다.
|
||||||
/**
|
/**
|
||||||
* 알림 설정 '비즈뿌리오' 통합 탭 — [편집] 모달 통합 UI 구조 검증 (#597, PO 결정 2026-08-23)
|
* 알림 설정 '비즈뿌리오' 통합 탭 — [편집] 모달 통합 UI 구조 검증 (#597, 제품 결정 2026-08-23)
|
||||||
*
|
*
|
||||||
* @effects row_footer_shows_status_summary_only, approval_badge_two_tier, edit_modal_hosts_alimtalk_and_sms_sections,
|
* @effects row_footer_shows_status_summary_only, approval_badge_two_tier, edit_modal_hosts_alimtalk_and_sms_sections,
|
||||||
* unified_save_chain_alimtalk_then_core_recipients, compose_modal_switches_conditional_fields_by_type,
|
* unified_save_chain_alimtalk_then_core_recipients, compose_modal_switches_conditional_fields_by_type,
|
||||||
@@ -239,7 +239,7 @@ describe('lifecycle UI — 행 하단은 상태 요약만 (버튼 0)', () => {
|
|||||||
expect(raw).not.toContain('.slice(0, 40)');
|
expect(raw).not.toContain('.slice(0, 40)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('SMS 상태 3종은 문구가 아니라 배지다 — 사용=초록/미사용=회색(승인 배지와 같은 모양), 본문 미설정=외곽선 칩 (PO 지시 2026-08-23)', () => {
|
it('SMS 상태 3종은 문구가 아니라 배지다 — 사용=초록/미사용=회색(승인 배지와 같은 모양), 본문 미설정=외곽선 칩 (제품 결정 2026-08-23)', () => {
|
||||||
const APPROVED_SET = 'bg-green-100 dark:bg-green-900 text-green-700 dark:text-green-200';
|
const APPROVED_SET = 'bg-green-100 dark:bg-green-900 text-green-700 dark:text-green-200';
|
||||||
const GRAY_SET = 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300';
|
const GRAY_SET = 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300';
|
||||||
for (const [id, field] of [['bizppurio_row_sms_fallback_badge', 'fallback_sms_enabled'], ['bizppurio_row_sms_only_badge', 'sms_only']] as const) {
|
for (const [id, field] of [['bizppurio_row_sms_fallback_badge', 'fallback_sms_enabled'], ['bizppurio_row_sms_only_badge', 'sms_only']] as const) {
|
||||||
@@ -613,7 +613,7 @@ describe('lifecycle UI — 통합 [저장] 체인 (푸터 액션)', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('lifecycle UI — 검수자 전달 의견 입력란 (#597 §18.7, PO 결정 2026-08-23)', () => {
|
describe('lifecycle UI — 검수자 전달 의견 입력란 (#597 §18.7, 제품 결정 2026-08-23)', () => {
|
||||||
const editor = findById(sectionsRoot, 'bizppurio_tpl_editor') as AnyNode;
|
const editor = findById(sectionsRoot, 'bizppurio_tpl_editor') as AnyNode;
|
||||||
const block = findById(editor, 'bizppurio_tpl_request_comment') as AnyNode;
|
const block = findById(editor, 'bizppurio_tpl_request_comment') as AnyNode;
|
||||||
|
|
||||||
@@ -661,7 +661,7 @@ describe('lifecycle UI — 검수자 전달 의견 입력란 (#597 §18.7, PO
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
it('바로연결 블록(헤더+목록) 바로 뒤 형제로 놓이고, 라벨+[바로연결 추가] flex 행 안에 끼지 않는다 (회귀: PO 화면 지적 2026-08-23)', () => {
|
it('바로연결 블록(헤더+목록) 바로 뒤 형제로 놓이고, 라벨+[바로연결 추가] flex 행 안에 끼지 않는다 (회귀: 화면 검수 지적 2026-08-23)', () => {
|
||||||
const chain = ancestorsOf(editor, 'bizppurio_tpl_request_comment') as AnyNode[];
|
const chain = ancestorsOf(editor, 'bizppurio_tpl_request_comment') as AnyNode[];
|
||||||
expect(chain).toBeTruthy();
|
expect(chain).toBeTruthy();
|
||||||
const parent = chain[chain.length - 1];
|
const parent = chain[chain.length - 1];
|
||||||
|
|||||||
+5
-5
@@ -159,7 +159,7 @@ describe('manage — 행 액션(알림 설정 탭 행 하단과 동일 엔드포
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 관리 화면(bzRow)과 코어 [편집] 모달 섹션(_global.bz_tpl_modal)의 노출 조건을 같은 상태
|
* 관리 화면(bzRow)과 코어 [편집] 모달 섹션(_global.bz_tpl_modal)의 노출 조건을 같은 상태
|
||||||
* 집합에 **실제로 태워** 대조한다(PO 결정 2026-08-23 — 행 하단 버튼 폐지, 섹션이 SSoT).
|
* 집합에 **실제로 태워** 대조한다(제품 결정 2026-08-23 — 행 하단 버튼 폐지, 섹션이 SSoT).
|
||||||
*
|
*
|
||||||
* 문자열 동일성 단언은 두 면의 식이 실제로 같은 결과를 내는지 증명하지 못한다 — 두 식을
|
* 문자열 동일성 단언은 두 면의 식이 실제로 같은 결과를 내는지 증명하지 못한다 — 두 식을
|
||||||
* 각자의 컨텍스트로 평가해 상태별 결과가 일치하는지를 본다.
|
* 각자의 컨텍스트로 평가해 상태별 결과가 일치하는지를 본다.
|
||||||
@@ -375,7 +375,7 @@ describe('manage 모달 — 이미지 업로드 배선·SMS 언어 탭 (#597 §1
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('manage 모달 — 검수자 전달 의견 (#597 §18.7, PO 결정 2026-08-23)', () => {
|
describe('manage 모달 — 검수자 전달 의견 (#597 §18.7, 제품 결정 2026-08-23)', () => {
|
||||||
const composeModal = findById(modalRoot, 'modal_bizppurio_template') as AnyNode;
|
const composeModal = findById(modalRoot, 'modal_bizppurio_template') as AnyNode;
|
||||||
const sectionsRoot = { children: (sections as { components?: AnyNode[] }).components ?? [] } as AnyNode;
|
const sectionsRoot = { children: (sections as { components?: AnyNode[] }).components ?? [] } as AnyNode;
|
||||||
const collectHandlers = (node: unknown, acc: AnyNode[] = []): AnyNode[] => {
|
const collectHandlers = (node: unknown, acc: AnyNode[] = []): AnyNode[] => {
|
||||||
@@ -411,7 +411,7 @@ describe('manage 모달 — 검수자 전달 의견 (#597 §18.7, PO 결정 2026
|
|||||||
for (const r of rowReqs) expect((r.params as { body?: unknown }).body).toBeUndefined();
|
for (const r of rowReqs) expect((r.params as { body?: unknown }).body).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('바로연결 블록(헤더+목록) 바로 뒤 형제로 놓이고, 라벨+[바로연결 추가] flex 행 안에 끼지 않는다 (회귀: PO 화면 지적 2026-08-23)', () => {
|
it('바로연결 블록(헤더+목록) 바로 뒤 형제로 놓이고, 라벨+[바로연결 추가] flex 행 안에 끼지 않는다 (회귀: 화면 검수 지적 2026-08-23)', () => {
|
||||||
const ancestorsOf = (root: AnyNode, id: string, anc: AnyNode[] = []): AnyNode[] | null => {
|
const ancestorsOf = (root: AnyNode, id: string, anc: AnyNode[] = []): AnyNode[] | null => {
|
||||||
for (const c of (root.children as AnyNode[] | undefined) ?? []) {
|
for (const c of (root.children as AnyNode[] | undefined) ?? []) {
|
||||||
if (c.id === id) return anc.concat(root);
|
if (c.id === id) return anc.concat(root);
|
||||||
@@ -452,7 +452,7 @@ describe('manage 모달 — 검수자 전달 의견 (#597 §18.7, PO 결정 2026
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('manage — 목록 SMS 열은 상태 배지 (행 하단과 같은 규칙, PO 지시 2026-08-23)', () => {
|
describe('manage — 목록 SMS 열은 상태 배지 (행 하단과 같은 규칙, 제품 결정 2026-08-23)', () => {
|
||||||
// iteration(bzRow) 안이라 정적 id 를 둘 수 없다 — 텍스트 식으로 찾는다
|
// iteration(bzRow) 안이라 정적 id 를 둘 수 없다 — 텍스트 식으로 찾는다
|
||||||
const badge = findAllByName(manageView, 'Span').find((n) => String(n.text).includes("manage.sms_fallback') : $t('sirsoft-message_bizppurio.template.row.off')")) as AnyNode;
|
const badge = findAllByName(manageView, 'Span').find((n) => String(n.text).includes("manage.sms_fallback') : $t('sirsoft-message_bizppurio.template.row.off')")) as AnyNode;
|
||||||
const evalCell = (expr: string, row: Record<string, unknown>): unknown => {
|
const evalCell = (expr: string, row: Record<string, unknown>): unknown => {
|
||||||
@@ -475,7 +475,7 @@ describe('manage — 목록 SMS 열은 상태 배지 (행 하단과 같은 규
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('manage — 목록 모바일 카드 전환 + 도구줄 버튼 일관성 (PO 지시 2026-08-24)', () => {
|
describe('manage — 목록 모바일 카드 전환 + 도구줄 버튼 일관성 (제품 결정 2026-08-24)', () => {
|
||||||
const header = findById(manageView, 'bz_manage_list_header') as AnyNode;
|
const header = findById(manageView, 'bz_manage_list_header') as AnyNode;
|
||||||
const rowsWrap = findById(manageView, 'bz_manage_list_rows') as AnyNode;
|
const rowsWrap = findById(manageView, 'bz_manage_list_rows') as AnyNode;
|
||||||
const findIterationRow = (n: AnyNode | null): AnyNode | null => {
|
const findIterationRow = (n: AnyNode | null): AnyNode | null => {
|
||||||
|
|||||||
+1
-1
@@ -36,7 +36,7 @@ import { describe, it, expect } from 'vitest';
|
|||||||
const BASE = path.resolve(__dirname, '../../../..');
|
const BASE = path.resolve(__dirname, '../../../..');
|
||||||
|
|
||||||
const FILES = [
|
const FILES = [
|
||||||
// 3면 공유 1본 — 코어 [편집] 모달 푸터에 주입되는 통합 저장/검수 신청 버튼(PO 결정 2026-08-23)
|
// 3면 공유 1본 — 코어 [편집] 모달 푸터에 주입되는 통합 저장/검수 신청 버튼(제품 결정 2026-08-23)
|
||||||
'resources/extensions/notification_template_form_footer_actions.json',
|
'resources/extensions/notification_template_form_footer_actions.json',
|
||||||
// 플러그인 관리 화면의 자기 모달
|
// 플러그인 관리 화면의 자기 모달
|
||||||
'resources/layouts/admin/plugin_settings.json',
|
'resources/layouts/admin/plugin_settings.json',
|
||||||
|
|||||||
+5
-5
@@ -8,7 +8,7 @@
|
|||||||
"meta": {
|
"meta": {
|
||||||
"title": "$t:sirsoft-message_bizppurio.settings.title",
|
"title": "$t:sirsoft-message_bizppurio.settings.title",
|
||||||
"description": "$t:sirsoft-message_bizppurio.settings.description",
|
"description": "$t:sirsoft-message_bizppurio.settings.description",
|
||||||
"_e2e_allow": "e2e:allow (§529) 연결 확인 필드·hasChanges 가드 추가는 레이아웃 회귀테스트(plugin_settings.test.tsx) + PHPUnit Feature(TokenCheckEndpointTest·InvalidateTokenOnSettingsSaveListenerTest)로 커버. 실연동 Playwright는 계획서 §9 방침에 따라 PO 직접 수행(인증·발송 환경 필요) 단계에서 도입 예정 — tests/scenarios/plugin-settings.yaml 상단 audit:allow 사유 참고."
|
"_e2e_allow": "e2e:allow (§529) 연결 확인 필드·hasChanges 가드 추가는 레이아웃 회귀테스트(plugin_settings.test.tsx) + PHPUnit Feature(TokenCheckEndpointTest·InvalidateTokenOnSettingsSaveListenerTest)로 커버. 실연동 Playwright는 계획서 §9 방침에 따라 직접 수행(인증·발송 환경 필요) 단계에서 도입 예정 — tests/scenarios/plugin-settings.yaml 상단 audit:allow 사유 참고."
|
||||||
},
|
},
|
||||||
"init_actions": [
|
"init_actions": [
|
||||||
{
|
{
|
||||||
@@ -1771,7 +1771,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"comment": "새로고침 — 코어 관리자 목록 관례(btn-icon + 회전 아이콘)와 통일 (PO 지시 2026-08-24).",
|
"comment": "새로고침 — 코어 관리자 목록 관례(btn-icon + 회전 아이콘)와 통일 (제품 결정 2026-08-24).",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"type": "basic",
|
"type": "basic",
|
||||||
@@ -1804,7 +1804,7 @@
|
|||||||
"id": "bz_manage_list_header",
|
"id": "bz_manage_list_header",
|
||||||
"type": "basic",
|
"type": "basic",
|
||||||
"name": "Div",
|
"name": "Div",
|
||||||
"comment": "데스크톱 grid 헤더 — portable 에서는 카드가 자기 서술이므로 숨긴다 (PO 지시 2026-08-24 모바일 카드뷰).",
|
"comment": "데스크톱 grid 헤더 — portable 에서는 카드가 자기 서술이므로 숨긴다 (제품 결정 2026-08-24 모바일 카드뷰).",
|
||||||
"props": {
|
"props": {
|
||||||
"className": "grid grid-cols-12 gap-2 px-4 py-2.5 bg-gray-50 dark:bg-gray-900 text-xs font-medium text-gray-500 dark:text-gray-400"
|
"className": "grid grid-cols-12 gap-2 px-4 py-2.5 bg-gray-50 dark:bg-gray-900 text-xs font-medium text-gray-500 dark:text-gray-400"
|
||||||
},
|
},
|
||||||
@@ -1994,7 +1994,7 @@
|
|||||||
"props": {
|
"props": {
|
||||||
"className": "col-span-1"
|
"className": "col-span-1"
|
||||||
},
|
},
|
||||||
"comment": "SMS 발송 모드 배지 — 단독/대체(초록), 미사용(회색). 행 하단 상태 배지와 같은 규칙(PO 지시 2026-08-23).",
|
"comment": "SMS 발송 모드 배지 — 단독/대체(초록), 미사용(회색). 행 하단 상태 배지와 같은 규칙(제품 결정 2026-08-23).",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"type": "basic",
|
"type": "basic",
|
||||||
@@ -4238,7 +4238,7 @@
|
|||||||
"id": "bz_manage_request_comment",
|
"id": "bz_manage_request_comment",
|
||||||
"type": "basic",
|
"type": "basic",
|
||||||
"name": "Div",
|
"name": "Div",
|
||||||
"comment": "검수자 전달 의견 — kapi template/request 의 comment(≤500). 카카오 심사 가이드가 요구하는 변수 예시값 등을 검수자에게 전할 유일한 통로(PO 결정 2026-08-23 §18.7). 신청 시에만 전송되며 행에 저장되지 않는다.",
|
"comment": "검수자 전달 의견 — kapi template/request 의 comment(≤500). 카카오 심사 가이드가 요구하는 변수 예시값 등을 검수자에게 전할 유일한 통로(제품 결정 2026-08-23 §18.7). 신청 시에만 전송되며 행에 저장되지 않는다.",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"type": "basic",
|
"type": "basic",
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@ namespace Plugins\Sirsoft\MessageBizppurio\Http\Requests;
|
|||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 알림톡 템플릿 검수 신청 요청 검증 (#597 §18.7 — PO 결정 2026-08-23).
|
* 알림톡 템플릿 검수 신청 요청 검증 (#597 §18.7 — 제품 결정 2026-08-23).
|
||||||
*
|
*
|
||||||
* 카카오 심사 가이드는 템플릿 변수마다 '예시 텍스트' 를 요구하지만 kapi `template/add` 에는
|
* 카카오 심사 가이드는 템플릿 변수마다 '예시 텍스트' 를 요구하지만 kapi `template/add` 에는
|
||||||
* 예시 필드가 없다. 검수자에게 무언가를 전달할 유일한 통로가 `template/request` 의
|
* 예시 필드가 없다. 검수자에게 무언가를 전달할 유일한 통로가 `template/request` 의
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ use Plugins\Sirsoft\MessageBizppurio\Services\DispatchLinkContext;
|
|||||||
* - core.notification_log.after_log_sent — 발송 성공 로그 생성 직후(NotificationLog 전달)
|
* - core.notification_log.after_log_sent — 발송 성공 로그 생성 직후(NotificationLog 전달)
|
||||||
* - core.notification_log.after_log_failed — 발송 실패 로그 생성 직후(NotificationLog 전달)
|
* - core.notification_log.after_log_failed — 발송 실패 로그 생성 직후(NotificationLog 전달)
|
||||||
*
|
*
|
||||||
* 매칭 방식(A안, PO 확정): 복합키 근사 매칭이 아니라 발송 사이클 refkey 직접 표식이다.
|
* 매칭 방식(A안, 제품 결정): 복합키 근사 매칭이 아니라 발송 사이클 refkey 직접 표식이다.
|
||||||
* 같은 채널 발송 한 사이클에서 우리 드라이버 send() 가 dispatch(refkey) 를 먼저 만들고
|
* 같은 채널 발송 한 사이클에서 우리 드라이버 send() 가 dispatch(refkey) 를 먼저 만들고
|
||||||
* DispatchLinkContext 에 refkey 를 남긴 뒤, 곧바로 이 로그 훅이 발화한다. 여기서 그 refkey 를
|
* DispatchLinkContext 에 refkey 를 남긴 뒤, 곧바로 이 로그 훅이 발화한다. 여기서 그 refkey 를
|
||||||
* 꺼내(consume) 그 dispatch 에 방금 만들어진 코어 로그 id 를 기록한다.
|
* 꺼내(consume) 그 dispatch 에 방금 만들어진 코어 로그 id 를 기록한다.
|
||||||
|
|||||||
+1
-1
@@ -271,7 +271,7 @@ class RegisterNotificationChannelsListener implements HookListenerInterface
|
|||||||
* - alimtalk.tab_channels: 이 목록 중 하나라도 활성 저장이면 탭을 노출한다.
|
* - alimtalk.tab_channels: 이 목록 중 하나라도 활성 저장이면 탭을 노출한다.
|
||||||
* - alimtalk.tab_label_key: 탭 라벨용 프론트 lang 키($t 해석 — 카드 라벨(name)과 분리).
|
* - alimtalk.tab_label_key: 탭 라벨용 프론트 lang 키($t 해석 — 카드 라벨(name)과 분리).
|
||||||
* - alimtalk.hidden_template_editor: 코어 알림 템플릿 [편집] 모달의 제목/본문 입력·미리보기·
|
* - alimtalk.hidden_template_editor: 코어 알림 템플릿 [편집] 모달의 제목/본문 입력·미리보기·
|
||||||
* 코어 [저장]을 숨긴다(PO 결정 2026-08-23). 알림톡 본문은 카카오 규격(#{var}, 유형별 필드)이라
|
* 코어 [저장]을 숨긴다(제품 결정 2026-08-23). 알림톡 본문은 카카오 규격(#{var}, 유형별 필드)이라
|
||||||
* 코어 본문과 다른 편집기가 필요하고, 그 편집기·통합 저장은 플러그인이 같은 모달의
|
* 코어 본문과 다른 편집기가 필요하고, 그 편집기·통합 저장은 플러그인이 같은 모달의
|
||||||
* extension_point(notification_template_form_sections / _footer_actions)에 주입한다.
|
* extension_point(notification_template_form_sections / _footer_actions)에 주입한다.
|
||||||
* 코어 채널 템플릿 행(제목/본문)은 발송에 쓰이지 않으므로 숨겨도 동작 손실이 없다.
|
* 코어 채널 템플릿 행(제목/본문)은 발송에 쓰이지 않으므로 숨겨도 동작 손실이 없다.
|
||||||
|
|||||||
+1
-1
@@ -194,7 +194,7 @@ class BizppurioTemplateService
|
|||||||
* add 성공 시점에만 template_code 를 행에 확정하므로, add 자체가 실패하면 다음
|
* add 성공 시점에만 template_code 를 행에 확정하므로, add 자체가 실패하면 다음
|
||||||
* 시도에서 다시 채번부터 진행된다.
|
* 시도에서 다시 채번부터 진행된다.
|
||||||
* - 검수자 전달 의견(comment)은 kapi request 에만 싣고 행에 저장하지 않는다 — 카카오 심사
|
* - 검수자 전달 의견(comment)은 kapi request 에만 싣고 행에 저장하지 않는다 — 카카오 심사
|
||||||
* 가이드가 요구하는 변수 '예시 텍스트' 를 전할 유일한 통로다(PO 결정 2026-08-23, §18.7).
|
* 가이드가 요구하는 변수 '예시 텍스트' 를 전할 유일한 통로다(제품 결정 2026-08-23, §18.7).
|
||||||
*
|
*
|
||||||
* @param BizppurioTemplate $template 대상 행
|
* @param BizppurioTemplate $template 대상 행
|
||||||
* @param string|null $comment 검수자 전달 의견 (≤500, 비어 있으면 미전달)
|
* @param string|null $comment 검수자 전달 의견 (≤500, 비어 있으면 미전달)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ use Plugins\Sirsoft\MessageBizppurio\Exceptions\BizppurioApiException;
|
|||||||
*
|
*
|
||||||
* `/v1/token` 을 Basic 인증(계정:암호 Base64)으로 호출해 Bearer 토큰을 발급받고,
|
* `/v1/token` 을 Basic 인증(계정:암호 Base64)으로 호출해 Bearer 토큰을 발급받고,
|
||||||
* 확장 도메인 캐시(CacheInterface)에 저장한다. 토큰 유효 시간은 24시간이나, 만료
|
* 확장 도메인 캐시(CacheInterface)에 저장한다. 토큰 유효 시간은 24시간이나, 만료
|
||||||
* 경계 재발급 리스크를 피하기 위해 23시간 TTL 로 캐시한다(PO 결정, 계획서 §5).
|
* 경계 재발급 리스크를 피하기 위해 23시간 TTL 로 캐시한다(제품 결정, 계획서 §5).
|
||||||
*
|
*
|
||||||
* 발송 응답이 3002(토큰무효)/3005(인증정보무효)를 반환하면 캐시를 forget 하고
|
* 발송 응답이 3002(토큰무효)/3005(인증정보무효)를 반환하면 캐시를 forget 하고
|
||||||
* 1회 재발급한다(BizppurioApiClient 가 재시도 트리거). CacheInterface 는
|
* 1회 재발급한다(BizppurioApiClient 가 재시도 트리거). CacheInterface 는
|
||||||
|
|||||||
+1
-1
@@ -610,7 +610,7 @@ class BizppurioTemplateControllerTest extends PluginTestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 검수자 전달 의견(comment)은 선택 입력이며 kapi request 로만 전달된다 (#597 §18.7 — PO 결정 2026-08-23).
|
* 검수자 전달 의견(comment)은 선택 입력이며 kapi request 로만 전달된다 (#597 §18.7 — 제품 결정 2026-08-23).
|
||||||
*
|
*
|
||||||
* 500자 초과는 FormRequest 가 kapi 호출 전에 422 로 끊고(행 상태 불변), 유효한 의견은
|
* 500자 초과는 FormRequest 가 kapi 호출 전에 422 로 끊고(행 상태 불변), 유효한 의견은
|
||||||
* `template/request` 의 comment 로 원문 그대로 실린다.
|
* `template/request` 의 comment 로 원문 그대로 실린다.
|
||||||
|
|||||||
+2
-2
@@ -11,7 +11,7 @@
|
|||||||
* sms_body_presence_and_preview_resolved_by_server, inspection_request_carries_reviewer_comment
|
* sms_body_presence_and_preview_resolved_by_server, inspection_request_carries_reviewer_comment
|
||||||
*
|
*
|
||||||
* 계획서 §6.3 이 요구한 7대 축(T1~T7) + 선택 축(T8~T10) + 회귀 축(R1~R6)을 브라우저에서 실측한다.
|
* 계획서 §6.3 이 요구한 7대 축(T1~T7) + 선택 축(T8~T10) + 회귀 축(R1~R6)을 브라우저에서 실측한다.
|
||||||
* PO 결정(2026-08-23, 계획서 §18)으로 알림톡 작성·SMS 본문 편집은 행 하단 버튼/별도 모달이 아니라
|
* 제품 결정(2026-08-23, 계획서 §18)으로 알림톡 작성·SMS 본문 편집은 행 하단 버튼/별도 모달이 아니라
|
||||||
* 코어 [편집] 모달 안의 섹션으로 통합됐다 — 모달 진입은 언제나 행의 [편집] 이고, 저장은 하단 [저장] 하나다.
|
* 코어 [편집] 모달 안의 섹션으로 통합됐다 — 모달 진입은 언제나 행의 [편집] 이고, 저장은 하단 [저장] 하나다.
|
||||||
* 이 매트릭스는 라운드 1~4 동안 "수행 증거 없음" 으로 남아 있었고, 그 근본 원인은 플러그인
|
* 이 매트릭스는 라운드 1~4 동안 "수행 증거 없음" 으로 남아 있었고, 그 근본 원인은 플러그인
|
||||||
* package.json 에 실행 진입점(test:e2e)이 없었다는 것이다 — 라운드 5 에서 진입점을 만들고
|
* package.json 에 실행 진입점(test:e2e)이 없었다는 것이다 — 라운드 5 에서 진입점을 만들고
|
||||||
@@ -479,7 +479,7 @@ test.describe('T4 제출/응답 + T10 경계', () => {
|
|||||||
// 서버의 원자 선점(claimForInspection)이며, 두 번째 신청은 422 로 거부된다.
|
// 서버의 원자 선점(claimForInspection)이며, 두 번째 신청은 422 로 거부된다.
|
||||||
const modal2 = await openEditModal(page, 'password_changed');
|
const modal2 = await openEditModal(page, 'password_changed');
|
||||||
await modal2.locator('textarea[name="bz_template_content"]').fill('중복 신청 테스트 #{site_name}');
|
await modal2.locator('textarea[name="bz_template_content"]').fill('중복 신청 테스트 #{site_name}');
|
||||||
// 검수자 전달 의견(PO 결정 2026-08-23 §18.7) — 신청 요청 본문의 comment 로 실려야 한다.
|
// 검수자 전달 의견(제품 결정 2026-08-23 §18.7) — 신청 요청 본문의 comment 로 실려야 한다.
|
||||||
const REVIEW_COMMENT = '변수 예시: #{site_name}=G7 데모 사이트';
|
const REVIEW_COMMENT = '변수 예시: #{site_name}=G7 데모 사이트';
|
||||||
await modal2.locator('textarea[name="bz_request_comment"]').fill(REVIEW_COMMENT);
|
await modal2.locator('textarea[name="bz_request_comment"]').fill(REVIEW_COMMENT);
|
||||||
const requestBodies: string[] = [];
|
const requestBodies: string[] = [];
|
||||||
|
|||||||
+4
-4
@@ -14,7 +14,7 @@
|
|||||||
* 4. 플러그인 관리 화면 — 상태 필터가 URL(bz_status)에 보존되는 목록 왕복(mergeQuery)
|
* 4. 플러그인 관리 화면 — 상태 필터가 URL(bz_status)에 보존되는 목록 왕복(mergeQuery)
|
||||||
*
|
*
|
||||||
* 카카오 API(kapi) 실호출이 필요한 검수 신청·동기화 경로는 브라우저 E2E 범위 밖이다
|
* 카카오 API(kapi) 실호출이 필요한 검수 신청·동기화 경로는 브라우저 E2E 범위 밖이다
|
||||||
* (자격증명·실검수 필요 — PHPUnit 이 Http::fake 로 전수 가드, 실연동은 PO 수행 단계).
|
* (자격증명·실검수 필요 — PHPUnit 이 Http::fake 로 전수 가드, 실연동은 별도 수행 단계).
|
||||||
*
|
*
|
||||||
* 계획서 §6.2 의 "작성→신청→(kapi mock 승인)→발송 배지" 왕복 축을 여기에 두지 않은 이유는
|
* 계획서 §6.2 의 "작성→신청→(kapi mock 승인)→발송 배지" 왕복 축을 여기에 두지 않은 이유는
|
||||||
* 구조적이다: kapi 호출은 서버(PHP)에서 서버로 나가고, Playwright 의 route 가로채기는
|
* 구조적이다: kapi 호출은 서버(PHP)에서 서버로 나가고, Playwright 의 route 가로채기는
|
||||||
@@ -82,7 +82,7 @@ test.describe('비즈뿌리오 통합 탭 (코어 알림 설정)', () => {
|
|||||||
await expect(firstRow.getByText(/승인됨|미승인/).first()).toBeVisible();
|
await expect(firstRow.getByText(/승인됨|미승인/).first()).toBeVisible();
|
||||||
await expect(firstRow.getByText('대체 SMS', { exact: false }).first()).toBeVisible();
|
await expect(firstRow.getByText('대체 SMS', { exact: false }).first()).toBeVisible();
|
||||||
await expect(firstRow.getByText('SMS 단독', { exact: false }).first()).toBeVisible();
|
await expect(firstRow.getByText('SMS 단독', { exact: false }).first()).toBeVisible();
|
||||||
// SMS 사용 여부는 문구("대체 SMS: 미사용")가 아니라 배지(사용/미사용)로 렌더된다 (PO 지시 2026-08-23)
|
// SMS 사용 여부는 문구("대체 SMS: 미사용")가 아니라 배지(사용/미사용)로 렌더된다 (제품 결정 2026-08-23)
|
||||||
expect(await firstRow.locator('span.rounded', { hasText: /^(사용|미사용)$/ }).count()).toBeGreaterThanOrEqual(2);
|
expect(await firstRow.locator('span.rounded', { hasText: /^(사용|미사용)$/ }).count()).toBeGreaterThanOrEqual(2);
|
||||||
expect(await firstRow.getByText(/대체 SMS:|SMS 단독:/).count()).toBe(0);
|
expect(await firstRow.getByText(/대체 SMS:|SMS 단독:/).count()).toBe(0);
|
||||||
expect(await rows.locator('button').count()).toBe(0);
|
expect(await rows.locator('button').count()).toBe(0);
|
||||||
@@ -117,7 +117,7 @@ test.describe('비즈뿌리오 통합 탭 (코어 알림 설정)', () => {
|
|||||||
await expect(modal.locator('textarea[name="bz_template_content"]')).toBeVisible();
|
await expect(modal.locator('textarea[name="bz_template_content"]')).toBeVisible();
|
||||||
|
|
||||||
// 검수자 전달 의견 입력란은 바로연결 블록 아래 한 줄을 통째로 차지한다
|
// 검수자 전달 의견 입력란은 바로연결 블록 아래 한 줄을 통째로 차지한다
|
||||||
// (회귀: 라벨+[바로연결 추가] flex 행 안에 끼어 라벨이 세로로 찌그러짐 — PO 화면 지적 2026-08-23)
|
// (회귀: 라벨+[바로연결 추가] flex 행 안에 끼어 라벨이 세로로 찌그러짐 — 화면 검수 지적 2026-08-23)
|
||||||
const commentBox = modal.locator('textarea[name="bz_request_comment"]');
|
const commentBox = modal.locator('textarea[name="bz_request_comment"]');
|
||||||
await expect(commentBox).toBeVisible();
|
await expect(commentBox).toBeVisible();
|
||||||
const [quickAddBox, commentBounds, bodyBox] = await Promise.all([
|
const [quickAddBox, commentBounds, bodyBox] = await Promise.all([
|
||||||
@@ -170,7 +170,7 @@ test.describe('비즈뿌리오 알림 템플릿 관리 (플러그인 설정)', (
|
|||||||
|
|
||||||
await expect(manageView).toBeVisible({ timeout: 30_000 });
|
await expect(manageView).toBeVisible({ timeout: 30_000 });
|
||||||
|
|
||||||
// 목록 SMS 열은 평문(단독/대체/-)이 아니라 상태 배지(단독·대체=초록, 미사용=회색) — 행 하단과 같은 규칙 (PO 지시 2026-08-23)
|
// 목록 SMS 열은 평문(단독/대체/-)이 아니라 상태 배지(단독·대체=초록, 미사용=회색) — 행 하단과 같은 규칙 (제품 결정 2026-08-23)
|
||||||
await expect(manageView.locator('span.rounded', { hasText: /^(단독|대체|미사용)$/ }).first()).toBeVisible({ timeout: 15_000 });
|
await expect(manageView.locator('span.rounded', { hasText: /^(단독|대체|미사용)$/ }).first()).toBeVisible({ timeout: 15_000 });
|
||||||
|
|
||||||
// 상태 필터 변경 → URL bz_status 반영 (mergeQuery — tab 파라미터 유지)
|
// 상태 필터 변경 → URL bz_status 반영 (mergeQuery — tab 파라미터 유지)
|
||||||
|
|||||||
+1
-1
@@ -735,7 +735,7 @@ class BizppurioTemplateServiceTest extends PluginTestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 검수자 전달 의견은 kapi request 의 comment 로만 실린다 (#597 §18.7 — PO 결정 2026-08-23).
|
* 검수자 전달 의견은 kapi request 의 comment 로만 실린다 (#597 §18.7 — 제품 결정 2026-08-23).
|
||||||
*
|
*
|
||||||
* 카카오 심사 가이드가 요구하는 변수 '예시 텍스트' 를 전할 유일한 통로가 request comment 다.
|
* 카카오 심사 가이드가 요구하는 변수 '예시 텍스트' 를 전할 유일한 통로가 request comment 다.
|
||||||
* 등록(add) 페이로드에는 섞이지 않고, 행에도 남지 않는다.
|
* 등록(add) 페이로드에는 섞이지 않고, 행에도 남지 않는다.
|
||||||
|
|||||||
+3
-3
@@ -16,7 +16,7 @@ description: |
|
|||||||
승인 전이 시 content 를 approved_content 로 동결(발송 SSoT), 반려 시 comments 저장
|
승인 전이 시 content 를 approved_content 로 동결(발송 SSoT), 반려 시 comments 저장
|
||||||
- 화면: 3면(코어/게시판/이커머스) '비즈뿌리오' 통합 탭(sms 탭 숨김 + tab_channels 규칙)
|
- 화면: 3면(코어/게시판/이커머스) '비즈뿌리오' 통합 탭(sms 탭 숨김 + tab_channels 규칙)
|
||||||
행 하단 상태 요약(승인 2단 배지) + 코어 [편집] 모달에 녹인 알림톡·SMS 섹션(통합 저장,
|
행 하단 상태 요약(승인 2단 배지) + 코어 [편집] 모달에 녹인 알림톡·SMS 섹션(통합 저장,
|
||||||
4×4 유형) + 플러그인 관리 화면(DB 목록). PO 결정 2026-08-23: 별도 작성/SMS 모달 폐지
|
4×4 유형) + 플러그인 관리 화면(DB 목록). 제품 결정 2026-08-23: 별도 작성/SMS 모달 폐지
|
||||||
|
|
||||||
axis 설계 노트:
|
axis 설계 노트:
|
||||||
- content_variant 는 카카오 메시지유형×강조유형의 대표 변형 4종이다 — 유형별 조건부
|
- content_variant 는 카카오 메시지유형×강조유형의 대표 변형 4종이다 — 유형별 조건부
|
||||||
@@ -75,7 +75,7 @@ effects:
|
|||||||
- approval_transition_freezes_content_into_approved_content
|
- approval_transition_freezes_content_into_approved_content
|
||||||
- rejection_transition_stores_comments_detail
|
- rejection_transition_stores_comments_detail
|
||||||
- manual_sync_updates_single_row
|
- manual_sync_updates_single_row
|
||||||
# 화면 (S5 — PO 결정 2026-08-23: 편집 모달 통합)
|
# 화면 (S5 — 제품 결정 2026-08-23: 편집 모달 통합)
|
||||||
- bizppurio_tab_replaces_sms_and_alimtalk_tabs
|
- bizppurio_tab_replaces_sms_and_alimtalk_tabs
|
||||||
- tab_visible_when_any_of_tab_channels_active
|
- tab_visible_when_any_of_tab_channels_active
|
||||||
- row_footer_shows_status_summary_only
|
- row_footer_shows_status_summary_only
|
||||||
@@ -85,7 +85,7 @@ effects:
|
|||||||
- unified_save_chain_alimtalk_then_core_recipients
|
- unified_save_chain_alimtalk_then_core_recipients
|
||||||
- compose_modal_switches_conditional_fields_by_type
|
- compose_modal_switches_conditional_fields_by_type
|
||||||
- manage_screen_lists_db_rows_with_merge_query_round_trip
|
- manage_screen_lists_db_rows_with_merge_query_round_trip
|
||||||
# 관리 목록 반응형 (PO 지시 2026-08-24) — portable 카드 전환 + 도구줄 btn 계열 통일
|
# 관리 목록 반응형 (제품 결정 2026-08-24) — portable 카드 전환 + 도구줄 btn 계열 통일
|
||||||
- manage_list_mobile_card_view_and_unified_toolbar
|
- manage_list_mobile_card_view_and_unified_toolbar
|
||||||
- sms_modal_saves_body_via_delivery_upsert
|
- sms_modal_saves_body_via_delivery_upsert
|
||||||
- sms_modal_edits_body_per_locale_tab
|
- sms_modal_edits_body_per_locale_tab
|
||||||
|
|||||||
+1
-1
@@ -9,7 +9,7 @@
|
|||||||
# - 결과 조회 API(권한·검증·성공/실패/잔액부족/미매칭): DispatchResultEndpointTest.
|
# - 결과 조회 API(권한·검증·성공/실패/잔액부족/미매칭): DispatchResultEndpointTest.
|
||||||
# - overlay 결과 컬럼 실제 렌더(성공/잔액부족/대체발송/빈셀 조건부 렌더): notification_log_result.test.tsx.
|
# - overlay 결과 컬럼 실제 렌더(성공/잔액부족/대체발송/빈셀 조건부 렌더): notification_log_result.test.tsx.
|
||||||
# e2e_* 축(브라우저 왕복: 코어 이력 화면 진입→결과 컬럼 확인→회원 링크/배지)은 실제 발송·webhook
|
# e2e_* 축(브라우저 왕복: 코어 이력 화면 진입→결과 컬럼 확인→회원 링크/배지)은 실제 발송·webhook
|
||||||
# 왕복 결과가 필요해, 계획서 §9 방침대로 PO 직접 수행하는 실연동 검증 단계에서 Playwright spec 을
|
# 왕복 결과가 필요해, 계획서 §9 방침대로 직접 수행하는 실연동 검증 단계에서 Playwright spec 을
|
||||||
# 그때 @scenario/@effects 로 이 매니페스트에 매핑한다. Vitest 렌더 테스트가 프론트 overlay 컬럼
|
# 그때 @scenario/@effects 로 이 매니페스트에 매핑한다. Vitest 렌더 테스트가 프론트 overlay 컬럼
|
||||||
# 주입·조건부 렌더를 가드하므로 이번 단계는 spec 미도입
|
# 주입·조건부 렌더를 가드하므로 이번 단계는 spec 미도입
|
||||||
# (frontend-change-requires-e2e 는 이 매니페스트의 e2e axis + Vitest 렌더 커버로 충족).
|
# (frontend-change-requires-e2e 는 이 매니페스트의 e2e axis + Vitest 렌더 커버로 충족).
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
# TokenCheckEndpointTest, 저장 시 토큰 캐시 무효화는 실제 훅 체인(core.plugin_settings.
|
# TokenCheckEndpointTest, 저장 시 토큰 캐시 무효화는 실제 훅 체인(core.plugin_settings.
|
||||||
# after_save) + 실제 CacheInterface 로 InvalidateTokenOnSettingsSaveListenerTest 가,
|
# after_save) + 실제 CacheInterface 로 InvalidateTokenOnSettingsSaveListenerTest 가,
|
||||||
# verifyCredentials/describeFailure 는 BizppurioTokenServiceTest 가 각각 관찰한다.
|
# verifyCredentials/describeFailure 는 BizppurioTokenServiceTest 가 각각 관찰한다.
|
||||||
# 런타임 Playwright spec 은 계획서 §9 방침에 따라 실연동 검증(PO 직접 수행, 인증·발송
|
# 런타임 Playwright spec 은 계획서 §9 방침에 따라 실연동 검증(직접 수행, 인증·발송
|
||||||
# 환경 필요) 단계에서 최초 도입하며, 그 시점에 @scenario/@effects docblock 완전 매핑을
|
# 환경 필요) 단계에서 최초 도입하며, 그 시점에 @scenario/@effects docblock 완전 매핑을
|
||||||
# 추가한다. 그때까지 매니페스트는 명세로 유지한다.
|
# 추가한다. 그때까지 매니페스트는 명세로 유지한다.
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
# GuestPhoneExtractListenerTest(6) + ChannelRegistrationHookTest(4, 실제 훅 체인).
|
# GuestPhoneExtractListenerTest(6) + ChannelRegistrationHookTest(4, 실제 훅 체인).
|
||||||
# 프론트 변경 없음(레이아웃 JSON/컴포넌트 미변경) → frontend-change-requires-e2e 비대상이라
|
# 프론트 변경 없음(레이아웃 JSON/컴포넌트 미변경) → frontend-change-requires-e2e 비대상이라
|
||||||
# Playwright spec 은 이번 Phase 미도입. 실발송 왕복(실제 API·webhook)은 계획서 §9 방침대로
|
# Playwright spec 은 이번 Phase 미도입. 실발송 왕복(실제 API·webhook)은 계획서 §9 방침대로
|
||||||
# PO 직접 수행하는 실연동 검증 단계에서 spec 최초 도입하며, 그때 @scenario/@effects 를 매핑한다.
|
# 직접 수행하는 실연동 검증 단계에서 spec 최초 도입하며, 그때 @scenario/@effects 를 매핑한다.
|
||||||
|
|
||||||
feature: 비즈뿌리오 문자 채널 등록 + 자동발송 (Phase 3)
|
feature: 비즈뿌리오 문자 채널 등록 + 자동발송 (Phase 3)
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며,
|
형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며,
|
||||||
[Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다.
|
[Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다.
|
||||||
|
|
||||||
## [1.0.7] - 2026-08-22
|
## [1.0.7] - 2026-08-24
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며,
|
형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며,
|
||||||
[Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다.
|
[Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다.
|
||||||
|
|
||||||
## [1.1.2] - 2026-08-22
|
## [1.1.2] - 2026-08-24
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ description: |
|
|||||||
|
|
||||||
키가 없으면 예외·경고 없이 원시 키 문자열이 제목으로 그대로 노출된다
|
키가 없으면 예외·경고 없이 원시 키 문자열이 제목으로 그대로 노출된다
|
||||||
(실사례: #481 이 sitemap_regenerated / sitemap_regenerate_failed 정의를 config 에만
|
(실사례: #481 이 sitemap_regenerated / sitemap_regenerate_failed 정의를 config 에만
|
||||||
추가하고 템플릿 라벨을 누락 — 2026-08-24 PO 제보). config/core.php 의 코어 정의
|
추가하고 템플릿 라벨을 누락 — 2026-08-24 제보). config/core.php 의 코어 정의
|
||||||
전수를 양 로케일 라벨과 자동 대조해 재발을 차단한다.
|
전수를 양 로케일 라벨과 자동 대조해 재발을 차단한다.
|
||||||
|
|
||||||
axes:
|
axes:
|
||||||
|
|||||||
Reference in New Issue
Block a user