Merge remote-tracking branch 'origin/develop' into develop
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;
|
||||
}
|
||||
|
||||
@@ -856,4 +861,91 @@ public function getServiceCodes(): 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([
|
||||
'server_mode' => 'required|in:test,production',
|
||||
'confirmed' => 'required|boolean',
|
||||
], [
|
||||
'server_mode.required' => '서버 모드를 선택해주세요.',
|
||||
'server_mode.in' => '서버 모드는 test 또는 production 이어야 합니다.',
|
||||
'confirmed.required' => '경고 확인이 필요합니다.',
|
||||
]);
|
||||
|
||||
// 확인 체크
|
||||
if (!$validated['confirmed']) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => '서버 변경 경고를 확인해주세요.',
|
||||
], 422);
|
||||
}
|
||||
|
||||
$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,
|
||||
'message' => ($newMode === 'test' ? '테스트' : '운영') . ' 서버로 변경되었습니다.',
|
||||
'data' => $member->fresh(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 회원사별 서버 모드 조회
|
||||
*/
|
||||
public function getServerMode(int $id): JsonResponse
|
||||
{
|
||||
$member = BarobillMember::find($id);
|
||||
|
||||
if (!$member) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => '회원사를 찾을 수 없습니다.',
|
||||
], 404);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => [
|
||||
'server_mode' => $member->server_mode ?? 'test',
|
||||
'server_mode_label' => $member->server_mode_label,
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,6 +102,53 @@ public function store(Request $request): JsonResponse
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 서비스 설정 개별 저장 (체크박스 변경 시 즉시 저장)
|
||||
*/
|
||||
public function updateService(Request $request): JsonResponse
|
||||
{
|
||||
$tenantId = session('selected_tenant_id', 1);
|
||||
|
||||
$validated = $request->validate([
|
||||
'field' => 'required|in:use_tax_invoice,use_bank_account,use_card_usage,use_hometax',
|
||||
'value' => 'required|boolean',
|
||||
]);
|
||||
|
||||
try {
|
||||
$setting = BarobillSetting::updateOrCreate(
|
||||
['tenant_id' => $tenantId],
|
||||
[
|
||||
$validated['field'] => $validated['value'],
|
||||
'corp_name' => '미설정',
|
||||
'ceo_name' => '미설정',
|
||||
'corp_num' => '0000000000',
|
||||
]
|
||||
);
|
||||
|
||||
$serviceNames = [
|
||||
'use_tax_invoice' => '전자세금계산서',
|
||||
'use_bank_account' => '계좌조회',
|
||||
'use_card_usage' => '카드사용내역',
|
||||
'use_hometax' => '홈텍스매입/매출',
|
||||
];
|
||||
|
||||
$serviceName = $serviceNames[$validated['field']] ?? $validated['field'];
|
||||
$status = $validated['value'] ? '활성화' : '비활성화';
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => "{$serviceName} 서비스가 {$status}되었습니다.",
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
Log::error('바로빌 서비스 설정 저장 실패', ['error' => $e->getMessage()]);
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => '설정 저장에 실패했습니다.',
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 서비스 이용 여부 확인 (다른 메뉴에서 참조용)
|
||||
*/
|
||||
|
||||
@@ -107,16 +107,58 @@ public function index(Request $request): View|Response
|
||||
// 해당 테넌트의 바로빌 회원사 정보
|
||||
$barobillMember = BarobillMember::where('tenant_id', $tenantId)->first();
|
||||
|
||||
// 테넌트별 서버 모드 적용 (회원사 설정 우선)
|
||||
$isTestMode = $barobillMember ? $barobillMember->isTestMode() : $this->isTestMode;
|
||||
|
||||
// 서버 모드에 따라 SOAP 설정 재초기화
|
||||
if ($barobillMember && $barobillMember->server_mode) {
|
||||
$this->applyMemberServerMode($barobillMember);
|
||||
}
|
||||
|
||||
return view('barobill.eaccount.index', [
|
||||
'certKey' => $this->certKey,
|
||||
'corpNum' => $this->corpNum,
|
||||
'isTestMode' => $this->isTestMode,
|
||||
'isTestMode' => $isTestMode,
|
||||
'hasSoapClient' => $this->soapClient !== null,
|
||||
'currentTenant' => $currentTenant,
|
||||
'barobillMember' => $barobillMember,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 회원사 서버 모드에 따라 SOAP 설정 적용
|
||||
*/
|
||||
private function applyMemberServerMode(BarobillMember $member): void
|
||||
{
|
||||
$memberTestMode = $member->isTestMode();
|
||||
$targetEnv = $memberTestMode ? 'test' : 'production';
|
||||
|
||||
// 해당 환경의 BarobillConfig 조회 (is_active 무관하게 환경에 맞는 설정 사용)
|
||||
$config = BarobillConfig::where('environment', $targetEnv)->first();
|
||||
|
||||
if ($config) {
|
||||
$this->isTestMode = $memberTestMode;
|
||||
$this->certKey = $config->cert_key;
|
||||
$this->corpNum = $config->corp_num;
|
||||
$baseUrl = $config->base_url ?: ($memberTestMode
|
||||
? 'https://testws.baroservice.com'
|
||||
: 'https://ws.baroservice.com');
|
||||
$this->soapUrl = $baseUrl . '/BANKACCOUNT.asmx?WSDL';
|
||||
|
||||
// SOAP 클라이언트 재초기화
|
||||
$this->initSoapClient();
|
||||
|
||||
Log::info('[Eaccount] 서버 모드 적용', [
|
||||
'targetEnv' => $targetEnv,
|
||||
'certKey' => substr($this->certKey ?? '', 0, 10) . '...',
|
||||
'corpNum' => $this->corpNum,
|
||||
'soapUrl' => $this->soapUrl,
|
||||
]);
|
||||
} else {
|
||||
Log::warning('[Eaccount] BarobillConfig 없음', ['targetEnv' => $targetEnv]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 등록된 계좌 목록 조회 (GetBankAccountEx)
|
||||
*/
|
||||
@@ -129,6 +171,11 @@ public function accounts(Request $request): JsonResponse
|
||||
$tenantId = session('selected_tenant_id', self::HEADQUARTERS_TENANT_ID);
|
||||
$barobillMember = BarobillMember::where('tenant_id', $tenantId)->first();
|
||||
|
||||
// 테넌트별 서버 모드 적용
|
||||
if ($barobillMember && $barobillMember->server_mode) {
|
||||
$this->applyMemberServerMode($barobillMember);
|
||||
}
|
||||
|
||||
// 바로빌 사용자 ID 결정
|
||||
$userId = $barobillMember?->barobill_id ?? '';
|
||||
|
||||
@@ -210,6 +257,11 @@ public function transactions(Request $request): JsonResponse
|
||||
$barobillMember = BarobillMember::where('tenant_id', $tenantId)->first();
|
||||
$userId = $barobillMember?->barobill_id ?? '';
|
||||
|
||||
// 테넌트별 서버 모드 적용
|
||||
if ($barobillMember && $barobillMember->server_mode) {
|
||||
$this->applyMemberServerMode($barobillMember);
|
||||
}
|
||||
|
||||
// DB에서 저장된 계정과목 데이터 조회
|
||||
$savedData = BankTransaction::getByDateRange($tenantId, $startDate, $endDate, $bankAccountNum ?: null);
|
||||
|
||||
@@ -532,12 +584,11 @@ private function getBankName(string $code): string
|
||||
}
|
||||
|
||||
/**
|
||||
* 계정과목 목록 조회
|
||||
* 계정과목 목록 조회 (글로벌 데이터)
|
||||
*/
|
||||
public function accountCodes(): JsonResponse
|
||||
{
|
||||
$tenantId = session('selected_tenant_id', self::HEADQUARTERS_TENANT_ID);
|
||||
$codes = AccountCode::getActiveByTenant($tenantId);
|
||||
$codes = AccountCode::getActive();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
@@ -551,15 +602,11 @@ public function accountCodes(): JsonResponse
|
||||
}
|
||||
|
||||
/**
|
||||
* 전체 계정과목 목록 조회 (설정용, 비활성 포함)
|
||||
* 전체 계정과목 목록 조회 (설정용, 비활성 포함, 글로벌 데이터)
|
||||
*/
|
||||
public function accountCodesAll(): JsonResponse
|
||||
{
|
||||
$tenantId = session('selected_tenant_id', self::HEADQUARTERS_TENANT_ID);
|
||||
$codes = AccountCode::where('tenant_id', $tenantId)
|
||||
->orderBy('sort_order')
|
||||
->orderBy('code')
|
||||
->get();
|
||||
$codes = AccountCode::getAll();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
@@ -568,23 +615,19 @@ public function accountCodesAll(): JsonResponse
|
||||
}
|
||||
|
||||
/**
|
||||
* 계정과목 추가
|
||||
* 계정과목 추가 (글로벌 데이터)
|
||||
*/
|
||||
public function accountCodeStore(Request $request): JsonResponse
|
||||
{
|
||||
try {
|
||||
$tenantId = session('selected_tenant_id', self::HEADQUARTERS_TENANT_ID);
|
||||
|
||||
$validated = $request->validate([
|
||||
'code' => 'required|string|max:10',
|
||||
'name' => 'required|string|max:100',
|
||||
'category' => 'nullable|string|max:50',
|
||||
]);
|
||||
|
||||
// 중복 체크
|
||||
$exists = AccountCode::where('tenant_id', $tenantId)
|
||||
->where('code', $validated['code'])
|
||||
->exists();
|
||||
// 중복 체크 (글로벌)
|
||||
$exists = AccountCode::where('code', $validated['code'])->exists();
|
||||
|
||||
if ($exists) {
|
||||
return response()->json([
|
||||
@@ -593,10 +636,10 @@ public function accountCodeStore(Request $request): JsonResponse
|
||||
], 422);
|
||||
}
|
||||
|
||||
$maxSort = AccountCode::where('tenant_id', $tenantId)->max('sort_order') ?? 0;
|
||||
$maxSort = AccountCode::max('sort_order') ?? 0;
|
||||
|
||||
$accountCode = AccountCode::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'tenant_id' => self::HEADQUARTERS_TENANT_ID, // 글로벌 데이터는 기본 테넌트에 저장
|
||||
'code' => $validated['code'],
|
||||
'name' => $validated['name'],
|
||||
'category' => $validated['category'] ?? null,
|
||||
@@ -618,16 +661,12 @@ public function accountCodeStore(Request $request): JsonResponse
|
||||
}
|
||||
|
||||
/**
|
||||
* 계정과목 수정
|
||||
* 계정과목 수정 (글로벌 데이터)
|
||||
*/
|
||||
public function accountCodeUpdate(Request $request, int $id): JsonResponse
|
||||
{
|
||||
try {
|
||||
$tenantId = session('selected_tenant_id', self::HEADQUARTERS_TENANT_ID);
|
||||
|
||||
$accountCode = AccountCode::where('tenant_id', $tenantId)
|
||||
->where('id', $id)
|
||||
->first();
|
||||
$accountCode = AccountCode::find($id);
|
||||
|
||||
if (!$accountCode) {
|
||||
return response()->json([
|
||||
@@ -643,10 +682,9 @@ public function accountCodeUpdate(Request $request, int $id): JsonResponse
|
||||
'is_active' => 'sometimes|boolean',
|
||||
]);
|
||||
|
||||
// 코드 변경 시 중복 체크
|
||||
// 코드 변경 시 중복 체크 (글로벌)
|
||||
if (isset($validated['code']) && $validated['code'] !== $accountCode->code) {
|
||||
$exists = AccountCode::where('tenant_id', $tenantId)
|
||||
->where('code', $validated['code'])
|
||||
$exists = AccountCode::where('code', $validated['code'])
|
||||
->where('id', '!=', $id)
|
||||
->exists();
|
||||
|
||||
@@ -674,16 +712,12 @@ public function accountCodeUpdate(Request $request, int $id): JsonResponse
|
||||
}
|
||||
|
||||
/**
|
||||
* 계정과목 삭제
|
||||
* 계정과목 삭제 (글로벌 데이터)
|
||||
*/
|
||||
public function accountCodeDestroy(int $id): JsonResponse
|
||||
{
|
||||
try {
|
||||
$tenantId = session('selected_tenant_id', self::HEADQUARTERS_TENANT_ID);
|
||||
|
||||
$accountCode = AccountCode::where('tenant_id', $tenantId)
|
||||
->where('id', $id)
|
||||
->first();
|
||||
$accountCode = AccountCode::find($id);
|
||||
|
||||
if (!$accountCode) {
|
||||
return response()->json([
|
||||
|
||||
@@ -107,16 +107,58 @@ public function index(Request $request): View|Response
|
||||
// 해당 테넌트의 바로빌 회원사 정보
|
||||
$barobillMember = BarobillMember::where('tenant_id', $tenantId)->first();
|
||||
|
||||
// 테넌트별 서버 모드 적용 (회원사 설정 우선)
|
||||
$isTestMode = $barobillMember ? $barobillMember->isTestMode() : $this->isTestMode;
|
||||
|
||||
// 서버 모드에 따라 SOAP 설정 재초기화
|
||||
if ($barobillMember && $barobillMember->server_mode) {
|
||||
$this->applyMemberServerMode($barobillMember);
|
||||
}
|
||||
|
||||
return view('barobill.ecard.index', [
|
||||
'certKey' => $this->certKey,
|
||||
'corpNum' => $this->corpNum,
|
||||
'isTestMode' => $this->isTestMode,
|
||||
'isTestMode' => $isTestMode,
|
||||
'hasSoapClient' => $this->soapClient !== null,
|
||||
'currentTenant' => $currentTenant,
|
||||
'barobillMember' => $barobillMember,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 회원사 서버 모드에 따라 SOAP 설정 적용
|
||||
*/
|
||||
private function applyMemberServerMode(BarobillMember $member): void
|
||||
{
|
||||
$memberTestMode = $member->isTestMode();
|
||||
$targetEnv = $memberTestMode ? 'test' : 'production';
|
||||
|
||||
// 해당 환경의 BarobillConfig 조회 (is_active 무관하게 환경에 맞는 설정 사용)
|
||||
$config = BarobillConfig::where('environment', $targetEnv)->first();
|
||||
|
||||
if ($config) {
|
||||
$this->isTestMode = $memberTestMode;
|
||||
$this->certKey = $config->cert_key;
|
||||
$this->corpNum = $config->corp_num;
|
||||
$baseUrl = $config->base_url ?: ($memberTestMode
|
||||
? 'https://testws.baroservice.com'
|
||||
: 'https://ws.baroservice.com');
|
||||
$this->soapUrl = $baseUrl . '/CARD.asmx?WSDL';
|
||||
|
||||
// SOAP 클라이언트 재초기화
|
||||
$this->initSoapClient();
|
||||
|
||||
Log::info('[Ecard] 서버 모드 적용', [
|
||||
'targetEnv' => $targetEnv,
|
||||
'certKey' => substr($this->certKey ?? '', 0, 10) . '...',
|
||||
'corpNum' => $this->corpNum,
|
||||
'soapUrl' => $this->soapUrl,
|
||||
]);
|
||||
} else {
|
||||
Log::warning('[Ecard] BarobillConfig 없음', ['targetEnv' => $targetEnv]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 등록된 카드 목록 조회 (GetCardEx2)
|
||||
* 레퍼런스: https://dev.barobill.co.kr/docs/references/카드조회-API#GetCardEx2
|
||||
@@ -124,6 +166,13 @@ public function index(Request $request): View|Response
|
||||
public function cards(Request $request): JsonResponse
|
||||
{
|
||||
try {
|
||||
// 테넌트별 서버 모드 적용
|
||||
$tenantId = session('selected_tenant_id', self::HEADQUARTERS_TENANT_ID);
|
||||
$barobillMember = BarobillMember::where('tenant_id', $tenantId)->first();
|
||||
if ($barobillMember && $barobillMember->server_mode) {
|
||||
$this->applyMemberServerMode($barobillMember);
|
||||
}
|
||||
|
||||
$availOnly = $request->input('availOnly', 0);
|
||||
|
||||
$result = $this->callSoap('GetCardEx2', [
|
||||
@@ -220,6 +269,11 @@ public function transactions(Request $request): JsonResponse
|
||||
$barobillMember = BarobillMember::where('tenant_id', $tenantId)->first();
|
||||
$userId = $barobillMember?->barobill_id ?? '';
|
||||
|
||||
// 테넌트별 서버 모드 적용
|
||||
if ($barobillMember && $barobillMember->server_mode) {
|
||||
$this->applyMemberServerMode($barobillMember);
|
||||
}
|
||||
|
||||
// 디버그 로그
|
||||
Log::info('[ECard] 조회 요청', [
|
||||
'tenantId' => $tenantId,
|
||||
|
||||
@@ -99,16 +99,58 @@ public function index(Request $request): View|Response
|
||||
? BarobillMember::where('tenant_id', $tenantId)->first()
|
||||
: null;
|
||||
|
||||
// 테넌트별 서버 모드 적용 (회원사 설정 우선)
|
||||
$isTestMode = $barobillMember ? $barobillMember->isTestMode() : $this->isTestMode;
|
||||
|
||||
// 서버 모드에 따라 SOAP 설정 재초기화
|
||||
if ($barobillMember && $barobillMember->server_mode) {
|
||||
$this->applyMemberServerMode($barobillMember);
|
||||
}
|
||||
|
||||
return view('barobill.etax.index', [
|
||||
'certKey' => $this->certKey,
|
||||
'corpNum' => $this->corpNum,
|
||||
'isTestMode' => $this->isTestMode,
|
||||
'isTestMode' => $isTestMode,
|
||||
'hasSoapClient' => $this->soapClient !== null,
|
||||
'currentTenant' => $currentTenant,
|
||||
'barobillMember' => $barobillMember,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 회원사 서버 모드에 따라 SOAP 설정 적용
|
||||
*/
|
||||
private function applyMemberServerMode(BarobillMember $member): void
|
||||
{
|
||||
$memberTestMode = $member->isTestMode();
|
||||
$targetEnv = $memberTestMode ? 'test' : 'production';
|
||||
|
||||
// 해당 환경의 BarobillConfig 조회 (is_active 무관하게 환경에 맞는 설정 사용)
|
||||
$config = BarobillConfig::where('environment', $targetEnv)->first();
|
||||
|
||||
if ($config) {
|
||||
$this->isTestMode = $memberTestMode;
|
||||
$this->certKey = $config->cert_key;
|
||||
$this->corpNum = $config->corp_num;
|
||||
$baseUrl = $config->base_url ?: ($memberTestMode
|
||||
? 'https://testws.baroservice.com'
|
||||
: 'https://ws.baroservice.com');
|
||||
$this->soapUrl = $baseUrl . '/TI.asmx?WSDL';
|
||||
|
||||
// SOAP 클라이언트 재초기화
|
||||
$this->initSoapClient();
|
||||
|
||||
Log::info('[Etax] 서버 모드 적용', [
|
||||
'targetEnv' => $targetEnv,
|
||||
'certKey' => substr($this->certKey ?? '', 0, 10) . '...',
|
||||
'corpNum' => $this->corpNum,
|
||||
'soapUrl' => $this->soapUrl,
|
||||
]);
|
||||
} else {
|
||||
Log::warning('[Etax] BarobillConfig 없음', ['targetEnv' => $targetEnv]);
|
||||
}
|
||||
}
|
||||
|
||||
// 바로빌 파트너사 (본사) 테넌트 ID
|
||||
private const HEADQUARTERS_TENANT_ID = 1;
|
||||
|
||||
@@ -153,6 +195,13 @@ public function getInvoices(): JsonResponse
|
||||
*/
|
||||
public function issue(Request $request): JsonResponse
|
||||
{
|
||||
// 테넌트별 서버 모드 적용
|
||||
$tenantId = session('selected_tenant_id', self::HEADQUARTERS_TENANT_ID);
|
||||
$barobillMember = BarobillMember::where('tenant_id', $tenantId)->first();
|
||||
if ($barobillMember && $barobillMember->server_mode) {
|
||||
$this->applyMemberServerMode($barobillMember);
|
||||
}
|
||||
|
||||
$input = $request->all();
|
||||
|
||||
$useRealAPI = $this->soapClient !== null && ($this->isTestMode || !empty($this->certKey));
|
||||
@@ -221,6 +270,13 @@ public function issue(Request $request): JsonResponse
|
||||
*/
|
||||
public function sendToNts(Request $request): JsonResponse
|
||||
{
|
||||
// 테넌트별 서버 모드 적용
|
||||
$tenantId = session('selected_tenant_id', self::HEADQUARTERS_TENANT_ID);
|
||||
$barobillMember = BarobillMember::where('tenant_id', $tenantId)->first();
|
||||
if ($barobillMember && $barobillMember->server_mode) {
|
||||
$this->applyMemberServerMode($barobillMember);
|
||||
}
|
||||
|
||||
$invoiceId = $request->input('invoiceId');
|
||||
|
||||
// 인보이스 조회
|
||||
|
||||
@@ -107,10 +107,18 @@ public function index(Request $request): View|Response
|
||||
// 해당 테넌트의 바로빌 회원사 정보
|
||||
$barobillMember = BarobillMember::where('tenant_id', $tenantId)->first();
|
||||
|
||||
// 테넌트별 서버 모드 적용 (회원사 설정 우선)
|
||||
$isTestMode = $barobillMember ? $barobillMember->isTestMode() : $this->isTestMode;
|
||||
|
||||
// 서버 모드에 따라 SOAP 설정 재초기화
|
||||
if ($barobillMember && $barobillMember->server_mode) {
|
||||
$this->applyMemberServerMode($barobillMember);
|
||||
}
|
||||
|
||||
return view('barobill.hometax.index', [
|
||||
'certKey' => $this->certKey,
|
||||
'corpNum' => $this->corpNum,
|
||||
'isTestMode' => $this->isTestMode,
|
||||
'isTestMode' => $isTestMode,
|
||||
'hasSoapClient' => $this->soapClient !== null,
|
||||
'tenantId' => $tenantId,
|
||||
'currentTenant' => $currentTenant,
|
||||
@@ -118,6 +126,39 @@ public function index(Request $request): View|Response
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 회원사 서버 모드에 따라 SOAP 설정 적용
|
||||
*/
|
||||
private function applyMemberServerMode(BarobillMember $member): void
|
||||
{
|
||||
$memberTestMode = $member->isTestMode();
|
||||
$targetEnv = $memberTestMode ? 'test' : 'production';
|
||||
|
||||
// 해당 환경의 BarobillConfig 조회 (is_active 무관하게 환경에 맞는 설정 사용)
|
||||
$config = BarobillConfig::where('environment', $targetEnv)->first();
|
||||
|
||||
if ($config) {
|
||||
$this->isTestMode = $memberTestMode;
|
||||
$this->certKey = $config->cert_key;
|
||||
$this->corpNum = $config->corp_num;
|
||||
$this->baseUrl = $config->base_url ?: ($memberTestMode
|
||||
? 'https://testws.baroservice.com'
|
||||
: 'https://ws.baroservice.com');
|
||||
|
||||
// SOAP 클라이언트 재초기화
|
||||
$this->initSoapClient();
|
||||
|
||||
Log::info('[Hometax] 서버 모드 적용', [
|
||||
'targetEnv' => $targetEnv,
|
||||
'certKey' => substr($this->certKey ?? '', 0, 10) . '...',
|
||||
'corpNum' => $this->corpNum,
|
||||
'baseUrl' => $this->baseUrl,
|
||||
]);
|
||||
} else {
|
||||
Log::warning('[Hometax] BarobillConfig 없음', ['targetEnv' => $targetEnv]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 매출 세금계산서 목록 조회 (GetPeriodTaxInvoiceSalesList)
|
||||
*
|
||||
@@ -146,6 +187,11 @@ public function sales(Request $request): JsonResponse
|
||||
]);
|
||||
}
|
||||
|
||||
// 테넌트별 서버 모드 적용
|
||||
if ($barobillMember->server_mode) {
|
||||
$this->applyMemberServerMode($barobillMember);
|
||||
}
|
||||
|
||||
$userId = $barobillMember->barobill_id ?? '';
|
||||
|
||||
if (empty($userId)) {
|
||||
@@ -221,12 +267,16 @@ public function sales(Request $request): JsonResponse
|
||||
// 작성일 기준으로 정렬 (최신순)
|
||||
usort($allInvoices, fn($a, $b) => strcmp($b['writeDate'] ?? '', $a['writeDate'] ?? ''));
|
||||
|
||||
// 마지막 매출 수집 시간 업데이트
|
||||
$barobillMember->update(['last_sales_fetch_at' => now()]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => [
|
||||
'invoices' => $allInvoices,
|
||||
'pagination' => $lastPagination,
|
||||
'summary' => $totalSummary
|
||||
'summary' => $totalSummary,
|
||||
'lastFetchAt' => now()->format('Y-m-d H:i:s')
|
||||
]
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
@@ -266,6 +316,11 @@ public function purchases(Request $request): JsonResponse
|
||||
]);
|
||||
}
|
||||
|
||||
// 테넌트별 서버 모드 적용
|
||||
if ($barobillMember->server_mode) {
|
||||
$this->applyMemberServerMode($barobillMember);
|
||||
}
|
||||
|
||||
$userId = $barobillMember->barobill_id ?? '';
|
||||
|
||||
if (empty($userId)) {
|
||||
@@ -341,12 +396,16 @@ public function purchases(Request $request): JsonResponse
|
||||
// 작성일 기준으로 정렬 (최신순)
|
||||
usort($allInvoices, fn($a, $b) => strcmp($b['writeDate'] ?? '', $a['writeDate'] ?? ''));
|
||||
|
||||
// 마지막 매입 수집 시간 업데이트
|
||||
$barobillMember->update(['last_purchases_fetch_at' => now()]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => [
|
||||
'invoices' => $allInvoices,
|
||||
'pagination' => $lastPagination,
|
||||
'summary' => $totalSummary
|
||||
'summary' => $totalSummary,
|
||||
'lastFetchAt' => now()->format('Y-m-d H:i:s')
|
||||
]
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
@@ -491,6 +550,12 @@ public function diagnose(Request $request): JsonResponse
|
||||
try {
|
||||
$tenantId = session('selected_tenant_id', self::HEADQUARTERS_TENANT_ID);
|
||||
$barobillMember = BarobillMember::where('tenant_id', $tenantId)->first();
|
||||
|
||||
// 테넌트별 서버 모드 적용
|
||||
if ($barobillMember && $barobillMember->server_mode) {
|
||||
$this->applyMemberServerMode($barobillMember);
|
||||
}
|
||||
|
||||
$userId = $barobillMember?->barobill_id ?? '';
|
||||
$memberCorpNum = $barobillMember?->biz_no ?? '';
|
||||
|
||||
@@ -577,18 +642,24 @@ public function requestCollect(Request $request): JsonResponse
|
||||
}
|
||||
|
||||
/**
|
||||
* 수집 상태 확인 (미지원 안내)
|
||||
* 수집 상태 확인 (마지막 수집 시간 조회)
|
||||
*/
|
||||
public function collectStatus(Request $request): JsonResponse
|
||||
{
|
||||
$tenantId = session('selected_tenant_id', self::HEADQUARTERS_TENANT_ID);
|
||||
$barobillMember = BarobillMember::where('tenant_id', $tenantId)->first();
|
||||
|
||||
$salesLastFetch = $barobillMember?->last_sales_fetch_at;
|
||||
$purchasesLastFetch = $barobillMember?->last_purchases_fetch_at;
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => [
|
||||
'salesLastCollectDate' => '',
|
||||
'purchaseLastCollectDate' => '',
|
||||
'salesLastCollectDate' => $salesLastFetch ? $salesLastFetch->format('Y-m-d H:i') : '',
|
||||
'purchaseLastCollectDate' => $purchasesLastFetch ? $purchasesLastFetch->format('Y-m-d H:i') : '',
|
||||
'isCollecting' => false,
|
||||
'collectStateText' => '확인 필요',
|
||||
'message' => '서비스 상태 진단 기능을 사용하여 홈택스 연동 상태를 확인해주세요.'
|
||||
'collectStateText' => ($salesLastFetch || $purchasesLastFetch) ? '조회 완료' : '조회 전',
|
||||
'message' => '매출/매입 탭을 클릭하면 데이터가 조회되고 수집 시간이 기록됩니다.'
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
166
app/Http/Controllers/Finance/CorporateVehicleController.php
Normal file
166
app/Http/Controllers/Finance/CorporateVehicleController.php
Normal file
@@ -0,0 +1,166 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Finance;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\CorporateVehicle;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class CorporateVehicleController extends Controller
|
||||
{
|
||||
public function index(Request $request): View|Response
|
||||
{
|
||||
if ($request->header('HX-Request')) {
|
||||
return response('', 200)->header('HX-Redirect', route('finance.corporate-vehicles'));
|
||||
}
|
||||
|
||||
return view('finance.corporate-vehicles');
|
||||
}
|
||||
|
||||
public function list(Request $request): JsonResponse
|
||||
{
|
||||
$tenantId = session('tenant_id', 1);
|
||||
|
||||
$query = CorporateVehicle::where('tenant_id', $tenantId);
|
||||
|
||||
// 필터링
|
||||
if ($request->filled('ownership_type') && $request->ownership_type !== 'all') {
|
||||
$query->where('ownership_type', $request->ownership_type);
|
||||
}
|
||||
|
||||
if ($request->filled('vehicle_type') && $request->vehicle_type !== 'all') {
|
||||
$query->where('vehicle_type', $request->vehicle_type);
|
||||
}
|
||||
|
||||
if ($request->filled('status') && $request->status !== 'all') {
|
||||
$query->where('status', $request->status);
|
||||
}
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$search = $request->search;
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('plate_number', 'like', "%{$search}%")
|
||||
->orWhere('model', 'like', "%{$search}%")
|
||||
->orWhere('driver', 'like', "%{$search}%");
|
||||
});
|
||||
}
|
||||
|
||||
$vehicles = $query->orderBy('created_at', 'desc')->get();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $vehicles,
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(Request $request): JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
'plate_number' => 'required|string|max:20',
|
||||
'model' => 'required|string|max:100',
|
||||
'vehicle_type' => 'required|string|max:20',
|
||||
'ownership_type' => 'required|in:corporate,rent,lease',
|
||||
]);
|
||||
|
||||
$tenantId = session('tenant_id', 1);
|
||||
|
||||
$vehicle = CorporateVehicle::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'plate_number' => $request->plate_number,
|
||||
'model' => $request->model,
|
||||
'vehicle_type' => $request->vehicle_type,
|
||||
'ownership_type' => $request->ownership_type,
|
||||
'year' => $request->year,
|
||||
'driver' => $request->driver,
|
||||
'status' => $request->status ?? 'active',
|
||||
'mileage' => $request->mileage ?? 0,
|
||||
'memo' => $request->memo,
|
||||
// 법인차량 전용
|
||||
'purchase_date' => $request->purchase_date,
|
||||
'purchase_price' => $request->purchase_price ?? 0,
|
||||
// 렌트/리스 전용
|
||||
'contract_date' => $request->contract_date,
|
||||
'rent_company' => $request->rent_company,
|
||||
'rent_company_tel' => $request->rent_company_tel,
|
||||
'rent_period' => $request->rent_period,
|
||||
'agreed_mileage' => $request->agreed_mileage,
|
||||
'vehicle_price' => $request->vehicle_price ?? 0,
|
||||
'residual_value' => $request->residual_value ?? 0,
|
||||
'deposit' => $request->deposit ?? 0,
|
||||
'monthly_rent' => $request->monthly_rent ?? 0,
|
||||
'monthly_rent_tax' => $request->monthly_rent_tax ?? 0,
|
||||
'insurance_company' => $request->insurance_company,
|
||||
'insurance_company_tel' => $request->insurance_company_tel,
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => '차량이 등록되었습니다.',
|
||||
'data' => $vehicle,
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(Request $request, int $id): JsonResponse
|
||||
{
|
||||
$tenantId = session('tenant_id', 1);
|
||||
|
||||
$vehicle = CorporateVehicle::where('tenant_id', $tenantId)->findOrFail($id);
|
||||
|
||||
$request->validate([
|
||||
'plate_number' => 'required|string|max:20',
|
||||
'model' => 'required|string|max:100',
|
||||
'vehicle_type' => 'required|string|max:20',
|
||||
'ownership_type' => 'required|in:corporate,rent,lease',
|
||||
]);
|
||||
|
||||
$vehicle->update([
|
||||
'plate_number' => $request->plate_number,
|
||||
'model' => $request->model,
|
||||
'vehicle_type' => $request->vehicle_type,
|
||||
'ownership_type' => $request->ownership_type,
|
||||
'year' => $request->year,
|
||||
'driver' => $request->driver,
|
||||
'status' => $request->status ?? 'active',
|
||||
'mileage' => $request->mileage ?? 0,
|
||||
'memo' => $request->memo,
|
||||
// 법인차량 전용
|
||||
'purchase_date' => $request->purchase_date,
|
||||
'purchase_price' => $request->purchase_price ?? 0,
|
||||
// 렌트/리스 전용
|
||||
'contract_date' => $request->contract_date,
|
||||
'rent_company' => $request->rent_company,
|
||||
'rent_company_tel' => $request->rent_company_tel,
|
||||
'rent_period' => $request->rent_period,
|
||||
'agreed_mileage' => $request->agreed_mileage,
|
||||
'vehicle_price' => $request->vehicle_price ?? 0,
|
||||
'residual_value' => $request->residual_value ?? 0,
|
||||
'deposit' => $request->deposit ?? 0,
|
||||
'monthly_rent' => $request->monthly_rent ?? 0,
|
||||
'monthly_rent_tax' => $request->monthly_rent_tax ?? 0,
|
||||
'insurance_company' => $request->insurance_company,
|
||||
'insurance_company_tel' => $request->insurance_company_tel,
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => '차량 정보가 수정되었습니다.',
|
||||
'data' => $vehicle,
|
||||
]);
|
||||
}
|
||||
|
||||
public function destroy(int $id): JsonResponse
|
||||
{
|
||||
$tenantId = session('tenant_id', 1);
|
||||
|
||||
$vehicle = CorporateVehicle::where('tenant_id', $tenantId)->findOrFail($id);
|
||||
$vehicle->delete();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => '차량이 삭제되었습니다.',
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Http\Controllers\Sales;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Sales\SalesCommission;
|
||||
use App\Models\Sales\SalesScenarioChecklist;
|
||||
use App\Models\Sales\SalesTenantManagement;
|
||||
use App\Models\Sales\TenantProspect;
|
||||
@@ -82,7 +83,7 @@ private function getIndexData(Request $request): array
|
||||
// 영업 역할을 가진 사용자 목록 (영업파트너)
|
||||
$salesPartners = User::whereHas('userRoles', function ($q) {
|
||||
$q->whereHas('role', function ($rq) {
|
||||
$rq->whereIn('name', ['sales', 'manager', 'recruiter']);
|
||||
$rq->whereIn('name', ['sales', 'manager']);
|
||||
});
|
||||
})->orderBy('name')->get();
|
||||
|
||||
@@ -136,6 +137,14 @@ private function getIndexData(Request $request): array
|
||||
$prospect->hq_status = $management?->hq_status ?? 'pending';
|
||||
$prospect->hq_status_label = $management?->hq_status_label ?? '대기';
|
||||
$prospect->manager_user = $management?->manager;
|
||||
|
||||
// 수당 정보 (management가 있는 경우)
|
||||
if ($management) {
|
||||
$commission = SalesCommission::where('management_id', $management->id)->first();
|
||||
$prospect->commission = $commission;
|
||||
} else {
|
||||
$prospect->commission = null;
|
||||
}
|
||||
}
|
||||
|
||||
// 전체 통계
|
||||
@@ -185,4 +194,87 @@ public function updateHqStatus(int $id, Request $request)
|
||||
'hq_status_label' => $management->hq_status_label,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 수당 날짜 기록/수정
|
||||
*/
|
||||
public function updateCommissionDate(int $id, Request $request)
|
||||
{
|
||||
$this->checkAdminAccess();
|
||||
|
||||
$request->validate([
|
||||
'field' => 'required|in:first_payment_at,first_partner_paid_at,second_payment_at,second_partner_paid_at,first_subscription_at,manager_paid_at',
|
||||
'date' => 'nullable|date',
|
||||
]);
|
||||
|
||||
$prospect = TenantProspect::findOrFail($id);
|
||||
$management = SalesTenantManagement::findOrCreateByProspect($prospect->id);
|
||||
|
||||
// Commission 레코드 조회 또는 생성
|
||||
$commission = SalesCommission::firstOrCreate(
|
||||
['management_id' => $management->id],
|
||||
[
|
||||
'tenant_id' => $prospect->tenant_id ?? 1,
|
||||
'payment_type' => 'deposit',
|
||||
'payment_amount' => 0,
|
||||
'payment_date' => now(),
|
||||
'base_amount' => 0,
|
||||
'partner_rate' => 0,
|
||||
'manager_rate' => 0,
|
||||
'partner_commission' => 0,
|
||||
'manager_commission' => 0,
|
||||
'scheduled_payment_date' => now()->addMonth()->day(10),
|
||||
'status' => SalesCommission::STATUS_PENDING,
|
||||
'partner_id' => $management->sales_partner_id ?? 0,
|
||||
'manager_user_id' => $management->manager_user_id,
|
||||
]
|
||||
);
|
||||
|
||||
$field = $request->input('field');
|
||||
$date = $request->input('date') ?: now()->format('Y-m-d');
|
||||
|
||||
$commission->update([
|
||||
$field => $date,
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'field' => $field,
|
||||
'date' => $commission->$field?->format('Y-m-d'),
|
||||
'date_display' => $commission->$field?->format('m/d'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 수당 날짜 삭제 (초기화)
|
||||
*/
|
||||
public function clearCommissionDate(int $id, Request $request)
|
||||
{
|
||||
$this->checkAdminAccess();
|
||||
|
||||
$request->validate([
|
||||
'field' => 'required|in:first_payment_at,first_partner_paid_at,second_payment_at,second_partner_paid_at,first_subscription_at,manager_paid_at',
|
||||
]);
|
||||
|
||||
$prospect = TenantProspect::findOrFail($id);
|
||||
$management = SalesTenantManagement::where('tenant_prospect_id', $prospect->id)->first();
|
||||
|
||||
if (!$management) {
|
||||
return response()->json(['success' => false, 'message' => '관리 정보가 없습니다.']);
|
||||
}
|
||||
|
||||
$commission = SalesCommission::where('management_id', $management->id)->first();
|
||||
|
||||
if (!$commission) {
|
||||
return response()->json(['success' => false, 'message' => '수당 정보가 없습니다.']);
|
||||
}
|
||||
|
||||
$field = $request->input('field');
|
||||
$commission->update([$field => null]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'field' => $field,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,10 +251,8 @@ private function getDashboardData(Request $request): array
|
||||
->get()
|
||||
->keyBy('tenant_id');
|
||||
|
||||
// 내가 유치한 영업파트너 목록 (드롭다운용)
|
||||
$allManagers = auth()->user()->children()
|
||||
->where('is_active', true)
|
||||
->get(['id', 'name', 'email']);
|
||||
// 상담매니저 역할을 가진 모든 사용자 (드롭다운용)
|
||||
$allManagers = $this->getAllManagerUsers();
|
||||
|
||||
// 내가 매니저로만 참여하는 건 (다른 사람이 등록, 내가 매니저)
|
||||
$managerOnlyProspects = $this->getManagerOnlyProspects($currentUserId);
|
||||
@@ -412,10 +410,8 @@ public function refreshTenantList(Request $request): View
|
||||
->get()
|
||||
->keyBy('tenant_id');
|
||||
|
||||
// 내가 유치한 영업파트너 목록 (드롭다운용)
|
||||
$allManagers = auth()->user()->children()
|
||||
->where('is_active', true)
|
||||
->get(['id', 'name', 'email']);
|
||||
// 상담매니저 역할을 가진 모든 사용자 (드롭다운용)
|
||||
$allManagers = $this->getAllManagerUsers();
|
||||
|
||||
return view('sales.dashboard.partials.tenant-list', compact(
|
||||
'tenants',
|
||||
@@ -768,6 +764,58 @@ private function getCommissionData(): array
|
||||
return compact('commissionSummary', 'recentCommissions', 'partner');
|
||||
}
|
||||
|
||||
/**
|
||||
* 상담매니저 역할을 가진 모든 사용자 조회
|
||||
* (tenant_id 조건 없이 - 파트너 관리 페이지와 동일한 방식)
|
||||
*/
|
||||
private function getAllManagerUsers()
|
||||
{
|
||||
return User::whereHas('userRoles.role', fn($q) => $q->where('name', 'manager'))
|
||||
->where('is_active', true)
|
||||
->where('id', '!=', auth()->id()) // 본인 제외
|
||||
->get(['id', 'name', 'email']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 매니저 검색 API (AJAX)
|
||||
* (tenant_id 조건 없이 - 모든 상담매니저 검색 가능)
|
||||
*/
|
||||
public function searchManagers(Request $request): JsonResponse
|
||||
{
|
||||
$query = $request->input('q', '');
|
||||
$authId = auth()->id();
|
||||
|
||||
// 디버깅: SQL 쿼리 로깅
|
||||
\DB::enableQueryLog();
|
||||
|
||||
$managers = User::whereHas('userRoles.role', fn($q) => $q->where('name', 'manager'))
|
||||
->where('is_active', true)
|
||||
->where('id', '!=', $authId)
|
||||
->when($query, function ($q) use ($query) {
|
||||
$q->where(function ($subQ) use ($query) {
|
||||
$subQ->where('name', 'like', "%{$query}%")
|
||||
->orWhere('email', 'like', "%{$query}%");
|
||||
});
|
||||
})
|
||||
->limit(10)
|
||||
->get(['id', 'name', 'email']);
|
||||
|
||||
$sqlLog = \DB::getQueryLog();
|
||||
|
||||
\Log::info('searchManagers 디버그', [
|
||||
'query' => $query,
|
||||
'auth_id' => $authId,
|
||||
'result_count' => $managers->count(),
|
||||
'results' => $managers->pluck('name')->toArray(),
|
||||
'sql' => $sqlLog,
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'managers' => $managers,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 영업파트너 가이드북 도움말 모달
|
||||
*/
|
||||
|
||||
@@ -261,7 +261,7 @@ public function delegateRole(Request $request, int $id)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'to_user_id' => 'required|exists:users,id',
|
||||
'role_name' => 'required|string|in:manager,recruiter',
|
||||
'role_name' => 'required|string|in:manager',
|
||||
]);
|
||||
|
||||
$fromUser = User::findOrFail($id);
|
||||
@@ -270,7 +270,7 @@ public function delegateRole(Request $request, int $id)
|
||||
try {
|
||||
$this->service->delegateRole($fromUser, $toUser, $validated['role_name']);
|
||||
|
||||
$roleLabel = $validated['role_name'] === 'manager' ? '매니저' : '유치담당';
|
||||
$roleLabel = '상담매니저';
|
||||
return redirect()->back()
|
||||
->with('success', "{$roleLabel} 역할이 {$toUser->name}님에게 위임되었습니다.");
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
@@ -285,13 +285,13 @@ public function delegateRole(Request $request, int $id)
|
||||
public function assignRole(Request $request, int $id)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'role_name' => 'required|string|in:sales,manager,recruiter',
|
||||
'role_name' => 'required|string|in:sales,manager',
|
||||
]);
|
||||
|
||||
$partner = User::findOrFail($id);
|
||||
$this->service->assignRole($partner, $validated['role_name']);
|
||||
|
||||
$roleLabels = ['sales' => '영업', 'manager' => '매니저', 'recruiter' => '유치담당'];
|
||||
$roleLabels = ['sales' => '영업파트너', 'manager' => '상담매니저'];
|
||||
return redirect()->back()
|
||||
->with('success', "{$roleLabels[$validated['role_name']]} 역할이 부여되었습니다.");
|
||||
}
|
||||
@@ -302,13 +302,13 @@ public function assignRole(Request $request, int $id)
|
||||
public function removeRole(Request $request, int $id)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'role_name' => 'required|string|in:sales,manager,recruiter',
|
||||
'role_name' => 'required|string|in:sales,manager',
|
||||
]);
|
||||
|
||||
$partner = User::findOrFail($id);
|
||||
$this->service->removeRole($partner, $validated['role_name']);
|
||||
|
||||
$roleLabels = ['sales' => '영업', 'manager' => '매니저', 'recruiter' => '유치담당'];
|
||||
$roleLabels = ['sales' => '영업파트너', 'manager' => '상담매니저'];
|
||||
return redirect()->back()
|
||||
->with('success', "{$roleLabels[$validated['role_name']]} 역할이 제거되었습니다.");
|
||||
}
|
||||
|
||||
@@ -228,6 +228,7 @@ public function prospectManagerScenario(int $prospectId, Request $request): View
|
||||
$steps = config('sales_scenario.manager_steps');
|
||||
$currentStep = (int) $request->input('step', 1);
|
||||
$icons = config('sales_scenario.icons');
|
||||
$readonly = $request->boolean('readonly', false);
|
||||
|
||||
// 가망고객 영업 관리 정보 조회 또는 생성
|
||||
$management = SalesTenantManagement::findOrCreateByProspect($prospectId);
|
||||
@@ -250,6 +251,7 @@ public function prospectManagerScenario(int $prospectId, Request $request): View
|
||||
'icons' => $icons,
|
||||
'management' => $management,
|
||||
'isProspect' => true,
|
||||
'readonly' => $readonly,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -262,6 +264,7 @@ public function prospectManagerScenario(int $prospectId, Request $request): View
|
||||
'icons' => $icons,
|
||||
'management' => $management,
|
||||
'isProspect' => true,
|
||||
'readonly' => $readonly,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -171,9 +171,10 @@ public function destroy(int $id)
|
||||
->with('error', '이미 테넌트로 전환된 영업권은 삭제할 수 없습니다.');
|
||||
}
|
||||
|
||||
// 본인 또는 관리자만 삭제 가능
|
||||
if ($prospect->registered_by !== auth()->id()) {
|
||||
// TODO: 관리자 권한 체크 추가
|
||||
// 관리자만 삭제 가능
|
||||
if (!auth()->user()->isAdmin()) {
|
||||
return redirect()->route('sales.prospects.index')
|
||||
->with('error', '삭제 권한이 없습니다. 본사 운영팀에 문의하세요.');
|
||||
}
|
||||
|
||||
$prospect->delete();
|
||||
|
||||
Reference in New Issue
Block a user