refactor:바로빌 서버 모드를 회원사별 개별 설정으로 변경
기존 전역 세션 기반 서버 모드 → 회원사별 개별 설정 방식으로 변경 주요 변경사항: - BarobillMember 모델: server_mode 필드 및 accessor 추가 - BarobillService: switchServerMode() 메서드 추가 (동적 서버 전환) - BarobillMemberController: 회원사별 서버 모드 변경 API 추가 - 회원사 목록 테이블: 서버 모드 컬럼 추가 (클릭 시 변경 모달) - 서버 변경 확인 모달: 요금 부과 경고 및 동의 체크박스 추가 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -24,6 +24,8 @@ public function __construct(
|
||||
/**
|
||||
* 회원사 조회 및 비밀번호 검증 헬퍼
|
||||
*
|
||||
* 회원사의 서버 모드에 따라 BarobillService의 서버 모드도 자동 전환합니다.
|
||||
*
|
||||
* @return BarobillMember|JsonResponse 회원사 객체 또는 에러 응답
|
||||
*/
|
||||
private function validateMemberForUrlApi(int $id): BarobillMember|JsonResponse
|
||||
@@ -45,6 +47,9 @@ private function validateMemberForUrlApi(int $id): BarobillMember|JsonResponse
|
||||
], 422);
|
||||
}
|
||||
|
||||
// 회원사의 서버 모드로 BarobillService 전환
|
||||
$this->barobillService->setServerMode($member->server_mode ?? 'test');
|
||||
|
||||
return $member;
|
||||
}
|
||||
|
||||
@@ -858,57 +863,89 @@ public function getServiceCodes(): JsonResponse
|
||||
}
|
||||
|
||||
/**
|
||||
* 서버 모드 설정 (테스트/운영 서버 전환)
|
||||
* 회원사별 서버 모드 변경
|
||||
*
|
||||
* 세션에 바로빌 서버 모드를 저장합니다.
|
||||
* BarobillService 생성 시 이 세션 값을 읽어 사용합니다.
|
||||
* 특정 회원사의 바로빌 서버 모드(테스트/운영)를 변경합니다.
|
||||
* 주의: 운영 서버로 전환 시 요금이 부과됩니다.
|
||||
*/
|
||||
public function setServerMode(Request $request): JsonResponse
|
||||
public function updateServerMode(Request $request, int $id): JsonResponse
|
||||
{
|
||||
$member = BarobillMember::find($id);
|
||||
|
||||
if (!$member) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => '회원사를 찾을 수 없습니다.',
|
||||
], 404);
|
||||
}
|
||||
|
||||
$validated = $request->validate([
|
||||
'mode' => 'required|in:test,production',
|
||||
'server_mode' => 'required|in:test,production',
|
||||
'confirmed' => 'required|boolean',
|
||||
], [
|
||||
'mode.required' => '서버 모드를 선택해주세요.',
|
||||
'mode.in' => '서버 모드는 test 또는 production 이어야 합니다.',
|
||||
'server_mode.required' => '서버 모드를 선택해주세요.',
|
||||
'server_mode.in' => '서버 모드는 test 또는 production 이어야 합니다.',
|
||||
'confirmed.required' => '경고 확인이 필요합니다.',
|
||||
]);
|
||||
|
||||
$mode = $validated['mode'];
|
||||
session(['barobill_server_mode' => $mode]);
|
||||
// 확인 체크
|
||||
if (!$validated['confirmed']) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => '서버 변경 경고를 확인해주세요.',
|
||||
], 422);
|
||||
}
|
||||
|
||||
Log::info('바로빌 서버 모드 변경', [
|
||||
'mode' => $mode,
|
||||
$oldMode = $member->server_mode ?? 'test';
|
||||
$newMode = $validated['server_mode'];
|
||||
|
||||
// 변경 없으면 바로 반환
|
||||
if ($oldMode === $newMode) {
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => '서버 모드가 이미 ' . ($newMode === 'test' ? '테스트' : '운영') . ' 서버입니다.',
|
||||
'data' => $member,
|
||||
]);
|
||||
}
|
||||
|
||||
$member->update(['server_mode' => $newMode]);
|
||||
|
||||
Log::info('바로빌 회원사 서버 모드 변경', [
|
||||
'member_id' => $id,
|
||||
'biz_no' => $member->biz_no,
|
||||
'corp_name' => $member->corp_name,
|
||||
'old_mode' => $oldMode,
|
||||
'new_mode' => $newMode,
|
||||
'user_id' => auth()->id(),
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'mode' => $mode,
|
||||
'message' => ($mode === 'test' ? '테스트' : '운영') . ' 서버로 전환되었습니다.',
|
||||
'message' => ($newMode === 'test' ? '테스트' : '운영') . ' 서버로 변경되었습니다.',
|
||||
'data' => $member->fresh(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 서버 모드 조회
|
||||
*
|
||||
* 현재 세션에 저장된 바로빌 서버 모드를 반환합니다.
|
||||
* 세션 값이 없으면 .env 설정값을 반환합니다.
|
||||
* 회원사별 서버 모드 조회
|
||||
*/
|
||||
public function getServerMode(): JsonResponse
|
||||
public function getServerMode(int $id): JsonResponse
|
||||
{
|
||||
$sessionMode = session('barobill_server_mode');
|
||||
$member = BarobillMember::find($id);
|
||||
|
||||
if ($sessionMode) {
|
||||
$mode = $sessionMode;
|
||||
} else {
|
||||
// .env 설정 기준 (BAROBILL_TEST_MODE)
|
||||
$isTestMode = config('services.barobill.test_mode', true);
|
||||
$mode = $isTestMode ? 'test' : 'production';
|
||||
if (!$member) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => '회원사를 찾을 수 없습니다.',
|
||||
], 404);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'mode' => $mode,
|
||||
'source' => $sessionMode ? 'session' : 'env',
|
||||
'data' => [
|
||||
'server_mode' => $member->server_mode ?? 'test',
|
||||
'server_mode_label' => $member->server_mode_label,
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ class BarobillMember extends Model
|
||||
'manager_email',
|
||||
'manager_hp',
|
||||
'status',
|
||||
'server_mode',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
@@ -85,4 +86,36 @@ public function getStatusColorAttribute(): string
|
||||
default => 'bg-gray-100 text-gray-800',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 서버 모드 라벨
|
||||
*/
|
||||
public function getServerModeLabelAttribute(): string
|
||||
{
|
||||
return match ($this->server_mode) {
|
||||
'test' => '테스트',
|
||||
'production' => '운영',
|
||||
default => '테스트',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 서버 모드별 색상 클래스
|
||||
*/
|
||||
public function getServerModeColorAttribute(): string
|
||||
{
|
||||
return match ($this->server_mode) {
|
||||
'test' => 'bg-amber-100 text-amber-800',
|
||||
'production' => 'bg-green-100 text-green-800',
|
||||
default => 'bg-amber-100 text-amber-800',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 테스트 모드 여부
|
||||
*/
|
||||
public function isTestMode(): bool
|
||||
{
|
||||
return $this->server_mode !== 'production';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,15 +96,55 @@ class BarobillService
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
// 1. 세션에서 서버 모드 가져오기 (최우선)
|
||||
$sessionMode = session('barobill_server_mode');
|
||||
if ($sessionMode) {
|
||||
$this->isTestMode = ($sessionMode === 'test');
|
||||
} else {
|
||||
// 2. .env에서 테스트 모드 설정 가져오기 (기본값: true = 테스트 모드)
|
||||
$this->isTestMode = config('services.barobill.test_mode', true);
|
||||
// 기본값: .env 설정 사용
|
||||
$this->isTestMode = config('services.barobill.test_mode', true);
|
||||
$this->initializeConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* 서버 모드 전환 (회원사별 설정 적용)
|
||||
*
|
||||
* @param bool $isTestMode true: 테스트서버, false: 운영서버
|
||||
*/
|
||||
public function switchServerMode(bool $isTestMode): self
|
||||
{
|
||||
if ($this->isTestMode !== $isTestMode) {
|
||||
$this->isTestMode = $isTestMode;
|
||||
// SOAP 클라이언트 초기화 (새 서버로 재연결)
|
||||
$this->corpStateClient = null;
|
||||
$this->tiClient = null;
|
||||
$this->bankAccountClient = null;
|
||||
$this->cardClient = null;
|
||||
// 설정 재로드
|
||||
$this->initializeConfig();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 서버 모드 문자열로 전환
|
||||
*
|
||||
* @param string $mode 'test' 또는 'production'
|
||||
*/
|
||||
public function setServerMode(string $mode): self
|
||||
{
|
||||
return $this->switchServerMode($mode === 'test');
|
||||
}
|
||||
|
||||
/**
|
||||
* 현재 서버 모드 조회
|
||||
*/
|
||||
public function getServerMode(): string
|
||||
{
|
||||
return $this->isTestMode ? 'test' : 'production';
|
||||
}
|
||||
|
||||
/**
|
||||
* 설정 초기화 (서버 모드에 따른 설정 로드)
|
||||
*/
|
||||
protected function initializeConfig(): void
|
||||
{
|
||||
// DB에서 활성화된 설정 가져오기 (우선순위)
|
||||
$dbConfig = $this->loadConfigFromDatabase();
|
||||
|
||||
|
||||
@@ -10,30 +10,16 @@
|
||||
<h1 class="text-2xl font-bold text-gray-800">회원사관리</h1>
|
||||
<p class="text-sm text-gray-500 mt-1">바로빌 연동 회원사를 관리합니다</p>
|
||||
</div>
|
||||
<div class="flex flex-col sm:flex-row gap-3 items-stretch sm:items-center">
|
||||
<!-- 서버 선택 토글 -->
|
||||
<div id="serverModeToggle" class="flex items-center gap-2 px-3 py-2 bg-gray-50 rounded-lg border border-gray-200">
|
||||
<span class="text-sm font-medium text-gray-600">서버:</span>
|
||||
<button id="testServerBtn" onclick="BarobillServer.setMode('test')"
|
||||
class="px-3 py-1 text-xs rounded-full transition font-medium">
|
||||
테스트
|
||||
</button>
|
||||
<button id="prodServerBtn" onclick="BarobillServer.setMode('production')"
|
||||
class="px-3 py-1 text-xs rounded-full transition font-medium">
|
||||
운영
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onclick="MemberModal.openCreate()"
|
||||
class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg transition text-center w-full sm:w-auto flex items-center justify-center gap-2"
|
||||
>
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
|
||||
</svg>
|
||||
회원사 등록
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onclick="MemberModal.openCreate()"
|
||||
class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg transition text-center w-full sm:w-auto flex items-center justify-center gap-2"
|
||||
>
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
|
||||
</svg>
|
||||
회원사 등록
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 통계 카드 -->
|
||||
@@ -137,6 +123,78 @@ class="w-full px-4 py-2 border border-gray-300 text-gray-700 rounded-lg hover:bg
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 서버 모드 변경 확인 모달 -->
|
||||
<div id="serverModeConfirmModal" class="fixed inset-0 z-50 hidden">
|
||||
<div class="fixed inset-0 bg-black/50" onclick="ServerModeManager.closeModal()"></div>
|
||||
<div class="fixed inset-0 flex items-center justify-center p-4">
|
||||
<div class="bg-white rounded-xl shadow-xl w-full max-w-lg" onclick="event.stopPropagation()">
|
||||
<div class="px-6 py-4 border-b border-gray-100 flex items-center justify-between">
|
||||
<div>
|
||||
<h3 class="text-lg font-semibold text-gray-800">바로빌 서버 변경</h3>
|
||||
<p class="text-sm text-gray-500">
|
||||
<span id="serverModeModalMemberName" class="font-medium text-gray-700"></span> 회원사
|
||||
</p>
|
||||
</div>
|
||||
<button type="button" onclick="ServerModeManager.closeModal()" class="text-gray-400 hover:text-gray-600">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="p-6 space-y-4">
|
||||
<!-- 변경 정보 -->
|
||||
<div class="flex items-center justify-center gap-4 text-center">
|
||||
<div>
|
||||
<p class="text-xs text-gray-500 mb-1">현재</p>
|
||||
<p id="serverModeModalCurrentMode" class="font-semibold"></p>
|
||||
</div>
|
||||
<svg class="w-6 h-6 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3" />
|
||||
</svg>
|
||||
<div>
|
||||
<p class="text-xs text-gray-500 mb-1">변경</p>
|
||||
<p id="serverModeModalNewMode" class="font-semibold"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 경고 메시지 -->
|
||||
<div id="serverModeWarning">
|
||||
<!-- 동적으로 채워짐 -->
|
||||
</div>
|
||||
|
||||
<!-- 확인 체크박스 -->
|
||||
<label class="flex items-start gap-3 p-3 bg-gray-50 rounded-lg cursor-pointer hover:bg-gray-100 transition">
|
||||
<input type="checkbox"
|
||||
id="serverModeConfirmCheckbox"
|
||||
onchange="ServerModeManager.onConfirmCheckChange(this.checked)"
|
||||
class="mt-0.5 w-5 h-5 rounded border-gray-300 text-blue-600 focus:ring-blue-500">
|
||||
<span class="text-sm text-gray-700">
|
||||
위 내용을 확인하였으며, <strong>서버 변경에 따른 요금 부과</strong>에 동의합니다.
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="px-6 py-4 border-t border-gray-100 flex gap-3">
|
||||
<button
|
||||
type="button"
|
||||
onclick="ServerModeManager.closeModal()"
|
||||
class="flex-1 px-4 py-2 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 transition"
|
||||
>
|
||||
취소
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
id="serverModeConfirmBtn"
|
||||
onclick="ServerModeManager.confirmChange()"
|
||||
disabled
|
||||
class="flex-1 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
서버 변경
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
@@ -635,49 +693,111 @@ function closeBarobillDropdown() {
|
||||
}
|
||||
});
|
||||
|
||||
// 바로빌 서버 모드 관리
|
||||
const BarobillServer = {
|
||||
currentMode: 'test',
|
||||
// 회원사별 서버 모드 변경 관리
|
||||
const ServerModeManager = {
|
||||
pendingMemberId: null,
|
||||
pendingMode: null,
|
||||
|
||||
async init() {
|
||||
try {
|
||||
const res = await fetch('/api/admin/barobill/members/server-mode', {
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': '{{ csrf_token() }}',
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
});
|
||||
const data = await res.json();
|
||||
if (data.success) {
|
||||
this.currentMode = data.mode;
|
||||
this.updateUI();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('서버 모드 조회 실패:', error);
|
||||
// 서버 모드 변경 요청 (경고 모달 표시)
|
||||
requestChange(memberId, memberName, currentMode) {
|
||||
this.pendingMemberId = memberId;
|
||||
const newMode = currentMode === 'test' ? 'production' : 'test';
|
||||
this.pendingMode = newMode;
|
||||
|
||||
const modal = document.getElementById('serverModeConfirmModal');
|
||||
const memberNameEl = document.getElementById('serverModeModalMemberName');
|
||||
const currentModeEl = document.getElementById('serverModeModalCurrentMode');
|
||||
const newModeEl = document.getElementById('serverModeModalNewMode');
|
||||
const warningEl = document.getElementById('serverModeWarning');
|
||||
const confirmCheckbox = document.getElementById('serverModeConfirmCheckbox');
|
||||
|
||||
memberNameEl.textContent = memberName;
|
||||
currentModeEl.textContent = currentMode === 'test' ? '테스트 서버' : '운영 서버';
|
||||
currentModeEl.className = currentMode === 'test'
|
||||
? 'font-semibold text-amber-600'
|
||||
: 'font-semibold text-green-600';
|
||||
newModeEl.textContent = newMode === 'test' ? '테스트 서버' : '운영 서버';
|
||||
newModeEl.className = newMode === 'test'
|
||||
? 'font-semibold text-amber-600'
|
||||
: 'font-semibold text-green-600';
|
||||
|
||||
// 운영 서버로 전환 시 추가 경고
|
||||
if (newMode === 'production') {
|
||||
warningEl.innerHTML = `
|
||||
<div class="bg-red-50 border border-red-200 rounded-lg p-4 text-red-700">
|
||||
<div class="flex items-start gap-3">
|
||||
<svg class="w-5 h-5 flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
|
||||
</svg>
|
||||
<div>
|
||||
<p class="font-semibold">⚠️ 요금 부과 안내</p>
|
||||
<ul class="mt-2 text-sm space-y-1">
|
||||
<li>• 운영 서버 사용 시 <strong>실제 요금이 부과</strong>됩니다.</li>
|
||||
<li>• 회원사 등록, 세금계산서 발행 등 모든 API 호출에 과금됩니다.</li>
|
||||
<li>• 테스트 목적이라면 테스트 서버를 사용해 주세요.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
warningEl.innerHTML = `
|
||||
<div class="bg-amber-50 border border-amber-200 rounded-lg p-4 text-amber-700">
|
||||
<div class="flex items-start gap-3">
|
||||
<svg class="w-5 h-5 flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
<div>
|
||||
<p class="font-semibold">테스트 서버 안내</p>
|
||||
<ul class="mt-2 text-sm space-y-1">
|
||||
<li>• 테스트 서버는 개발/테스트 용도로만 사용됩니다.</li>
|
||||
<li>• 테스트 데이터는 실제 국세청에 전송되지 않습니다.</li>
|
||||
<li>• 운영 환경에서는 반드시 운영 서버로 전환해 주세요.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
confirmCheckbox.checked = false;
|
||||
document.getElementById('serverModeConfirmBtn').disabled = true;
|
||||
modal.classList.remove('hidden');
|
||||
},
|
||||
|
||||
async setMode(mode) {
|
||||
if (mode === this.currentMode) return;
|
||||
// 확인 체크박스 상태 변경
|
||||
onConfirmCheckChange(checked) {
|
||||
document.getElementById('serverModeConfirmBtn').disabled = !checked;
|
||||
},
|
||||
|
||||
// 서버 모드 변경 실행
|
||||
async confirmChange() {
|
||||
if (!this.pendingMemberId || !this.pendingMode) return;
|
||||
|
||||
const confirmBtn = document.getElementById('serverModeConfirmBtn');
|
||||
const originalText = confirmBtn.textContent;
|
||||
confirmBtn.disabled = true;
|
||||
confirmBtn.textContent = '변경 중...';
|
||||
|
||||
try {
|
||||
const res = await fetch('/api/admin/barobill/members/server-mode', {
|
||||
const res = await fetch(`/api/admin/barobill/members/${this.pendingMemberId}/server-mode`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-TOKEN': '{{ csrf_token() }}',
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ mode })
|
||||
body: JSON.stringify({
|
||||
server_mode: this.pendingMode,
|
||||
confirmed: true
|
||||
})
|
||||
});
|
||||
|
||||
const data = await res.json();
|
||||
|
||||
if (data.success) {
|
||||
this.currentMode = mode;
|
||||
this.updateUI();
|
||||
showToast(data.message, 'success');
|
||||
// 목록 새로고침
|
||||
this.closeModal();
|
||||
htmx.trigger(document.body, 'memberUpdated');
|
||||
} else {
|
||||
showToast(data.message || '서버 모드 변경 실패', 'error');
|
||||
@@ -685,31 +805,23 @@ function closeBarobillDropdown() {
|
||||
} catch (error) {
|
||||
console.error('서버 모드 변경 실패:', error);
|
||||
showToast('서버 모드 변경 중 오류가 발생했습니다.', 'error');
|
||||
} finally {
|
||||
confirmBtn.disabled = false;
|
||||
confirmBtn.textContent = originalText;
|
||||
}
|
||||
},
|
||||
|
||||
updateUI() {
|
||||
const testBtn = document.getElementById('testServerBtn');
|
||||
const prodBtn = document.getElementById('prodServerBtn');
|
||||
|
||||
// 버튼 스타일 초기화
|
||||
testBtn.classList.remove('bg-amber-500', 'text-white', 'bg-gray-200', 'text-gray-600');
|
||||
prodBtn.classList.remove('bg-green-500', 'text-white', 'bg-gray-200', 'text-gray-600');
|
||||
|
||||
if (this.currentMode === 'test') {
|
||||
testBtn.classList.add('bg-amber-500', 'text-white');
|
||||
prodBtn.classList.add('bg-gray-200', 'text-gray-600');
|
||||
} else {
|
||||
testBtn.classList.add('bg-gray-200', 'text-gray-600');
|
||||
prodBtn.classList.add('bg-green-500', 'text-white');
|
||||
}
|
||||
// 모달 닫기
|
||||
closeModal() {
|
||||
document.getElementById('serverModeConfirmModal').classList.add('hidden');
|
||||
this.pendingMemberId = null;
|
||||
this.pendingMode = null;
|
||||
}
|
||||
};
|
||||
|
||||
// 초기화
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
MemberModal.init();
|
||||
BarobillServer.init();
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
|
||||
@@ -46,6 +46,9 @@ class="inline-flex items-center px-4 py-2 border border-transparent shadow-sm te
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
||||
상태
|
||||
</th>
|
||||
<th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">
|
||||
서버
|
||||
</th>
|
||||
<th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">
|
||||
바로빌 서비스
|
||||
</th>
|
||||
@@ -88,6 +91,25 @@ class="inline-flex items-center px-4 py-2 border border-transparent shadow-sm te
|
||||
{{ $member->status_label }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-center">
|
||||
<button
|
||||
type="button"
|
||||
onclick="ServerModeManager.requestChange({{ $member->id }}, '{{ addslashes($member->corp_name) }}', '{{ $member->server_mode ?? 'test' }}')"
|
||||
class="px-2.5 py-1 inline-flex items-center text-xs leading-5 font-semibold rounded-full cursor-pointer hover:opacity-80 transition {{ $member->server_mode_color }}"
|
||||
title="클릭하여 서버 변경"
|
||||
>
|
||||
@if(($member->server_mode ?? 'test') === 'test')
|
||||
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
|
||||
</svg>
|
||||
@else
|
||||
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 00-2 2v4a2 2 0 002 2h14a2 2 0 002-2v-4a2 2 0 00-2-2m-2-4h.01M17 16h.01" />
|
||||
</svg>
|
||||
@endif
|
||||
{{ $member->server_mode_label }}
|
||||
</button>
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-center">
|
||||
<div class="relative inline-block text-left barobill-dropdown">
|
||||
<button
|
||||
|
||||
@@ -118,9 +118,6 @@
|
||||
Route::get('/stats', [\App\Http\Controllers\Api\Admin\Barobill\BarobillMemberController::class, 'stats'])->name('stats');
|
||||
// 서비스 코드 목록 (카드사/은행)
|
||||
Route::get('/service-codes', [\App\Http\Controllers\Api\Admin\Barobill\BarobillMemberController::class, 'getServiceCodes'])->name('service-codes');
|
||||
// 서버 모드 전환 (테스트/운영)
|
||||
Route::get('/server-mode', [\App\Http\Controllers\Api\Admin\Barobill\BarobillMemberController::class, 'getServerMode'])->name('server-mode.get');
|
||||
Route::post('/server-mode', [\App\Http\Controllers\Api\Admin\Barobill\BarobillMemberController::class, 'setServerMode'])->name('server-mode.set');
|
||||
|
||||
// 기본 CRUD
|
||||
Route::get('/', [\App\Http\Controllers\Api\Admin\Barobill\BarobillMemberController::class, 'index'])->name('index');
|
||||
@@ -158,6 +155,12 @@
|
||||
Route::post('/{id}/cash-charge-url', [\App\Http\Controllers\Api\Admin\Barobill\BarobillMemberController::class, 'getCashChargeUrl'])->name('cash-charge-url');
|
||||
Route::get('/{id}/certificate-status', [\App\Http\Controllers\Api\Admin\Barobill\BarobillMemberController::class, 'getCertificateStatus'])->name('certificate-status');
|
||||
Route::get('/{id}/balance', [\App\Http\Controllers\Api\Admin\Barobill\BarobillMemberController::class, 'getBalance'])->name('balance');
|
||||
|
||||
// ==========================================
|
||||
// 서버 모드 관리 (회원사별)
|
||||
// ==========================================
|
||||
Route::get('/{id}/server-mode', [\App\Http\Controllers\Api\Admin\Barobill\BarobillMemberController::class, 'getServerMode'])->name('server-mode.get');
|
||||
Route::post('/{id}/server-mode', [\App\Http\Controllers\Api\Admin\Barobill\BarobillMemberController::class, 'updateServerMode'])->name('server-mode.update');
|
||||
});
|
||||
|
||||
// 바로빌 사용량조회 API
|
||||
|
||||
Reference in New Issue
Block a user