diff --git a/app/Console/Commands/FixMenuUrlCommand.php b/app/Console/Commands/FixMenuUrlCommand.php
index 92d34e4f..2fcee57e 100644
--- a/app/Console/Commands/FixMenuUrlCommand.php
+++ b/app/Console/Commands/FixMenuUrlCommand.php
@@ -8,6 +8,7 @@
class FixMenuUrlCommand extends Command
{
protected $signature = 'menu:fix-url {name} {new-url} {--tenant=}';
+
protected $description = '메뉴 URL 수정 (이름으로 검색)';
public function handle(): int
@@ -26,6 +27,7 @@ public function handle(): int
if ($menus->isEmpty()) {
$this->error("'{$name}' 메뉴를 찾을 수 없습니다.");
+
return 1;
}
@@ -37,6 +39,7 @@ public function handle(): int
}
$this->info("{$menus->count()}건 수정 완료.");
+
return 0;
}
}
diff --git a/app/Console/Commands/SeedQuoteFormulasCommand.php b/app/Console/Commands/SeedQuoteFormulasCommand.php
index e2f76185..2c30725c 100644
--- a/app/Console/Commands/SeedQuoteFormulasCommand.php
+++ b/app/Console/Commands/SeedQuoteFormulasCommand.php
@@ -800,4 +800,4 @@ private function getItemData(): array
],
];
}
-}
\ No newline at end of file
+}
diff --git a/app/Http/Controllers/Api/Admin/BankAccountController.php b/app/Http/Controllers/Api/Admin/BankAccountController.php
index 7d975340..82968328 100644
--- a/app/Http/Controllers/Api/Admin/BankAccountController.php
+++ b/app/Http/Controllers/Api/Admin/BankAccountController.php
@@ -3,7 +3,6 @@
namespace App\Http\Controllers\Api\Admin;
use App\Http\Controllers\Controller;
-use App\Models\Finance\BankAccount;
use App\Services\BankAccountService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -86,7 +85,7 @@ public function store(Request $request): JsonResponse
// 기본값 설정
$validated['status'] = $validated['status'] ?? 'active';
- $validated['account_name'] = $validated['account_name'] ?? $validated['bank_name'] . ' 계좌';
+ $validated['account_name'] = $validated['account_name'] ?? $validated['bank_name'].' 계좌';
$account = $this->bankAccountService->createAccount($validated);
@@ -156,6 +155,7 @@ public function destroy(Request $request, int $id): JsonResponse|Response
// HTMX 요청인 경우 갱신된 테이블 반환
if ($request->header('HX-Request')) {
$accounts = $this->bankAccountService->getAccounts($request->all(), $request->integer('per_page', 15));
+
return response(view('finance.accounts.partials.table', compact('accounts')));
}
@@ -184,6 +184,7 @@ public function restore(Request $request, int $id): JsonResponse|Response
// HTMX 요청인 경우 갱신된 테이블 반환
if ($request->header('HX-Request')) {
$accounts = $this->bankAccountService->getAccounts($request->all(), $request->integer('per_page', 15));
+
return response(view('finance.accounts.partials.table', compact('accounts')));
}
@@ -212,6 +213,7 @@ public function forceDelete(Request $request, int $id): JsonResponse|Response
// HTMX 요청인 경우 갱신된 테이블 반환
if ($request->header('HX-Request')) {
$accounts = $this->bankAccountService->getAccounts($request->all(), $request->integer('per_page', 15));
+
return response(view('finance.accounts.partials.table', compact('accounts')));
}
@@ -240,6 +242,7 @@ public function toggleActive(Request $request, int $id): JsonResponse|Response
// HTMX 요청인 경우 갱신된 테이블 반환
if ($request->header('HX-Request')) {
$accounts = $this->bankAccountService->getAccounts($request->all(), $request->integer('per_page', 15));
+
return response(view('finance.accounts.partials.table', compact('accounts')));
}
diff --git a/app/Http/Controllers/Api/Admin/Barobill/BarobillBillingController.php b/app/Http/Controllers/Api/Admin/Barobill/BarobillBillingController.php
index 70479c97..19267748 100644
--- a/app/Http/Controllers/Api/Admin/Barobill/BarobillBillingController.php
+++ b/app/Http/Controllers/Api/Admin/Barobill/BarobillBillingController.php
@@ -42,7 +42,7 @@ public function subscriptions(Request $request): JsonResponse|Response
->orderBy('service_type');
// 테넌트 필터링
- if (!$isHeadquarters && !$allTenants) {
+ if (! $isHeadquarters && ! $allTenants) {
$query->whereHas('member', function ($q) use ($tenantId) {
$q->where('tenant_id', $tenantId);
});
@@ -102,7 +102,7 @@ public function cancelSubscription(int $id): JsonResponse
{
$result = $this->billingService->cancelSubscription($id);
- if (!$result) {
+ if (! $result) {
return response()->json([
'success' => false,
'message' => '구독을 찾을 수 없습니다.',
@@ -121,7 +121,7 @@ public function cancelSubscription(int $id): JsonResponse
public function memberSubscriptions(int $memberId): JsonResponse|Response
{
$member = BarobillMember::with('tenant')->find($memberId);
- if (!$member) {
+ if (! $member) {
return response()->json([
'success' => false,
'message' => '회원사를 찾을 수 없습니다.',
@@ -157,7 +157,7 @@ public function billingList(Request $request): JsonResponse|Response
$billingMonth = $request->input('billing_month', now()->format('Y-m'));
// 테넌트 필터링
- $filterTenantId = (!$isHeadquarters && !$allTenants) ? $tenantId : null;
+ $filterTenantId = (! $isHeadquarters && ! $allTenants) ? $tenantId : null;
$summaries = BarobillMonthlySummary::with(['member.tenant'])
->where('billing_month', $billingMonth)
@@ -202,7 +202,7 @@ public function billingStats(Request $request): JsonResponse|Response
$billingMonth = $request->input('billing_month', now()->format('Y-m'));
- $filterTenantId = (!$isHeadquarters && !$allTenants) ? $tenantId : null;
+ $filterTenantId = (! $isHeadquarters && ! $allTenants) ? $tenantId : null;
$stats = $this->billingService->getMonthlyTotal($billingMonth, $filterTenantId);
if ($request->header('HX-Request')) {
@@ -225,7 +225,7 @@ public function billingStats(Request $request): JsonResponse|Response
public function memberBilling(Request $request, int $memberId): JsonResponse|Response
{
$member = BarobillMember::with('tenant')->find($memberId);
- if (!$member) {
+ if (! $member) {
return response()->json([
'success' => false,
'message' => '회원사를 찾을 수 없습니다.',
@@ -293,7 +293,7 @@ public function yearlyTrend(Request $request): JsonResponse
$year = $request->input('year', now()->year);
- $filterTenantId = (!$isHeadquarters && !$allTenants) ? $tenantId : null;
+ $filterTenantId = (! $isHeadquarters && ! $allTenants) ? $tenantId : null;
$trend = $this->billingService->getYearlyTrend($year, $filterTenantId);
return response()->json([
@@ -313,7 +313,7 @@ public function export(Request $request)
$billingMonth = $request->input('billing_month', now()->format('Y-m'));
- $filterTenantId = (!$isHeadquarters && !$allTenants) ? $tenantId : null;
+ $filterTenantId = (! $isHeadquarters && ! $allTenants) ? $tenantId : null;
$summaries = BarobillMonthlySummary::with(['member.tenant'])
->where('billing_month', $billingMonth)
@@ -336,7 +336,7 @@ public function export(Request $request)
$callback = function () use ($summaries, $total, $isHeadquarters, $allTenants) {
$file = fopen('php://output', 'w');
- fprintf($file, chr(0xEF) . chr(0xBB) . chr(0xBF));
+ fprintf($file, chr(0xEF).chr(0xBB).chr(0xBF));
// 헤더
$headerRow = ['사업자번호', '상호', '계좌조회', '카드내역', '홈텍스', '월정액합계', '세금계산서(건)', '세금계산서(원)', '건별합계', '총합계'];
@@ -411,7 +411,7 @@ public function pricingPolicies(Request $request): JsonResponse|Response
public function updatePricingPolicy(Request $request, int $id): JsonResponse
{
$policy = BarobillPricingPolicy::find($id);
- if (!$policy) {
+ if (! $policy) {
return response()->json([
'success' => false,
'message' => '정책을 찾을 수 없습니다.',
@@ -444,7 +444,7 @@ public function updatePricingPolicy(Request $request, int $id): JsonResponse
public function getPricingPolicy(int $id): JsonResponse
{
$policy = BarobillPricingPolicy::find($id);
- if (!$policy) {
+ if (! $policy) {
return response()->json([
'success' => false,
'message' => '정책을 찾을 수 없습니다.',
diff --git a/app/Http/Controllers/Api/Admin/Barobill/BarobillConfigController.php b/app/Http/Controllers/Api/Admin/Barobill/BarobillConfigController.php
index f002493f..044e9bf2 100644
--- a/app/Http/Controllers/Api/Admin/Barobill/BarobillConfigController.php
+++ b/app/Http/Controllers/Api/Admin/Barobill/BarobillConfigController.php
@@ -94,7 +94,7 @@ public function show(int $id): JsonResponse
{
$config = BarobillConfig::find($id);
- if (!$config) {
+ if (! $config) {
return response()->json([
'success' => false,
'message' => '설정을 찾을 수 없습니다.',
@@ -114,7 +114,7 @@ public function update(Request $request, int $id): JsonResponse
{
$config = BarobillConfig::find($id);
- if (!$config) {
+ if (! $config) {
return response()->json([
'success' => false,
'message' => '설정을 찾을 수 없습니다.',
@@ -167,7 +167,7 @@ public function destroy(int $id): JsonResponse
{
$config = BarobillConfig::find($id);
- if (!$config) {
+ if (! $config) {
return response()->json([
'success' => false,
'message' => '설정을 찾을 수 없습니다.',
@@ -196,7 +196,7 @@ public function toggleActive(int $id): JsonResponse
{
$config = BarobillConfig::find($id);
- if (!$config) {
+ if (! $config) {
return response()->json([
'success' => false,
'message' => '설정을 찾을 수 없습니다.',
@@ -205,14 +205,14 @@ public function toggleActive(int $id): JsonResponse
DB::beginTransaction();
try {
- if (!$config->is_active) {
+ if (! $config->is_active) {
// 활성화하려면 같은 환경의 다른 설정들 비활성화
BarobillConfig::where('environment', $config->environment)
->where('id', '!=', $id)
->update(['is_active' => false]);
}
- $config->update(['is_active' => !$config->is_active]);
+ $config->update(['is_active' => ! $config->is_active]);
DB::commit();
@@ -231,5 +231,4 @@ public function toggleActive(int $id): JsonResponse
], 500);
}
}
-
}
diff --git a/app/Http/Controllers/Api/Admin/Barobill/BarobillSettingController.php b/app/Http/Controllers/Api/Admin/Barobill/BarobillSettingController.php
index a33cbe0e..fa0f7544 100644
--- a/app/Http/Controllers/Api/Admin/Barobill/BarobillSettingController.php
+++ b/app/Http/Controllers/Api/Admin/Barobill/BarobillSettingController.php
@@ -25,7 +25,7 @@ public function show(): JsonResponse
// 바로빌 회원사 정보 조회 (담당자 정보 기본값용)
$barobillMember = BarobillMember::where('tenant_id', $tenantId)->first();
- if (!$setting) {
+ if (! $setting) {
// 설정이 없으면 바로빌 회원사 정보를 기본값으로 사용
return response()->json([
'success' => true,
@@ -158,7 +158,7 @@ public function checkService(string $service): JsonResponse
$setting = BarobillSetting::where('tenant_id', $tenantId)->first();
- if (!$setting) {
+ if (! $setting) {
return response()->json([
'success' => true,
'enabled' => false,
diff --git a/app/Http/Controllers/Api/Admin/Barobill/BarobillUsageController.php b/app/Http/Controllers/Api/Admin/Barobill/BarobillUsageController.php
index 8220f138..c14704b6 100644
--- a/app/Http/Controllers/Api/Admin/Barobill/BarobillUsageController.php
+++ b/app/Http/Controllers/Api/Admin/Barobill/BarobillUsageController.php
@@ -8,7 +8,6 @@
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
-use Illuminate\Support\Facades\Log;
/**
* 바로빌 사용량조회 API 컨트롤러
@@ -44,7 +43,7 @@ public function index(Request $request): JsonResponse|Response
$apiEndDate = str_replace('-', '', $endDate);
// 테넌트 필터링
- $filterTenantId = (!$isHeadquarters && !$allTenants && $tenantId) ? $tenantId : null;
+ $filterTenantId = (! $isHeadquarters && ! $allTenants && $tenantId) ? $tenantId : null;
// 사용량 목록 조회
$usageList = $this->usageService->getUsageList($apiStartDate, $apiEndDate, $filterTenantId);
@@ -117,7 +116,7 @@ public function stats(Request $request): JsonResponse|Response
$apiEndDate = str_replace('-', '', $endDate);
// 테넌트 필터링
- $filterTenantId = (!$isHeadquarters && !$allTenants && $tenantId) ? $tenantId : null;
+ $filterTenantId = (! $isHeadquarters && ! $allTenants && $tenantId) ? $tenantId : null;
// 사용량 목록 조회 및 통계 집계
$usageList = $this->usageService->getUsageList($apiStartDate, $apiEndDate, $filterTenantId);
@@ -145,7 +144,7 @@ public function show(Request $request, int $memberId): JsonResponse|Response
{
$member = BarobillMember::with('tenant:id,company_name')->find($memberId);
- if (!$member) {
+ if (! $member) {
return response()->json([
'success' => false,
'message' => '회원사를 찾을 수 없습니다.',
@@ -209,7 +208,7 @@ public function export(Request $request)
$apiEndDate = str_replace('-', '', $endDate);
// 테넌트 필터링
- $filterTenantId = (!$isHeadquarters && !$allTenants && $tenantId) ? $tenantId : null;
+ $filterTenantId = (! $isHeadquarters && ! $allTenants && $tenantId) ? $tenantId : null;
// 사용량 목록 조회
$usageList = $this->usageService->getUsageList($apiStartDate, $apiEndDate, $filterTenantId);
@@ -227,7 +226,7 @@ public function export(Request $request)
$file = fopen('php://output', 'w');
// BOM for Excel UTF-8
- fprintf($file, chr(0xEF) . chr(0xBB) . chr(0xBF));
+ fprintf($file, chr(0xEF).chr(0xBB).chr(0xBF));
// 헤더
$headerRow = ['사업자번호', '상호', '바로빌ID', '세금계산서(건)', '계좌조회(건)', '카드내역(건)', '홈텍스(건)', '과금액(원)'];
diff --git a/app/Http/Controllers/Api/Admin/CategoryApiController.php b/app/Http/Controllers/Api/Admin/CategoryApiController.php
index cfd5506f..cd948e65 100644
--- a/app/Http/Controllers/Api/Admin/CategoryApiController.php
+++ b/app/Http/Controllers/Api/Admin/CategoryApiController.php
@@ -335,4 +335,4 @@ public function reorder(Request $request): JsonResponse
], 500);
}
}
-}
\ No newline at end of file
+}
diff --git a/app/Http/Controllers/Api/Admin/DocumentApiController.php b/app/Http/Controllers/Api/Admin/DocumentApiController.php
index fa7d4f81..e0c88d58 100644
--- a/app/Http/Controllers/Api/Admin/DocumentApiController.php
+++ b/app/Http/Controllers/Api/Admin/DocumentApiController.php
@@ -236,7 +236,7 @@ public function destroy(int $id): JsonResponse
*/
public function forceDestroy(int $id): JsonResponse
{
- if (!auth()->user()?->is_super_admin) {
+ if (! auth()->user()?->is_super_admin) {
return response()->json([
'success' => false,
'message' => '슈퍼관리자만 영구 삭제할 수 있습니다.',
@@ -263,7 +263,7 @@ public function forceDestroy(int $id): JsonResponse
*/
public function restore(int $id): JsonResponse
{
- if (!auth()->user()?->is_super_admin) {
+ if (! auth()->user()?->is_super_admin) {
return response()->json([
'success' => false,
'message' => '슈퍼관리자만 복원할 수 있습니다.',
diff --git a/app/Http/Controllers/Api/Admin/DocumentTemplateApiController.php b/app/Http/Controllers/Api/Admin/DocumentTemplateApiController.php
index a05462c2..c417e28a 100644
--- a/app/Http/Controllers/Api/Admin/DocumentTemplateApiController.php
+++ b/app/Http/Controllers/Api/Admin/DocumentTemplateApiController.php
@@ -66,7 +66,7 @@ public function index(Request $request): View
}
// 활성 상태 필터
- if ($request->filled('is_active') && !$showTrashed) {
+ if ($request->filled('is_active') && ! $showTrashed) {
$query->where('is_active', $request->boolean('is_active'));
}
@@ -290,7 +290,7 @@ public function destroy(int $id): JsonResponse
*/
public function forceDestroy(int $id): JsonResponse
{
- if (!auth()->user()?->is_super_admin) {
+ if (! auth()->user()?->is_super_admin) {
return response()->json([
'success' => false,
'message' => '슈퍼관리자만 영구 삭제할 수 있습니다.',
@@ -337,7 +337,7 @@ public function forceDestroy(int $id): JsonResponse
*/
public function restore(int $id): JsonResponse
{
- if (!auth()->user()?->is_super_admin) {
+ if (! auth()->user()?->is_super_admin) {
return response()->json([
'success' => false,
'message' => '슈퍼관리자만 복원할 수 있습니다.',
@@ -535,7 +535,7 @@ public function uploadImage(Request $request): JsonResponse
}
// API 토큰 교환
- $tokenService = new \App\Services\ApiTokenService();
+ $tokenService = new \App\Services\ApiTokenService;
$userId = auth()->id();
$tenantId = session('selected_tenant_id', 1);
diff --git a/app/Http/Controllers/Api/Admin/FundScheduleController.php b/app/Http/Controllers/Api/Admin/FundScheduleController.php
index e962146f..c6ab9d47 100644
--- a/app/Http/Controllers/Api/Admin/FundScheduleController.php
+++ b/app/Http/Controllers/Api/Admin/FundScheduleController.php
@@ -182,6 +182,7 @@ public function destroy(Request $request, int $id): JsonResponse|Response
$month = $request->integer('month', now()->month);
$calendarData = $this->fundScheduleService->getCalendarData($year, $month);
$summary = $this->fundScheduleService->getMonthlySummary($year, $month);
+
return response(view('finance.fund-schedules.partials.calendar', compact('year', 'month', 'calendarData', 'summary')));
}
@@ -229,6 +230,7 @@ public function updateStatus(Request $request, int $id): JsonResponse|Response
$month = $request->integer('month', now()->month);
$calendarData = $this->fundScheduleService->getCalendarData($year, $month);
$summary = $this->fundScheduleService->getMonthlySummary($year, $month);
+
return response(view('finance.fund-schedules.partials.calendar', compact('year', 'month', 'calendarData', 'summary')));
}
diff --git a/app/Http/Controllers/Api/Admin/GlobalCategoryApiController.php b/app/Http/Controllers/Api/Admin/GlobalCategoryApiController.php
index 1acc24bd..e8f3f671 100644
--- a/app/Http/Controllers/Api/Admin/GlobalCategoryApiController.php
+++ b/app/Http/Controllers/Api/Admin/GlobalCategoryApiController.php
@@ -266,6 +266,7 @@ public function bulkCopyToTenant(Request $request): JsonResponse
if ($exists) {
$skipped++;
+
continue;
}
@@ -288,6 +289,7 @@ public function bulkCopyToTenant(Request $request): JsonResponse
]);
$idMap[$gc->id] = $trashed->id;
$copied++;
+
continue;
}
@@ -336,4 +338,4 @@ public function bulkCopyToTenant(Request $request): JsonResponse
], 500);
}
}
-}
\ No newline at end of file
+}
diff --git a/app/Http/Controllers/Api/Admin/TenantUserApiController.php b/app/Http/Controllers/Api/Admin/TenantUserApiController.php
index 02d1d437..abe88a72 100644
--- a/app/Http/Controllers/Api/Admin/TenantUserApiController.php
+++ b/app/Http/Controllers/Api/Admin/TenantUserApiController.php
@@ -23,7 +23,7 @@ public function search(Request $request): JsonResponse
->where('user_tenants.tenant_id', $tenantId)
->where('user_tenants.is_active', true);
})
- ->leftJoin('departments', function ($join) use ($tenantId) {
+ ->leftJoin('departments', function ($join) {
$join->on('departments.id', '=', DB::raw('(
SELECT du.department_id FROM department_user du
WHERE du.user_id = users.id AND du.is_primary = 1
diff --git a/app/Http/Controllers/AppVersionController.php b/app/Http/Controllers/AppVersionController.php
index cf06bfc3..5e8c0f96 100644
--- a/app/Http/Controllers/AppVersionController.php
+++ b/app/Http/Controllers/AppVersionController.php
@@ -6,8 +6,8 @@
use App\Services\AppVersionService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
-use Illuminate\View\View;
use Illuminate\Support\Facades\Storage;
+use Illuminate\View\View;
use Symfony\Component\HttpFoundation\StreamedResponse;
class AppVersionController extends Controller
diff --git a/app/Http/Controllers/Barobill/BarobillController.php b/app/Http/Controllers/Barobill/BarobillController.php
index ae665a7a..aeb61658 100644
--- a/app/Http/Controllers/Barobill/BarobillController.php
+++ b/app/Http/Controllers/Barobill/BarobillController.php
@@ -77,9 +77,9 @@ public function settings(Request $request): View|Response
$hasBarobillLogin = false;
if ($barobillMember) {
try {
- $hasBarobillLogin = !empty($barobillMember->barobill_id) && !empty($barobillMember->barobill_pwd);
+ $hasBarobillLogin = ! empty($barobillMember->barobill_id) && ! empty($barobillMember->barobill_pwd);
} catch (\Throwable $e) {
- $hasBarobillLogin = !empty($barobillMember->barobill_id) && !empty($barobillMember->getRawOriginal('barobill_pwd'));
+ $hasBarobillLogin = ! empty($barobillMember->barobill_id) && ! empty($barobillMember->getRawOriginal('barobill_pwd'));
}
}
@@ -179,8 +179,8 @@ public function searchTradingPartners(Request $request): JsonResponse
if ($keyword) {
$query->where(function ($q) use ($keyword) {
$q->where('name', 'like', "%{$keyword}%")
- ->orWhere('biz_no', 'like', "%{$keyword}%")
- ->orWhere('manager', 'like', "%{$keyword}%");
+ ->orWhere('biz_no', 'like', "%{$keyword}%")
+ ->orWhere('manager', 'like', "%{$keyword}%");
});
}
diff --git a/app/Http/Controllers/Barobill/EtaxController.php b/app/Http/Controllers/Barobill/EtaxController.php
index 976f9b2e..3ea549c3 100644
--- a/app/Http/Controllers/Barobill/EtaxController.php
+++ b/app/Http/Controllers/Barobill/EtaxController.php
@@ -21,9 +21,13 @@ class EtaxController extends Controller
* 바로빌 SOAP 설정
*/
private ?string $certKey = null;
+
private ?string $corpNum = null;
+
private bool $isTestMode = false;
+
private ?string $soapUrl = null;
+
private ?\SoapClient $soapClient = null;
public function __construct()
@@ -35,7 +39,7 @@ public function __construct()
$this->certKey = $activeConfig->cert_key;
$this->corpNum = $activeConfig->corp_num;
$this->isTestMode = $activeConfig->environment === 'test';
- $this->soapUrl = $activeConfig->base_url . '/TI.asmx?WSDL';
+ $this->soapUrl = $activeConfig->base_url.'/TI.asmx?WSDL';
} else {
// 설정이 없으면 기본값 사용
$this->isTestMode = config('services.barobill.test_mode', true);
@@ -57,14 +61,14 @@ public function __construct()
*/
private function initSoapClient(): void
{
- if (!empty($this->certKey) || $this->isTestMode) {
+ if (! empty($this->certKey) || $this->isTestMode) {
try {
$context = stream_context_create([
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
- 'allow_self_signed' => true
- ]
+ 'allow_self_signed' => true,
+ ],
]);
$this->soapClient = new \SoapClient($this->soapUrl, [
@@ -73,10 +77,10 @@ private function initSoapClient(): void
'exceptions' => true,
'connection_timeout' => 30,
'stream_context' => $context,
- 'cache_wsdl' => WSDL_CACHE_NONE
+ 'cache_wsdl' => WSDL_CACHE_NONE,
]);
} catch (\Throwable $e) {
- Log::error('바로빌 SOAP 클라이언트 생성 실패: ' . $e->getMessage());
+ Log::error('바로빌 SOAP 클라이언트 생성 실패: '.$e->getMessage());
}
}
}
@@ -135,14 +139,14 @@ private function applyMemberServerMode(BarobillMember $member): void
$baseUrl = $config->base_url ?: ($memberTestMode
? 'https://testws.baroservice.com'
: 'https://ws.baroservice.com');
- $this->soapUrl = $baseUrl . '/TI.asmx?WSDL';
+ $this->soapUrl = $baseUrl.'/TI.asmx?WSDL';
// SOAP 클라이언트 재초기화
$this->initSoapClient();
Log::info('[Etax] 서버 모드 적용', [
'targetEnv' => $targetEnv,
- 'certKey' => substr($this->certKey ?? '', 0, 10) . '...',
+ 'certKey' => substr($this->certKey ?? '', 0, 10).'...',
'corpNum' => $this->corpNum,
'soapUrl' => $this->soapUrl,
]);
@@ -173,7 +177,7 @@ public function getInvoices(): JsonResponse
$allInvoices = $data['invoices'] ?? [];
// 본사(테넌트 1)가 아니면 해당 테넌트의 세금계산서만 필터링
- if (!$isHeadquarters && $tenantId) {
+ if (! $isHeadquarters && $tenantId) {
$invoices = array_values(array_filter($allInvoices, function ($invoice) use ($tenantId) {
return ($invoice['tenant_id'] ?? null) == $tenantId;
}));
@@ -204,12 +208,12 @@ public function issue(Request $request): JsonResponse
$input = $request->all();
- $useRealAPI = $this->soapClient !== null && ($this->isTestMode || !empty($this->certKey));
+ $useRealAPI = $this->soapClient !== null && ($this->isTestMode || ! empty($this->certKey));
$debugInfo = [
'hasSoapClient' => $this->soapClient !== null,
- 'hasCertKey' => !empty($this->certKey),
- 'hasCorpNum' => !empty($this->corpNum),
+ 'hasCertKey' => ! empty($this->certKey),
+ 'hasCorpNum' => ! empty($this->corpNum),
'isTestMode' => $this->isTestMode,
'willUseRealAPI' => $useRealAPI,
];
@@ -218,7 +222,7 @@ public function issue(Request $request): JsonResponse
$apiResult = $this->issueTaxInvoice($input);
if ($apiResult['success']) {
- $mgtKey = $input['issueKey'] ?? 'MGT' . date('YmdHis') . rand(1000, 9999);
+ $mgtKey = $input['issueKey'] ?? 'MGT'.date('YmdHis').rand(1000, 9999);
$newInvoice = $this->createInvoiceRecord($input, $mgtKey, $apiResult['data'] ?? null);
$this->saveInvoice($newInvoice);
@@ -245,7 +249,7 @@ public function issue(Request $request): JsonResponse
}
} else {
// 시뮬레이션 모드
- $issueKey = 'BARO-' . date('Y') . '-' . str_pad(rand(1, 9999), 4, '0', STR_PAD_LEFT);
+ $issueKey = 'BARO-'.date('Y').'-'.str_pad(rand(1, 9999), 4, '0', STR_PAD_LEFT);
$newInvoice = $this->createInvoiceRecord($input, $issueKey, null);
$this->saveInvoice($newInvoice);
@@ -293,16 +297,16 @@ public function sendToNts(Request $request): JsonResponse
}
}
- if (!$invoice) {
+ if (! $invoice) {
return response()->json([
'success' => false,
'error' => '세금계산서를 찾을 수 없습니다.',
], 404);
}
- $useRealAPI = $this->soapClient !== null && !empty($this->certKey);
+ $useRealAPI = $this->soapClient !== null && ! empty($this->certKey);
- if ($useRealAPI && !empty($invoice['mgtKey'])) {
+ if ($useRealAPI && ! empty($invoice['mgtKey'])) {
$result = $this->callBarobillSOAP('SendToNTS', [
'CorpNum' => $this->corpNum,
'MgtKey' => $invoice['mgtKey'],
@@ -310,7 +314,7 @@ public function sendToNts(Request $request): JsonResponse
if ($result['success']) {
$data['invoices'][$invoiceIndex]['status'] = 'sent';
- $data['invoices'][$invoiceIndex]['ntsReceiptNo'] = 'NTS-' . date('YmdHis');
+ $data['invoices'][$invoiceIndex]['ntsReceiptNo'] = 'NTS-'.date('YmdHis');
$data['invoices'][$invoiceIndex]['sentAt'] = date('Y-m-d');
file_put_contents($dataFile, json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
@@ -327,7 +331,7 @@ public function sendToNts(Request $request): JsonResponse
} else {
// 시뮬레이션
$data['invoices'][$invoiceIndex]['status'] = 'sent';
- $data['invoices'][$invoiceIndex]['ntsReceiptNo'] = 'NTS-SIM-' . date('YmdHis');
+ $data['invoices'][$invoiceIndex]['ntsReceiptNo'] = 'NTS-SIM-'.date('YmdHis');
$data['invoices'][$invoiceIndex]['sentAt'] = date('Y-m-d');
file_put_contents($dataFile, json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
@@ -345,12 +349,12 @@ public function sendToNts(Request $request): JsonResponse
public function getSupplier(): JsonResponse
{
$tenantId = session('selected_tenant_id');
- if (!$tenantId) {
+ if (! $tenantId) {
return response()->json(['success' => false, 'error' => '테넌트가 선택되지 않았습니다.'], 400);
}
$member = BarobillMember::where('tenant_id', $tenantId)->first();
- if (!$member) {
+ if (! $member) {
return response()->json(['success' => false, 'error' => '바로빌 회원사 정보가 없습니다.'], 404);
}
@@ -376,12 +380,12 @@ public function getSupplier(): JsonResponse
public function updateSupplier(Request $request): JsonResponse
{
$tenantId = session('selected_tenant_id');
- if (!$tenantId) {
+ if (! $tenantId) {
return response()->json(['success' => false, 'error' => '테넌트가 선택되지 않았습니다.'], 400);
}
$member = BarobillMember::where('tenant_id', $tenantId)->first();
- if (!$member) {
+ if (! $member) {
return response()->json(['success' => false, 'error' => '바로빌 회원사 정보가 없습니다.'], 404);
}
@@ -424,7 +428,7 @@ public function delete(Request $request): JsonResponse
$dataFile = storage_path('app/barobill/invoices_data.json');
- if (!file_exists($dataFile)) {
+ if (! file_exists($dataFile)) {
return response()->json([
'success' => false,
'error' => '데이터 파일이 없습니다.',
@@ -434,7 +438,7 @@ public function delete(Request $request): JsonResponse
$data = json_decode(file_get_contents($dataFile), true) ?? ['invoices' => []];
$originalCount = count($data['invoices']);
- $data['invoices'] = array_values(array_filter($data['invoices'], fn($inv) => $inv['id'] !== $invoiceId));
+ $data['invoices'] = array_values(array_filter($data['invoices'], fn ($inv) => $inv['id'] !== $invoiceId));
if (count($data['invoices']) === $originalCount) {
return response()->json([
@@ -456,20 +460,20 @@ public function delete(Request $request): JsonResponse
*/
private function callBarobillSOAP(string $method, array $params = []): array
{
- if (!$this->soapClient) {
+ if (! $this->soapClient) {
return [
'success' => false,
'error' => '바로빌 SOAP 클라이언트가 초기화되지 않았습니다.',
];
}
- if (!isset($params['CERTKEY'])) {
+ if (! isset($params['CERTKEY'])) {
$params['CERTKEY'] = $this->certKey;
}
try {
$result = $this->soapClient->$method($params);
- $resultProperty = $method . 'Result';
+ $resultProperty = $method.'Result';
if (isset($result->$resultProperty)) {
$resultData = $result->$resultProperty;
@@ -477,7 +481,7 @@ private function callBarobillSOAP(string $method, array $params = []): array
if (is_numeric($resultData) && $resultData < 0) {
return [
'success' => false,
- 'error' => '바로빌 API 오류 코드: ' . $resultData,
+ 'error' => '바로빌 API 오류 코드: '.$resultData,
'error_code' => $resultData,
];
}
@@ -495,12 +499,12 @@ private function callBarobillSOAP(string $method, array $params = []): array
} catch (\SoapFault $e) {
return [
'success' => false,
- 'error' => 'SOAP 오류: ' . $e->getMessage(),
+ 'error' => 'SOAP 오류: '.$e->getMessage(),
];
} catch (\Throwable $e) {
return [
'success' => false,
- 'error' => 'API 호출 오류: ' . $e->getMessage(),
+ 'error' => 'API 호출 오류: '.$e->getMessage(),
];
}
}
@@ -510,7 +514,7 @@ private function callBarobillSOAP(string $method, array $params = []): array
*/
private function issueTaxInvoice(array $invoiceData): array
{
- $mgtKey = $invoiceData['issueKey'] ?? 'MGT' . date('YmdHis') . rand(1000, 9999);
+ $mgtKey = $invoiceData['issueKey'] ?? 'MGT'.date('YmdHis').rand(1000, 9999);
$supplyAmt = 0;
$vat = 0;
@@ -583,7 +587,7 @@ private function issueTaxInvoice(array $invoiceData): array
$month = str_pad($item['month'] ?? '', 2, '0', STR_PAD_LEFT);
$day = str_pad($item['day'] ?? '', 2, '0', STR_PAD_LEFT);
$purchaseExpiry = ($month && $day && $month !== '00' && $day !== '00')
- ? $year . $month . $day
+ ? $year.$month.$day
: '';
$taxInvoice['TaxInvoiceTradeLineItems']['TaxInvoiceTradeLineItem'][] = [
@@ -613,7 +617,7 @@ private function issueTaxInvoice(array $invoiceData): array
private function createInvoiceRecord(array $input, string $issueKey, $apiData): array
{
return [
- 'id' => 'inv_' . time() . '_' . rand(1000, 9999),
+ 'id' => 'inv_'.time().'_'.rand(1000, 9999),
'tenant_id' => session('selected_tenant_id'), // 테넌트별 필터링용
'issueKey' => $issueKey,
'mgtKey' => $issueKey,
@@ -638,7 +642,7 @@ private function createInvoiceRecord(array $input, string $issueKey, $apiData):
'memo' => $input['memo'] ?? '',
'createdAt' => date('Y-m-d\TH:i:s'),
'sentAt' => date('Y-m-d'),
- 'barobillInvoiceId' => is_numeric($apiData) ? (string)$apiData : '',
+ 'barobillInvoiceId' => is_numeric($apiData) ? (string) $apiData : '',
];
}
@@ -648,11 +652,11 @@ private function createInvoiceRecord(array $input, string $issueKey, $apiData):
private function saveInvoice(array $invoice): bool
{
$dataDir = storage_path('app/barobill');
- if (!is_dir($dataDir)) {
+ if (! is_dir($dataDir)) {
mkdir($dataDir, 0755, true);
}
- $dataFile = $dataDir . '/invoices_data.json';
+ $dataFile = $dataDir.'/invoices_data.json';
$existingData = ['invoices' => []];
if (file_exists($dataFile)) {
diff --git a/app/Http/Controllers/Barobill/HometaxController.php b/app/Http/Controllers/Barobill/HometaxController.php
index 139547a8..fdbdea3f 100644
--- a/app/Http/Controllers/Barobill/HometaxController.php
+++ b/app/Http/Controllers/Barobill/HometaxController.php
@@ -14,7 +14,6 @@
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\DB;
-use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View;
use Symfony\Component\HttpFoundation\StreamedResponse;
@@ -32,9 +31,13 @@ class HometaxController extends Controller
* 바로빌 설정
*/
private ?string $certKey = null;
+
private ?string $corpNum = null;
+
private bool $isTestMode = false;
+
private string $baseUrl = '';
+
private ?\SoapClient $soapClient = null;
// 바로빌 파트너사 (본사) 테넌트 ID
@@ -72,26 +75,26 @@ public function __construct()
*/
private function initSoapClient(): void
{
- if (!empty($this->certKey) || $this->isTestMode) {
+ if (! empty($this->certKey) || $this->isTestMode) {
try {
$context = stream_context_create([
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
- 'allow_self_signed' => true
- ]
+ 'allow_self_signed' => true,
+ ],
]);
- $this->soapClient = new \SoapClient($this->baseUrl . '/TI.asmx?WSDL', [
+ $this->soapClient = new \SoapClient($this->baseUrl.'/TI.asmx?WSDL', [
'trace' => true,
'encoding' => 'UTF-8',
'exceptions' => true,
'connection_timeout' => 30,
'stream_context' => $context,
- 'cache_wsdl' => WSDL_CACHE_NONE
+ 'cache_wsdl' => WSDL_CACHE_NONE,
]);
} catch (\Throwable $e) {
- Log::error('바로빌 홈택스 SOAP 클라이언트 생성 실패: ' . $e->getMessage());
+ Log::error('바로빌 홈택스 SOAP 클라이언트 생성 실패: '.$e->getMessage());
}
}
}
@@ -155,7 +158,7 @@ private function applyMemberServerMode(BarobillMember $member): void
Log::info('[Hometax] 서버 모드 적용', [
'targetEnv' => $targetEnv,
- 'certKey' => substr($this->certKey ?? '', 0, 10) . '...',
+ 'certKey' => substr($this->certKey ?? '', 0, 10).'...',
'corpNum' => $this->corpNum,
'baseUrl' => $this->baseUrl,
]);
@@ -177,19 +180,19 @@ public function sales(Request $request): JsonResponse
try {
$startDate = $request->input('startDate', date('Ymd', strtotime('-1 month')));
$endDate = $request->input('endDate', date('Ymd'));
- $page = (int)$request->input('page', 1);
- $limit = (int)$request->input('limit', 50);
- $taxType = (int)$request->input('taxType', 0); // 0:전체, 1:과세+영세, 3:면세
- $dateType = (int)$request->input('dateType', 1); // 1:작성일자, 2:발급일자, 3:전송일자
+ $page = (int) $request->input('page', 1);
+ $limit = (int) $request->input('limit', 50);
+ $taxType = (int) $request->input('taxType', 0); // 0:전체, 1:과세+영세, 3:면세
+ $dateType = (int) $request->input('dateType', 1); // 1:작성일자, 2:발급일자, 3:전송일자
// 현재 테넌트의 바로빌 회원 정보 조회
$tenantId = session('selected_tenant_id', self::HEADQUARTERS_TENANT_ID);
$barobillMember = BarobillMember::where('tenant_id', $tenantId)->first();
- if (!$barobillMember) {
+ if (! $barobillMember) {
return response()->json([
'success' => false,
- 'error' => '바로빌 회원사 정보가 없습니다. 테넌트 설정을 확인해주세요.'
+ 'error' => '바로빌 회원사 정보가 없습니다. 테넌트 설정을 확인해주세요.',
]);
}
@@ -203,7 +206,7 @@ public function sales(Request $request): JsonResponse
if (empty($userId)) {
return response()->json([
'success' => false,
- 'error' => '바로빌 사용자 ID가 설정되지 않았습니다.'
+ 'error' => '바로빌 사용자 ID가 설정되지 않았습니다.',
]);
}
@@ -221,18 +224,19 @@ public function sales(Request $request): JsonResponse
'StartDate' => $startDate,
'EndDate' => $endDate,
'CountPerPage' => $limit,
- 'CurrentPage' => $page
+ 'CurrentPage' => $page,
]);
- if (!$result['success']) {
+ if (! $result['success']) {
// 첫 번째 조회 실패 시 에러 반환
if (empty($allInvoices)) {
return response()->json([
'success' => false,
'error' => $result['error'],
- 'error_code' => $result['error_code'] ?? null
+ 'error_code' => $result['error_code'] ?? null,
]);
}
+
continue; // 이미 일부 데이터가 있으면 계속 진행
}
@@ -240,19 +244,20 @@ public function sales(Request $request): JsonResponse
$errorCode = $this->checkErrorCode($resultData);
// 에러 코드 체크 (데이터 없음 외의 에러)
- if ($errorCode && !in_array($errorCode, [-60005, -60001])) {
+ if ($errorCode && ! in_array($errorCode, [-60005, -60001])) {
if (empty($allInvoices)) {
return response()->json([
'success' => false,
'error' => $this->getErrorMessage($errorCode),
- 'error_code' => $errorCode
+ 'error_code' => $errorCode,
]);
}
+
continue;
}
// 데이터가 있는 경우 파싱
- if (!$errorCode || !in_array($errorCode, [-60005, -60001])) {
+ if (! $errorCode || ! in_array($errorCode, [-60005, -60001])) {
$parsed = $this->parseInvoices($resultData, 'sales');
$allInvoices = array_merge($allInvoices, $parsed['invoices']);
$totalSummary['totalAmount'] += $parsed['summary']['totalAmount'];
@@ -265,13 +270,13 @@ public function sales(Request $request): JsonResponse
'currentPage' => $resultData->CurrentPage ?? 1,
'countPerPage' => $resultData->CountPerPage ?? 50,
'maxPageNum' => $resultData->MaxPageNum ?? 1,
- 'maxIndex' => $resultData->MaxIndex ?? 0
+ 'maxIndex' => $resultData->MaxIndex ?? 0,
];
}
}
// 작성일 기준으로 정렬 (최신순)
- usort($allInvoices, fn($a, $b) => strcmp($b['writeDate'] ?? '', $a['writeDate'] ?? ''));
+ usort($allInvoices, fn ($a, $b) => strcmp($b['writeDate'] ?? '', $a['writeDate'] ?? ''));
// 마지막 매출 수집 시간 업데이트
$barobillMember->update(['last_sales_fetch_at' => now()]);
@@ -282,14 +287,15 @@ public function sales(Request $request): JsonResponse
'invoices' => $allInvoices,
'pagination' => $lastPagination,
'summary' => $totalSummary,
- 'lastFetchAt' => now()->format('Y-m-d H:i:s')
- ]
+ 'lastFetchAt' => now()->format('Y-m-d H:i:s'),
+ ],
]);
} catch (\Throwable $e) {
- Log::error('홈택스 매출 조회 오류: ' . $e->getMessage());
+ Log::error('홈택스 매출 조회 오류: '.$e->getMessage());
+
return response()->json([
'success' => false,
- 'error' => '서버 오류: ' . $e->getMessage()
+ 'error' => '서버 오류: '.$e->getMessage(),
]);
}
}
@@ -307,19 +313,19 @@ public function purchases(Request $request): JsonResponse
try {
$startDate = $request->input('startDate', date('Ymd', strtotime('-1 month')));
$endDate = $request->input('endDate', date('Ymd'));
- $page = (int)$request->input('page', 1);
- $limit = (int)$request->input('limit', 50);
- $taxType = (int)$request->input('taxType', 0); // 0:전체, 1:과세+영세, 3:면세
- $dateType = (int)$request->input('dateType', 1); // 1:작성일자, 2:발급일자, 3:전송일자
+ $page = (int) $request->input('page', 1);
+ $limit = (int) $request->input('limit', 50);
+ $taxType = (int) $request->input('taxType', 0); // 0:전체, 1:과세+영세, 3:면세
+ $dateType = (int) $request->input('dateType', 1); // 1:작성일자, 2:발급일자, 3:전송일자
// 현재 테넌트의 바로빌 회원 정보 조회
$tenantId = session('selected_tenant_id', self::HEADQUARTERS_TENANT_ID);
$barobillMember = BarobillMember::where('tenant_id', $tenantId)->first();
- if (!$barobillMember) {
+ if (! $barobillMember) {
return response()->json([
'success' => false,
- 'error' => '바로빌 회원사 정보가 없습니다. 테넌트 설정을 확인해주세요.'
+ 'error' => '바로빌 회원사 정보가 없습니다. 테넌트 설정을 확인해주세요.',
]);
}
@@ -333,7 +339,7 @@ public function purchases(Request $request): JsonResponse
if (empty($userId)) {
return response()->json([
'success' => false,
- 'error' => '바로빌 사용자 ID가 설정되지 않았습니다.'
+ 'error' => '바로빌 사용자 ID가 설정되지 않았습니다.',
]);
}
@@ -351,18 +357,19 @@ public function purchases(Request $request): JsonResponse
'StartDate' => $startDate,
'EndDate' => $endDate,
'CountPerPage' => $limit,
- 'CurrentPage' => $page
+ 'CurrentPage' => $page,
]);
- if (!$result['success']) {
+ if (! $result['success']) {
// 첫 번째 조회 실패 시 에러 반환
if (empty($allInvoices)) {
return response()->json([
'success' => false,
'error' => $result['error'],
- 'error_code' => $result['error_code'] ?? null
+ 'error_code' => $result['error_code'] ?? null,
]);
}
+
continue; // 이미 일부 데이터가 있으면 계속 진행
}
@@ -370,19 +377,20 @@ public function purchases(Request $request): JsonResponse
$errorCode = $this->checkErrorCode($resultData);
// 에러 코드 체크 (데이터 없음 외의 에러)
- if ($errorCode && !in_array($errorCode, [-60005, -60001])) {
+ if ($errorCode && ! in_array($errorCode, [-60005, -60001])) {
if (empty($allInvoices)) {
return response()->json([
'success' => false,
'error' => $this->getErrorMessage($errorCode),
- 'error_code' => $errorCode
+ 'error_code' => $errorCode,
]);
}
+
continue;
}
// 데이터가 있는 경우 파싱
- if (!$errorCode || !in_array($errorCode, [-60005, -60001])) {
+ if (! $errorCode || ! in_array($errorCode, [-60005, -60001])) {
$parsed = $this->parseInvoices($resultData, 'purchase');
$allInvoices = array_merge($allInvoices, $parsed['invoices']);
$totalSummary['totalAmount'] += $parsed['summary']['totalAmount'];
@@ -395,13 +403,13 @@ public function purchases(Request $request): JsonResponse
'currentPage' => $resultData->CurrentPage ?? 1,
'countPerPage' => $resultData->CountPerPage ?? 50,
'maxPageNum' => $resultData->MaxPageNum ?? 1,
- 'maxIndex' => $resultData->MaxIndex ?? 0
+ 'maxIndex' => $resultData->MaxIndex ?? 0,
];
}
}
// 작성일 기준으로 정렬 (최신순)
- usort($allInvoices, fn($a, $b) => strcmp($b['writeDate'] ?? '', $a['writeDate'] ?? ''));
+ usort($allInvoices, fn ($a, $b) => strcmp($b['writeDate'] ?? '', $a['writeDate'] ?? ''));
// 마지막 매입 수집 시간 업데이트
$barobillMember->update(['last_purchases_fetch_at' => now()]);
@@ -412,14 +420,15 @@ public function purchases(Request $request): JsonResponse
'invoices' => $allInvoices,
'pagination' => $lastPagination,
'summary' => $totalSummary,
- 'lastFetchAt' => now()->format('Y-m-d H:i:s')
- ]
+ 'lastFetchAt' => now()->format('Y-m-d H:i:s'),
+ ],
]);
} catch (\Throwable $e) {
- Log::error('홈택스 매입 조회 오류: ' . $e->getMessage());
+ Log::error('홈택스 매입 조회 오류: '.$e->getMessage());
+
return response()->json([
'success' => false,
- 'error' => '서버 오류: ' . $e->getMessage()
+ 'error' => '서버 오류: '.$e->getMessage(),
]);
}
}
@@ -435,24 +444,24 @@ public function getScrapRequestUrl(Request $request): JsonResponse
$tenantId = session('selected_tenant_id', self::HEADQUARTERS_TENANT_ID);
$barobillMember = BarobillMember::where('tenant_id', $tenantId)->first();
- if (!$barobillMember) {
+ if (! $barobillMember) {
return response()->json([
'success' => false,
- 'error' => '바로빌 회원사 정보가 없습니다.'
+ 'error' => '바로빌 회원사 정보가 없습니다.',
]);
}
$userId = $barobillMember->barobill_id ?? '';
$result = $this->callSoap('GetTaxInvoiceScrapRequestURL', [
- 'UserID' => $userId
+ 'UserID' => $userId,
]);
- if (!$result['success']) {
+ if (! $result['success']) {
return response()->json([
'success' => false,
'error' => $result['error'],
- 'error_code' => $result['error_code'] ?? null
+ 'error_code' => $result['error_code'] ?? null,
]);
}
@@ -461,7 +470,7 @@ public function getScrapRequestUrl(Request $request): JsonResponse
if (is_string($url) && filter_var($url, FILTER_VALIDATE_URL)) {
return response()->json([
'success' => true,
- 'data' => ['url' => $url]
+ 'data' => ['url' => $url],
]);
}
@@ -469,20 +478,21 @@ public function getScrapRequestUrl(Request $request): JsonResponse
if (is_numeric($url) && $url < 0) {
return response()->json([
'success' => false,
- 'error' => $this->getErrorMessage((int)$url),
- 'error_code' => (int)$url
+ 'error' => $this->getErrorMessage((int) $url),
+ 'error_code' => (int) $url,
]);
}
return response()->json([
'success' => true,
- 'data' => ['url' => (string)$url]
+ 'data' => ['url' => (string) $url],
]);
} catch (\Throwable $e) {
- Log::error('홈택스 스크래핑 URL 조회 오류: ' . $e->getMessage());
+ Log::error('홈택스 스크래핑 URL 조회 오류: '.$e->getMessage());
+
return response()->json([
'success' => false,
- 'error' => '서버 오류: ' . $e->getMessage()
+ 'error' => '서버 오류: '.$e->getMessage(),
]);
}
}
@@ -498,24 +508,24 @@ public function refreshScrap(Request $request): JsonResponse
$tenantId = session('selected_tenant_id', self::HEADQUARTERS_TENANT_ID);
$barobillMember = BarobillMember::where('tenant_id', $tenantId)->first();
- if (!$barobillMember) {
+ if (! $barobillMember) {
return response()->json([
'success' => false,
- 'error' => '바로빌 회원사 정보가 없습니다.'
+ 'error' => '바로빌 회원사 정보가 없습니다.',
]);
}
$userId = $barobillMember->barobill_id ?? '';
$result = $this->callSoap('RefreshTaxInvoiceScrap', [
- 'UserID' => $userId
+ 'UserID' => $userId,
]);
- if (!$result['success']) {
+ if (! $result['success']) {
return response()->json([
'success' => false,
'error' => $result['error'],
- 'error_code' => $result['error_code'] ?? null
+ 'error_code' => $result['error_code'] ?? null,
]);
}
@@ -524,25 +534,27 @@ public function refreshScrap(Request $request): JsonResponse
if ($code < 0) {
return response()->json([
'success' => false,
- 'error' => $this->getErrorMessage((int)$code),
- 'error_code' => (int)$code
+ 'error' => $this->getErrorMessage((int) $code),
+ 'error_code' => (int) $code,
]);
}
+
return response()->json([
'success' => true,
- 'message' => '홈택스 데이터 수집이 요청되었습니다. 잠시 후 다시 조회해주세요.'
+ 'message' => '홈택스 데이터 수집이 요청되었습니다. 잠시 후 다시 조회해주세요.',
]);
}
return response()->json([
'success' => true,
- 'message' => '홈택스 데이터 수집이 요청되었습니다.'
+ 'message' => '홈택스 데이터 수집이 요청되었습니다.',
]);
} catch (\Throwable $e) {
- Log::error('홈택스 스크래핑 갱신 오류: ' . $e->getMessage());
+ Log::error('홈택스 스크래핑 갱신 오류: '.$e->getMessage());
+
return response()->json([
'success' => false,
- 'error' => '서버 오류: ' . $e->getMessage()
+ 'error' => '서버 오류: '.$e->getMessage(),
]);
}
}
@@ -568,29 +580,29 @@ public function diagnose(Request $request): JsonResponse
$diagnostics = [
'config' => [
- 'certKey' => !empty($this->certKey) ? substr($this->certKey, 0, 8) . '...' : '미설정',
+ 'certKey' => ! empty($this->certKey) ? substr($this->certKey, 0, 8).'...' : '미설정',
'corpNum' => $this->corpNum ?? '미설정', // 파트너사 사업자번호 (API 인증용)
'isTestMode' => $this->isTestMode,
- 'baseUrl' => $this->baseUrl
+ 'baseUrl' => $this->baseUrl,
],
'member' => [
'userId' => $userId ?: '미설정', // 테넌트의 바로빌 ID (API 호출에 사용)
'bizNo' => $memberCorpNum ?: '미설정', // 테넌트 사업자번호 (참고용)
- 'corpName' => $barobillMember?->corp_name ?? '미설정'
+ 'corpName' => $barobillMember?->corp_name ?? '미설정',
],
- 'tests' => []
+ 'tests' => [],
];
// 테스트 1: 홈택스 스크래핑 URL 조회 (서비스 활성화 확인용)
$scrapUrlResult = $this->callSoap('GetTaxInvoiceScrapRequestURL', [
- 'UserID' => $userId
+ 'UserID' => $userId,
]);
$diagnostics['tests']['scrapRequestUrl'] = [
'method' => 'GetTaxInvoiceScrapRequestURL',
'success' => $scrapUrlResult['success'],
'result' => $scrapUrlResult['success']
? (is_string($scrapUrlResult['data']) ? '성공 (URL 반환)' : $scrapUrlResult['data'])
- : ($scrapUrlResult['error'] ?? '오류')
+ : ($scrapUrlResult['error'] ?? '오류'),
];
// 테스트 2: 매출 세금계산서 조회 (기간: 최근 1개월)
@@ -602,7 +614,7 @@ public function diagnose(Request $request): JsonResponse
'StartDate' => date('Ymd', strtotime('-1 month')),
'EndDate' => date('Ymd'),
'CountPerPage' => 1,
- 'CurrentPage' => 1
+ 'CurrentPage' => 1,
]);
$diagnostics['tests']['salesList'] = [
'method' => 'GetPeriodTaxInvoiceSalesList',
@@ -611,7 +623,7 @@ public function diagnose(Request $request): JsonResponse
? ($this->checkErrorCode($salesResult['data'])
? $this->getErrorMessage($this->checkErrorCode($salesResult['data']))
: '성공')
- : ($salesResult['error'] ?? '오류')
+ : ($salesResult['error'] ?? '오류'),
];
// 테스트 3: 잔액 조회 (기본 연결 및 인증 확인용)
@@ -621,20 +633,21 @@ public function diagnose(Request $request): JsonResponse
'success' => $balanceResult['success'],
'result' => $balanceResult['success']
? (is_numeric($balanceResult['data']) && $balanceResult['data'] >= 0
- ? '성공 (잔액: ' . number_format($balanceResult['data']) . '원)'
+ ? '성공 (잔액: '.number_format($balanceResult['data']).'원)'
: $balanceResult['data'])
- : ($balanceResult['error'] ?? '오류')
+ : ($balanceResult['error'] ?? '오류'),
];
return response()->json([
'success' => true,
- 'data' => $diagnostics
+ 'data' => $diagnostics,
]);
} catch (\Throwable $e) {
- Log::error('홈택스 서비스 진단 오류: ' . $e->getMessage());
+ Log::error('홈택스 서비스 진단 오류: '.$e->getMessage());
+
return response()->json([
'success' => false,
- 'error' => '서버 오류: ' . $e->getMessage()
+ 'error' => '서버 오류: '.$e->getMessage(),
]);
}
}
@@ -666,8 +679,8 @@ public function collectStatus(Request $request): JsonResponse
'purchaseLastCollectDate' => $purchasesLastFetch ? $purchasesLastFetch->format('Y-m-d H:i') : '',
'isCollecting' => false,
'collectStateText' => ($salesLastFetch || $purchasesLastFetch) ? '조회 완료' : '조회 전',
- 'message' => '매출/매입 탭을 클릭하면 데이터가 조회되고 수집 시간이 기록됩니다.'
- ]
+ 'message' => '매출/매입 탭을 클릭하면 데이터가 조회되고 수집 시간이 기록됩니다.',
+ ],
]);
}
@@ -714,8 +727,8 @@ private function parseInvoices($resultData, string $type = 'sales'): array
$writeDate = $this->getProperty($item, 'IssueDT', '');
}
$formattedDate = '';
- if (!empty($writeDate) && strlen($writeDate) >= 8) {
- $formattedDate = substr($writeDate, 0, 4) . '-' . substr($writeDate, 4, 2) . '-' . substr($writeDate, 6, 2);
+ if (! empty($writeDate) && strlen($writeDate) >= 8) {
+ $formattedDate = substr($writeDate, 0, 4).'-'.substr($writeDate, 4, 2).'-'.substr($writeDate, 6, 2);
}
// 과세유형 (int: 1=과세, 2=영세, 3=면세)
@@ -757,8 +770,8 @@ private function parseInvoices($resultData, string $type = 'sales'): array
'totalAmount' => $totalAmount,
'totalTax' => $totalTax,
'totalSum' => $totalAmount + $totalTax,
- 'count' => count($invoices)
- ]
+ 'count' => count($invoices),
+ ],
];
}
@@ -768,8 +781,9 @@ private function parseInvoices($resultData, string $type = 'sales'): array
private function checkErrorCode($data): ?int
{
if (isset($data->CurrentPage) && is_numeric($data->CurrentPage) && $data->CurrentPage < 0) {
- return (int)$data->CurrentPage;
+ return (int) $data->CurrentPage;
}
+
return null;
}
@@ -794,7 +808,8 @@ private function getErrorMessage(int $errorCode): string
-60010 => '홈택스 로그인 실패 (-60010). 부서사용자 ID/비밀번호를 확인해주세요.',
-60011 => '홈택스 데이터 수집 중입니다 (-60011). 잠시 후 다시 조회해주세요.',
];
- return $messages[$errorCode] ?? '바로빌 API 오류: ' . $errorCode;
+
+ return $messages[$errorCode] ?? '바로빌 API 오류: '.$errorCode;
}
/**
@@ -802,7 +817,7 @@ private function getErrorMessage(int $errorCode): string
*/
private function getCollectTypeCode(string $type): int
{
- return match($type) {
+ return match ($type) {
'sales' => 1,
'purchase' => 2,
default => 0 // all
@@ -814,8 +829,9 @@ private function getCollectTypeCode(string $type): int
*/
private function getTaxTypeName(mixed $code): string
{
- $code = (string)$code;
- return match($code) {
+ $code = (string) $code;
+
+ return match ($code) {
'1', '01' => '과세',
'2', '02' => '영세',
'3', '03' => '면세',
@@ -828,8 +844,9 @@ private function getTaxTypeName(mixed $code): string
*/
private function getIssueTypeName(mixed $code): string
{
- $code = (string)$code;
- return match($code) {
+ $code = (string) $code;
+
+ return match ($code) {
'1', '01' => '정발행',
'2', '02' => '역발행',
'3', '03' => '위수탁',
@@ -842,8 +859,9 @@ private function getIssueTypeName(mixed $code): string
*/
private function getPurposeTypeName(mixed $code): string
{
- $code = (string)$code;
- return match($code) {
+ $code = (string) $code;
+
+ return match ($code) {
'1', '01' => '영수',
'2', '02' => '청구',
default => $code ?: '-'
@@ -875,29 +893,29 @@ public function exportExcel(Request $request): StreamedResponse|JsonResponse
if (empty($invoices)) {
return response()->json([
'success' => false,
- 'error' => '저장할 데이터가 없습니다.'
+ 'error' => '저장할 데이터가 없습니다.',
]);
}
$typeName = $type === 'sales' ? '매출' : '매입';
- $filename = "홈택스_{$typeName}_" . date('Ymd_His') . ".csv";
+ $filename = "홈택스_{$typeName}_".date('Ymd_His').'.csv';
return response()->streamDownload(function () use ($invoices, $type) {
$handle = fopen('php://output', 'w');
// UTF-8 BOM
- fprintf($handle, chr(0xEF) . chr(0xBB) . chr(0xBF));
+ fprintf($handle, chr(0xEF).chr(0xBB).chr(0xBF));
// 헤더
if ($type === 'sales') {
fputcsv($handle, [
'작성일', '국세청승인번호', '공급받는자 사업자번호', '공급받는자 상호',
- '공급가액', '세액', '합계', '과세유형', '발급유형', '영수/청구'
+ '공급가액', '세액', '합계', '과세유형', '발급유형', '영수/청구',
]);
} else {
fputcsv($handle, [
'작성일', '국세청승인번호', '공급자 사업자번호', '공급자 상호',
- '공급가액', '세액', '합계', '과세유형', '발급유형', '영수/청구'
+ '공급가액', '세액', '합계', '과세유형', '발급유형', '영수/청구',
]);
}
@@ -914,7 +932,7 @@ public function exportExcel(Request $request): StreamedResponse|JsonResponse
$inv['totalAmount'] ?? 0,
$inv['taxTypeName'] ?? '',
$inv['issueTypeName'] ?? '',
- $inv['purposeTypeName'] ?? ''
+ $inv['purposeTypeName'] ?? '',
]);
} else {
fputcsv($handle, [
@@ -927,7 +945,7 @@ public function exportExcel(Request $request): StreamedResponse|JsonResponse
$inv['totalAmount'] ?? 0,
$inv['taxTypeName'] ?? '',
$inv['issueTypeName'] ?? '',
- $inv['purposeTypeName'] ?? ''
+ $inv['purposeTypeName'] ?? '',
]);
}
}
@@ -935,13 +953,14 @@ public function exportExcel(Request $request): StreamedResponse|JsonResponse
fclose($handle);
}, $filename, [
'Content-Type' => 'text/csv; charset=utf-8',
- 'Content-Disposition' => 'attachment; filename="' . $filename . '"',
+ 'Content-Disposition' => 'attachment; filename="'.$filename.'"',
]);
} catch (\Throwable $e) {
- Log::error('홈택스 엑셀 다운로드 오류: ' . $e->getMessage());
+ Log::error('홈택스 엑셀 다운로드 오류: '.$e->getMessage());
+
return response()->json([
'success' => false,
- 'error' => '다운로드 오류: ' . $e->getMessage()
+ 'error' => '다운로드 오류: '.$e->getMessage(),
]);
}
}
@@ -951,32 +970,32 @@ public function exportExcel(Request $request): StreamedResponse|JsonResponse
*/
private function callSoap(string $method, array $params = []): array
{
- if (!$this->soapClient) {
+ if (! $this->soapClient) {
return [
'success' => false,
- 'error' => '바로빌 SOAP 클라이언트가 초기화되지 않았습니다.'
+ 'error' => '바로빌 SOAP 클라이언트가 초기화되지 않았습니다.',
];
}
- if (empty($this->certKey) && !$this->isTestMode) {
+ if (empty($this->certKey) && ! $this->isTestMode) {
return [
'success' => false,
- 'error' => 'CERTKEY가 설정되지 않았습니다.'
+ 'error' => 'CERTKEY가 설정되지 않았습니다.',
];
}
if (empty($this->corpNum)) {
return [
'success' => false,
- 'error' => '사업자번호가 설정되지 않았습니다.'
+ 'error' => '사업자번호가 설정되지 않았습니다.',
];
}
// CERTKEY와 CorpNum 자동 추가
- if (!isset($params['CERTKEY'])) {
+ if (! isset($params['CERTKEY'])) {
$params['CERTKEY'] = $this->certKey ?? '';
}
- if (!isset($params['CorpNum'])) {
+ if (! isset($params['CorpNum'])) {
$params['CorpNum'] = $this->corpNum;
}
@@ -984,18 +1003,18 @@ private function callSoap(string $method, array $params = []): array
// 날짜 파라미터 로깅 (디버깅용)
$dateInfo = '';
if (isset($params['StartDate']) || isset($params['EndDate'])) {
- $dateInfo = ", StartDate: " . ($params['StartDate'] ?? 'N/A') . ", EndDate: " . ($params['EndDate'] ?? 'N/A');
+ $dateInfo = ', StartDate: '.($params['StartDate'] ?? 'N/A').', EndDate: '.($params['EndDate'] ?? 'N/A');
}
- Log::info("바로빌 홈택스 API 호출 (SoapClient) - Method: {$method}, CorpNum: " . ($params['CorpNum'] ?? 'N/A') . ", UserID: " . ($params['UserID'] ?? 'N/A') . ", CERTKEY: " . substr($params['CERTKEY'] ?? '', 0, 10) . "..." . $dateInfo);
+ Log::info("바로빌 홈택스 API 호출 (SoapClient) - Method: {$method}, CorpNum: ".($params['CorpNum'] ?? 'N/A').', UserID: '.($params['UserID'] ?? 'N/A').', CERTKEY: '.substr($params['CERTKEY'] ?? '', 0, 10).'...'.$dateInfo);
// SoapClient로 호출
$result = $this->soapClient->$method($params);
- $resultProperty = $method . 'Result';
+ $resultProperty = $method.'Result';
- if (!isset($result->$resultProperty)) {
+ if (! isset($result->$resultProperty)) {
return [
'success' => false,
- 'error' => '응답 결과를 찾을 수 없습니다.'
+ 'error' => '응답 결과를 찾을 수 없습니다.',
];
}
@@ -1003,17 +1022,18 @@ private function callSoap(string $method, array $params = []): array
// 단순 숫자 응답인 경우 (에러 코드 또는 성공 코드)
if (is_numeric($resultData)) {
- $code = (int)$resultData;
+ $code = (int) $resultData;
if ($code < 0) {
return [
'success' => false,
'error' => $this->getErrorMessage($code),
- 'error_code' => $code
+ 'error_code' => $code,
];
}
+
return [
'success' => true,
- 'data' => $code
+ 'data' => $code,
];
}
@@ -1021,27 +1041,29 @@ private function callSoap(string $method, array $params = []): array
if (is_string($resultData)) {
return [
'success' => true,
- 'data' => $resultData
+ 'data' => $resultData,
];
}
// 객체 응답 (목록 조회 등)
return [
'success' => true,
- 'data' => $resultData
+ 'data' => $resultData,
];
} catch (\SoapFault $e) {
- Log::error('바로빌 SOAP 오류: ' . $e->getMessage());
+ Log::error('바로빌 SOAP 오류: '.$e->getMessage());
+
return [
'success' => false,
- 'error' => 'SOAP 오류: ' . $e->getMessage()
+ 'error' => 'SOAP 오류: '.$e->getMessage(),
];
} catch (\Throwable $e) {
- Log::error('바로빌 API 호출 오류: ' . $e->getMessage());
+ Log::error('바로빌 API 호출 오류: '.$e->getMessage());
+
return [
'success' => false,
- 'error' => 'API 호출 오류: ' . $e->getMessage()
+ 'error' => 'API 호출 오류: '.$e->getMessage(),
];
}
}
@@ -1053,15 +1075,15 @@ private function buildSoapRequest(string $method, array $params): string
{
$paramsXml = '';
foreach ($params as $key => $value) {
- $paramsXml .= "<{$key}>" . htmlspecialchars((string)$value, ENT_XML1, 'UTF-8') . "{$key}>";
+ $paramsXml .= "<{$key}>".htmlspecialchars((string) $value, ENT_XML1, 'UTF-8')."{$key}>";
}
return '
-
- ' . $paramsXml . '
-
+
+ '.$paramsXml.'
+
';
}
@@ -1077,7 +1099,7 @@ private function parseSoapResponse(string $xmlResponse, string $method): array
if ($xml === false) {
return [
'success' => false,
- 'error' => 'XML 파싱 실패'
+ 'error' => 'XML 파싱 실패',
];
}
@@ -1095,28 +1117,30 @@ private function parseSoapResponse(string $xmlResponse, string $method): array
if (empty($resultNodes)) {
Log::warning("응답에서 {$method}Result를 찾을 수 없음");
+
return [
'success' => false,
- 'error' => '응답 결과를 찾을 수 없습니다.'
+ 'error' => '응답 결과를 찾을 수 없습니다.',
];
}
$resultNode = $resultNodes[0];
// 단순 숫자 응답인 경우 (에러 코드)
- $textContent = trim((string)$resultNode);
+ $textContent = trim((string) $resultNode);
if (is_numeric($textContent) && $resultNode->count() === 0) {
- $code = (int)$textContent;
+ $code = (int) $textContent;
if ($code < 0) {
return [
'success' => false,
'error' => $this->getErrorMessage($code),
- 'error_code' => $code
+ 'error_code' => $code,
];
}
+
return [
'success' => true,
- 'data' => $code
+ 'data' => $code,
];
}
@@ -1125,14 +1149,15 @@ private function parseSoapResponse(string $xmlResponse, string $method): array
return [
'success' => true,
- 'data' => $resultData
+ 'data' => $resultData,
];
} catch (\Throwable $e) {
- Log::error('SOAP 응답 파싱 오류: ' . $e->getMessage());
+ Log::error('SOAP 응답 파싱 오류: '.$e->getMessage());
+
return [
'success' => false,
- 'error' => 'XML 파싱 오류: ' . $e->getMessage()
+ 'error' => 'XML 파싱 오류: '.$e->getMessage(),
];
}
}
@@ -1142,11 +1167,11 @@ private function parseSoapResponse(string $xmlResponse, string $method): array
*/
private function xmlToObject(\SimpleXMLElement $xml): object
{
- $result = new \stdClass();
+ $result = new \stdClass;
// 속성 처리
foreach ($xml->attributes() as $attrName => $attrValue) {
- $result->$attrName = (string)$attrValue;
+ $result->$attrName = (string) $attrValue;
}
// 자식 요소 처리
@@ -1160,20 +1185,20 @@ private function xmlToObject(\SimpleXMLElement $xml): object
foreach ($children as $name => $child) {
if ($childNames[$name] > 1) {
// 여러 개의 동일 이름 요소 → 배열
- if (!isset($result->$name)) {
+ if (! isset($result->$name)) {
$result->$name = [];
}
if ($child->count() > 0) {
$result->{$name}[] = $this->xmlToObject($child);
} else {
- $result->{$name}[] = (string)$child;
+ $result->{$name}[] = (string) $child;
}
- } else if ($child->count() > 0) {
+ } elseif ($child->count() > 0) {
// 자식이 있는 요소 → 재귀 호출
$result->$name = $this->xmlToObject($child);
} else {
// 텍스트 노드
- $result->$name = (string)$child;
+ $result->$name = (string) $child;
}
}
@@ -1193,10 +1218,10 @@ public function localSales(Request $request, HometaxSyncService $syncService): J
// YYYYMMDD 형식을 Y-m-d로 변환
if (strlen($startDate) === 8) {
- $startDate = substr($startDate, 0, 4) . '-' . substr($startDate, 4, 2) . '-' . substr($startDate, 6, 2);
+ $startDate = substr($startDate, 0, 4).'-'.substr($startDate, 4, 2).'-'.substr($startDate, 6, 2);
}
if (strlen($endDate) === 8) {
- $endDate = substr($endDate, 0, 4) . '-' . substr($endDate, 4, 2) . '-' . substr($endDate, 6, 2);
+ $endDate = substr($endDate, 0, 4).'-'.substr($endDate, 4, 2).'-'.substr($endDate, 6, 2);
}
$dateType = $request->input('dateType', 1) == 1 ? 'write' : 'issue';
@@ -1217,10 +1242,11 @@ public function localSales(Request $request, HometaxSyncService $syncService): J
'lastSyncAt' => $syncService->getLastSyncTime($tenantId, 'sales'),
]);
} catch (\Throwable $e) {
- Log::error('로컬 매출 조회 오류: ' . $e->getMessage());
+ Log::error('로컬 매출 조회 오류: '.$e->getMessage());
+
return response()->json([
'success' => false,
- 'error' => '조회 오류: ' . $e->getMessage()
+ 'error' => '조회 오류: '.$e->getMessage(),
]);
}
}
@@ -1238,10 +1264,10 @@ public function localPurchases(Request $request, HometaxSyncService $syncService
// YYYYMMDD 형식을 Y-m-d로 변환
if (strlen($startDate) === 8) {
- $startDate = substr($startDate, 0, 4) . '-' . substr($startDate, 4, 2) . '-' . substr($startDate, 6, 2);
+ $startDate = substr($startDate, 0, 4).'-'.substr($startDate, 4, 2).'-'.substr($startDate, 6, 2);
}
if (strlen($endDate) === 8) {
- $endDate = substr($endDate, 0, 4) . '-' . substr($endDate, 4, 2) . '-' . substr($endDate, 6, 2);
+ $endDate = substr($endDate, 0, 4).'-'.substr($endDate, 4, 2).'-'.substr($endDate, 6, 2);
}
$dateType = $request->input('dateType', 1) == 1 ? 'write' : 'issue';
@@ -1262,10 +1288,11 @@ public function localPurchases(Request $request, HometaxSyncService $syncService
'lastSyncAt' => $syncService->getLastSyncTime($tenantId, 'purchase'),
]);
} catch (\Throwable $e) {
- Log::error('로컬 매입 조회 오류: ' . $e->getMessage());
+ Log::error('로컬 매입 조회 오류: '.$e->getMessage());
+
return response()->json([
'success' => false,
- 'error' => '조회 오류: ' . $e->getMessage()
+ 'error' => '조회 오류: '.$e->getMessage(),
]);
}
}
@@ -1280,7 +1307,7 @@ public function sync(Request $request, HometaxSyncService $syncService): JsonRes
$type = $request->input('type', 'all'); // 'sales', 'purchase', 'all'
$startDate = $request->input('startDate', date('Ymd', strtotime('-1 month')));
$endDate = $request->input('endDate', date('Ymd'));
- $dateType = (int)$request->input('dateType', 1);
+ $dateType = (int) $request->input('dateType', 1);
$results = [];
@@ -1296,7 +1323,7 @@ public function sync(Request $request, HometaxSyncService $syncService): JsonRes
$salesResponse = $this->sales($salesRequest);
$salesData = json_decode($salesResponse->getContent(), true);
- if ($salesData['success'] && !empty($salesData['data']['invoices'])) {
+ if ($salesData['success'] && ! empty($salesData['data']['invoices'])) {
$results['sales'] = $syncService->syncInvoices(
$salesData['data']['invoices'],
$tenantId,
@@ -1325,7 +1352,7 @@ public function sync(Request $request, HometaxSyncService $syncService): JsonRes
$purchaseResponse = $this->purchases($purchaseRequest);
$purchaseData = json_decode($purchaseResponse->getContent(), true);
- if ($purchaseData['success'] && !empty($purchaseData['data']['invoices'])) {
+ if ($purchaseData['success'] && ! empty($purchaseData['data']['invoices'])) {
$results['purchase'] = $syncService->syncInvoices(
$purchaseData['data']['invoices'],
$tenantId,
@@ -1352,10 +1379,11 @@ public function sync(Request $request, HometaxSyncService $syncService): JsonRes
'data' => $results,
]);
} catch (\Throwable $e) {
- Log::error('홈택스 동기화 오류: ' . $e->getMessage());
+ Log::error('홈택스 동기화 오류: '.$e->getMessage());
+
return response()->json([
'success' => false,
- 'error' => '동기화 오류: ' . $e->getMessage()
+ 'error' => '동기화 오류: '.$e->getMessage(),
]);
}
}
@@ -1371,7 +1399,7 @@ public function autoSync(Request $request, HometaxSyncService $syncService): Jso
$type = $request->input('type', 'sales'); // 'sales' 또는 'purchase'
$barobillMember = BarobillMember::where('tenant_id', $tenantId)->first();
- if (!$barobillMember) {
+ if (! $barobillMember) {
return response()->json(['success' => true, 'skipped' => true, 'reason' => 'no_member']);
}
@@ -1411,7 +1439,7 @@ public function autoSync(Request $request, HometaxSyncService $syncService): Jso
$syncResult = ['inserted' => 0, 'updated' => 0, 'total' => 0];
- if ($apiData['success'] && !empty($apiData['data']['invoices'])) {
+ if ($apiData['success'] && ! empty($apiData['data']['invoices'])) {
$syncResult = $syncService->syncInvoices(
$apiData['data']['invoices'],
$tenantId,
@@ -1428,7 +1456,8 @@ public function autoSync(Request $request, HometaxSyncService $syncService): Jso
'lastFetchAt' => now()->format('Y-m-d H:i:s'),
]);
} catch (\Throwable $e) {
- Log::error('홈택스 자동동기화 오류: ' . $e->getMessage());
+ Log::error('홈택스 자동동기화 오류: '.$e->getMessage());
+
// 자동동기화 실패는 치명적이지 않음 - 로컬 데이터는 정상 표시됨
return response()->json([
'success' => true,
@@ -1458,7 +1487,7 @@ public function updateMemo(Request $request, HometaxSyncService $syncService): J
} catch (\Throwable $e) {
return response()->json([
'success' => false,
- 'error' => '오류: ' . $e->getMessage()
+ 'error' => '오류: '.$e->getMessage(),
]);
}
}
@@ -1480,7 +1509,7 @@ public function toggleChecked(Request $request, HometaxSyncService $syncService)
} catch (\Throwable $e) {
return response()->json([
'success' => false,
- 'error' => '오류: ' . $e->getMessage()
+ 'error' => '오류: '.$e->getMessage(),
]);
}
}
@@ -1542,12 +1571,12 @@ public function manualStore(Request $request): JsonResponse
$seq = 1;
if ($lastNum) {
$parts = explode('-', $lastNum);
- $seq = (int)end($parts) + 1;
+ $seq = (int) end($parts) + 1;
}
$ntsConfirmNum = sprintf('MAN-%s-%03d', $dateStr, $seq);
- $taxAmount = (float)($validated['tax_amount'] ?? 0);
- $totalAmount = (float)$validated['supply_amount'] + $taxAmount;
+ $taxAmount = (float) ($validated['tax_amount'] ?? 0);
+ $totalAmount = (float) $validated['supply_amount'] + $taxAmount;
$invoice = HometaxInvoice::create([
'tenant_id' => $tenantId,
@@ -1591,13 +1620,14 @@ public function manualStore(Request $request): JsonResponse
} catch (\Illuminate\Validation\ValidationException $e) {
return response()->json([
'success' => false,
- 'error' => '입력값 오류: ' . implode(', ', $e->validator->errors()->all()),
+ 'error' => '입력값 오류: '.implode(', ', $e->validator->errors()->all()),
], 422);
} catch (\Throwable $e) {
- Log::error('수동 세금계산서 저장 오류: ' . $e->getMessage());
+ Log::error('수동 세금계산서 저장 오류: '.$e->getMessage());
+
return response()->json([
'success' => false,
- 'error' => '저장 오류: ' . $e->getMessage(),
+ 'error' => '저장 오류: '.$e->getMessage(),
]);
}
}
@@ -1614,7 +1644,7 @@ public function manualUpdate(Request $request, int $id): JsonResponse
->where('tenant_id', $tenantId)
->firstOrFail();
- if (!str_starts_with($invoice->nts_confirm_num, 'MAN-')) {
+ if (! str_starts_with($invoice->nts_confirm_num, 'MAN-')) {
return response()->json([
'success' => false,
'error' => '수동 입력 건만 수정할 수 있습니다.',
@@ -1667,7 +1697,7 @@ public function manualUpdate(Request $request, int $id): JsonResponse
$supply = $validated['supply_amount'] ?? $invoice->supply_amount;
$tax = $validated['tax_amount'] ?? $invoice->tax_amount;
- $validated['total_amount'] = (float)$supply + (float)$tax;
+ $validated['total_amount'] = (float) $supply + (float) $tax;
$invoice->update($validated);
@@ -1682,10 +1712,11 @@ public function manualUpdate(Request $request, int $id): JsonResponse
'error' => '해당 세금계산서를 찾을 수 없습니다.',
], 404);
} catch (\Throwable $e) {
- Log::error('수동 세금계산서 수정 오류: ' . $e->getMessage());
+ Log::error('수동 세금계산서 수정 오류: '.$e->getMessage());
+
return response()->json([
'success' => false,
- 'error' => '수정 오류: ' . $e->getMessage(),
+ 'error' => '수정 오류: '.$e->getMessage(),
]);
}
}
@@ -1702,7 +1733,7 @@ public function manualDestroy(int $id): JsonResponse
->where('tenant_id', $tenantId)
->firstOrFail();
- if (!str_starts_with($invoice->nts_confirm_num, 'MAN-')) {
+ if (! str_starts_with($invoice->nts_confirm_num, 'MAN-')) {
return response()->json([
'success' => false,
'error' => '수동 입력 건만 삭제할 수 있습니다.',
@@ -1721,10 +1752,11 @@ public function manualDestroy(int $id): JsonResponse
'error' => '해당 세금계산서를 찾을 수 없습니다.',
], 404);
} catch (\Throwable $e) {
- Log::error('수동 세금계산서 삭제 오류: ' . $e->getMessage());
+ Log::error('수동 세금계산서 삭제 오류: '.$e->getMessage());
+
return response()->json([
'success' => false,
- 'error' => '삭제 오류: ' . $e->getMessage(),
+ 'error' => '삭제 오류: '.$e->getMessage(),
]);
}
}
@@ -1776,6 +1808,7 @@ public function createJournalEntry(Request $request): JsonResponse
$errors = $e->errors();
$firstError = collect($errors)->flatten()->first() ?? '입력 데이터가 올바르지 않습니다.';
Log::error('분개 저장 검증 오류', ['errors' => $errors]);
+
return response()->json([
'success' => false,
'error' => $firstError,
@@ -1787,10 +1820,11 @@ public function createJournalEntry(Request $request): JsonResponse
'error' => '해당 세금계산서를 찾을 수 없습니다.',
], 404);
} catch (\Throwable $e) {
- Log::error('분개 저장 오류: ' . $e->getMessage(), ['trace' => $e->getTraceAsString()]);
+ Log::error('분개 저장 오류: '.$e->getMessage(), ['trace' => $e->getTraceAsString()]);
+
return response()->json([
'success' => false,
- 'error' => '분개 저장 오류: ' . $e->getMessage(),
+ 'error' => '분개 저장 오류: '.$e->getMessage(),
]);
}
}
@@ -1804,11 +1838,11 @@ public function getJournals(Request $request): JsonResponse
$tenantId = session('selected_tenant_id', self::HEADQUARTERS_TENANT_ID);
$invoiceId = $request->input('invoice_id');
- if (!$invoiceId) {
+ if (! $invoiceId) {
return response()->json(['success' => false, 'error' => 'invoice_id는 필수입니다.'], 422);
}
- $journals = HometaxInvoiceJournal::getByInvoiceId($tenantId, (int)$invoiceId);
+ $journals = HometaxInvoiceJournal::getByInvoiceId($tenantId, (int) $invoiceId);
return response()->json([
'success' => true,
@@ -1824,10 +1858,11 @@ public function getJournals(Request $request): JsonResponse
}),
]);
} catch (\Throwable $e) {
- Log::error('분개 조회 오류: ' . $e->getMessage());
+ Log::error('분개 조회 오류: '.$e->getMessage());
+
return response()->json([
'success' => false,
- 'error' => '분개 조회 오류: ' . $e->getMessage(),
+ 'error' => '분개 조회 오류: '.$e->getMessage(),
]);
}
}
@@ -1841,21 +1876,22 @@ public function deleteJournals(Request $request): JsonResponse
$tenantId = session('selected_tenant_id', self::HEADQUARTERS_TENANT_ID);
$invoiceId = $request->input('invoice_id');
- if (!$invoiceId) {
+ if (! $invoiceId) {
return response()->json(['success' => false, 'error' => 'invoice_id는 필수입니다.'], 422);
}
- $deleted = HometaxInvoiceJournal::deleteJournals($tenantId, (int)$invoiceId);
+ $deleted = HometaxInvoiceJournal::deleteJournals($tenantId, (int) $invoiceId);
return response()->json([
'success' => true,
'message' => "분개가 삭제되었습니다. ({$deleted}건)",
]);
} catch (\Throwable $e) {
- Log::error('분개 삭제 오류: ' . $e->getMessage());
+ Log::error('분개 삭제 오류: '.$e->getMessage());
+
return response()->json([
'success' => false,
- 'error' => '분개 삭제 오류: ' . $e->getMessage(),
+ 'error' => '분개 삭제 오류: '.$e->getMessage(),
]);
}
}
@@ -1877,11 +1913,11 @@ public function cardTransactions(Request $request): JsonResponse
->orderByDesc('use_date')
->orderByDesc('use_time');
- if (!empty($search)) {
+ if (! empty($search)) {
$query->where(function ($q) use ($search) {
$q->where('merchant_name', 'like', "%{$search}%")
- ->orWhere('merchant_biz_num', 'like', "%{$search}%")
- ->orWhere('approval_num', 'like', "%{$search}%");
+ ->orWhere('merchant_biz_num', 'like', "%{$search}%")
+ ->orWhere('approval_num', 'like', "%{$search}%");
});
}
@@ -1893,10 +1929,10 @@ public function cardTransactions(Request $request): JsonResponse
'merchantName' => $t->merchant_name,
'merchantBizNum' => $t->merchant_biz_num,
'approvalNum' => $t->approval_num,
- 'approvalAmount' => (float)$t->approval_amount,
+ 'approvalAmount' => (float) $t->approval_amount,
'approvalAmountFormatted' => number_format($t->approval_amount),
- 'tax' => (float)($t->tax ?? 0),
- 'supplyAmount' => (float)($t->modified_supply_amount ?: ($t->approval_amount - ($t->tax ?? 0))),
+ 'tax' => (float) ($t->tax ?? 0),
+ 'supplyAmount' => (float) ($t->modified_supply_amount ?: ($t->approval_amount - ($t->tax ?? 0))),
'cardNum' => $t->card_num ? substr($t->card_num, -4) : '',
'cardCompanyName' => $t->card_company_name ?? '',
];
@@ -1907,10 +1943,11 @@ public function cardTransactions(Request $request): JsonResponse
'data' => $transactions,
]);
} catch (\Throwable $e) {
- Log::error('카드내역 조회 오류: ' . $e->getMessage());
+ Log::error('카드내역 조회 오류: '.$e->getMessage());
+
return response()->json([
'success' => false,
- 'error' => '조회 오류: ' . $e->getMessage(),
+ 'error' => '조회 오류: '.$e->getMessage(),
]);
}
}
diff --git a/app/Http/Controllers/CategoryController.php b/app/Http/Controllers/CategoryController.php
index d21cc359..14a8a786 100644
--- a/app/Http/Controllers/CategoryController.php
+++ b/app/Http/Controllers/CategoryController.php
@@ -208,7 +208,7 @@ public function index(Request $request): View|Response
private function flattenTree($categories): \Illuminate\Support\Collection
{
$result = collect();
- $byParent = $categories->groupBy(fn($c) => $c->parent_id ?? 0);
+ $byParent = $categories->groupBy(fn ($c) => $c->parent_id ?? 0);
$this->addChildrenRecursive($result, $byParent, 0, 0);
diff --git a/app/Http/Controllers/CategorySyncController.php b/app/Http/Controllers/CategorySyncController.php
index 301b16b9..63f2cc2c 100644
--- a/app/Http/Controllers/CategorySyncController.php
+++ b/app/Http/Controllers/CategorySyncController.php
@@ -22,6 +22,7 @@ class CategorySyncController extends Controller
protected function getTenantId(): int
{
$tenantId = session('selected_tenant_id');
+
return ($tenantId && $tenantId !== 'all') ? (int) $tenantId : 1;
}
@@ -155,6 +156,7 @@ public function import(Request $request): JsonResponse
if ($exists) {
$skipped++;
+
continue;
}
@@ -188,6 +190,7 @@ public function import(Request $request): JsonResponse
if ($exists) {
$skipped++;
+
continue;
}
@@ -218,7 +221,7 @@ public function import(Request $request): JsonResponse
return response()->json([
'success' => true,
- 'message' => "{$imported}개 카테고리가 동기화되었습니다." . ($skipped > 0 ? " ({$skipped}개 스킵)" : ''),
+ 'message' => "{$imported}개 카테고리가 동기화되었습니다.".($skipped > 0 ? " ({$skipped}개 스킵)" : ''),
'imported' => $imported,
'skipped' => $skipped,
]);
@@ -247,6 +250,7 @@ public function push(Request $request): JsonResponse
$localCategories = $this->getCategoryList($validated['type']);
$selectedCategories = array_filter($localCategories, function ($cat) use ($validated) {
$key = $this->makeCategoryKey($cat);
+
return in_array($key, $validated['category_keys']);
});
@@ -259,7 +263,7 @@ public function push(Request $request): JsonResponse
$response = Http::withHeaders([
'X-Menu-Sync-Key' => $env['api_key'],
'Accept' => 'application/json',
- ])->post(rtrim($env['url'], '/') . '/category-sync/import', [
+ ])->post(rtrim($env['url'], '/').'/category-sync/import', [
'categories' => array_values($selectedCategories),
]);
@@ -276,7 +280,7 @@ public function push(Request $request): JsonResponse
'error' => $response->json('error', '원격 서버 오류'),
], $response->status());
} catch (\Exception $e) {
- return response()->json(['error' => '연결 실패: ' . $e->getMessage()], 500);
+ return response()->json(['error' => '연결 실패: '.$e->getMessage()], 500);
}
}
@@ -309,6 +313,7 @@ public function pull(Request $request): JsonResponse
// 선택된 카테고리만 필터링
$selectedCategories = array_filter($remoteCategories, function ($cat) use ($validated) {
$key = $this->makeCategoryKey($cat);
+
return in_array($key, $validated['category_keys']);
});
@@ -328,6 +333,7 @@ public function pull(Request $request): JsonResponse
if ($exists) {
$skipped++;
+
continue;
}
@@ -359,6 +365,7 @@ public function pull(Request $request): JsonResponse
if ($exists) {
$skipped++;
+
continue;
}
@@ -388,7 +395,7 @@ public function pull(Request $request): JsonResponse
return response()->json([
'success' => true,
- 'message' => "{$imported}개 카테고리가 동기화되었습니다." . ($skipped > 0 ? " ({$skipped}개 스킵)" : ''),
+ 'message' => "{$imported}개 카테고리가 동기화되었습니다.".($skipped > 0 ? " ({$skipped}개 스킵)" : ''),
'imported' => $imported,
'skipped' => $skipped,
]);
@@ -396,7 +403,8 @@ public function pull(Request $request): JsonResponse
/**
* 카테고리 목록 조회
- * @param string $type 'global', 'tenant', or 'all'
+ *
+ * @param string $type 'global', 'tenant', or 'all'
*/
private function getCategoryList(string $type = 'all'): array
{
@@ -472,12 +480,12 @@ private function fetchRemoteCategories(array $env, string $type = 'all'): array
$response = Http::withHeaders([
'X-Menu-Sync-Key' => $env['api_key'],
'Accept' => 'application/json',
- ])->timeout(10)->get(rtrim($env['url'], '/') . '/category-sync/export', [
+ ])->timeout(10)->get(rtrim($env['url'], '/').'/category-sync/export', [
'type' => $type,
]);
if (! $response->successful()) {
- throw new \Exception('API 오류: HTTP ' . $response->status());
+ throw new \Exception('API 오류: HTTP '.$response->status());
}
$data = $response->json();
@@ -496,6 +504,7 @@ private function fetchRemoteCategories(array $env, string $type = 'all'): array
private function makeCategoryKey(array $cat): string
{
$typePart = $cat['is_global'] ? 'global' : "tenant:{$cat['tenant_id']}";
+
return "{$typePart}:{$cat['code_group']}:{$cat['code']}";
}
@@ -504,8 +513,8 @@ private function makeCategoryKey(array $cat): string
*/
private function calculateDiff(array $localCategories, array $remoteCategories): array
{
- $localKeys = array_map(fn($c) => $this->makeCategoryKey($c), $localCategories);
- $remoteKeys = array_map(fn($c) => $this->makeCategoryKey($c), $remoteCategories);
+ $localKeys = array_map(fn ($c) => $this->makeCategoryKey($c), $localCategories);
+ $remoteKeys = array_map(fn ($c) => $this->makeCategoryKey($c), $remoteCategories);
return [
'local_only' => array_values(array_diff($localKeys, $remoteKeys)),
diff --git a/app/Http/Controllers/CommonCodeController.php b/app/Http/Controllers/CommonCodeController.php
index bcc388a5..147d333b 100644
--- a/app/Http/Controllers/CommonCodeController.php
+++ b/app/Http/Controllers/CommonCodeController.php
@@ -10,7 +10,6 @@
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
-use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
class CommonCodeController extends Controller
@@ -272,6 +271,7 @@ public function update(Request $request, int $id): RedirectResponse|JsonResponse
if ($request->ajax()) {
return response()->json(['error' => '테넌트를 먼저 선택해주세요.'], 400);
}
+
return redirect()->back()->with('error', '테넌트를 먼저 선택해주세요.');
}
@@ -282,6 +282,7 @@ public function update(Request $request, int $id): RedirectResponse|JsonResponse
if ($request->ajax()) {
return response()->json(['error' => '코드를 찾을 수 없습니다.'], 404);
}
+
return redirect()->back()->with('error', '코드를 찾을 수 없습니다.');
}
@@ -294,6 +295,7 @@ public function update(Request $request, int $id): RedirectResponse|JsonResponse
if ($request->ajax()) {
return response()->json(['error' => '글로벌 코드는 본사만 수정할 수 있습니다.'], 403);
}
+
return redirect()->back()->with('error', '글로벌 코드는 본사만 수정할 수 있습니다.');
}
@@ -302,6 +304,7 @@ public function update(Request $request, int $id): RedirectResponse|JsonResponse
if ($request->ajax()) {
return response()->json(['error' => '다른 테넌트의 코드는 수정할 수 없습니다.'], 403);
}
+
return redirect()->back()->with('error', '다른 테넌트의 코드는 수정할 수 없습니다.');
}
}
@@ -393,6 +396,7 @@ public function bulkPromoteToGlobal(Request $request): RedirectResponse|JsonResp
if ($request->ajax()) {
return response()->json(['error' => '본사 또는 슈퍼관리자만 글로벌로 복사할 수 있습니다.'], 403);
}
+
return redirect()->back()->with('error', '본사 또는 슈퍼관리자만 글로벌로 복사할 수 있습니다.');
}
@@ -429,6 +433,7 @@ public function bulkPromoteToGlobal(Request $request): RedirectResponse|JsonResp
if ($exists) {
$skippedCount++;
+
continue;
}
@@ -447,6 +452,7 @@ public function bulkPromoteToGlobal(Request $request): RedirectResponse|JsonResp
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
+
return redirect()->back()->with('error', '복사 중 오류가 발생했습니다.');
}
@@ -471,6 +477,7 @@ public function copy(Request $request, int $id): RedirectResponse|JsonResponse
if ($request->ajax()) {
return response()->json(['error' => '테넌트를 먼저 선택해주세요.'], 400);
}
+
return redirect()->back()->with('error', '테넌트를 먼저 선택해주세요.');
}
@@ -479,6 +486,7 @@ public function copy(Request $request, int $id): RedirectResponse|JsonResponse
if ($request->ajax()) {
return response()->json(['error' => '글로벌 코드를 찾을 수 없습니다.'], 404);
}
+
return redirect()->back()->with('error', '글로벌 코드를 찾을 수 없습니다.');
}
@@ -493,6 +501,7 @@ public function copy(Request $request, int $id): RedirectResponse|JsonResponse
if ($request->ajax()) {
return response()->json(['error' => '이미 복사된 코드가 있습니다.'], 400);
}
+
return redirect()->back()->with('error', '이미 복사된 코드가 있습니다.');
}
@@ -527,6 +536,7 @@ public function bulkCopy(Request $request): RedirectResponse|JsonResponse
if ($request->ajax()) {
return response()->json(['error' => '테넌트를 먼저 선택해주세요.'], 400);
}
+
return redirect()->back()->with('error', '테넌트를 먼저 선택해주세요.');
}
@@ -538,6 +548,7 @@ public function bulkCopy(Request $request): RedirectResponse|JsonResponse
if ($request->ajax()) {
return response()->json(['error' => '복사할 코드를 선택해주세요.'], 400);
}
+
return redirect()->back()->with('error', '복사할 코드를 선택해주세요.');
}
} else {
@@ -570,6 +581,7 @@ public function bulkCopy(Request $request): RedirectResponse|JsonResponse
if ($exists) {
$skippedCount++;
+
continue;
}
@@ -593,6 +605,7 @@ public function bulkCopy(Request $request): RedirectResponse|JsonResponse
if ($request->ajax()) {
return response()->json(['error' => '복사 중 오류가 발생했습니다.'], 500);
}
+
return redirect()->back()->with('error', '복사 중 오류가 발생했습니다.');
}
@@ -624,6 +637,7 @@ public function promoteToGlobal(Request $request, int $id): RedirectResponse|Jso
if ($request->ajax()) {
return response()->json(['error' => '본사 또는 슈퍼관리자만 글로벌로 복사할 수 있습니다.'], 403);
}
+
return redirect()->back()->with('error', '본사 또는 슈퍼관리자만 글로벌로 복사할 수 있습니다.');
}
@@ -632,6 +646,7 @@ public function promoteToGlobal(Request $request, int $id): RedirectResponse|Jso
if ($request->ajax()) {
return response()->json(['error' => '테넌트 코드를 찾을 수 없습니다.'], 404);
}
+
return redirect()->back()->with('error', '테넌트 코드를 찾을 수 없습니다.');
}
@@ -646,6 +661,7 @@ public function promoteToGlobal(Request $request, int $id): RedirectResponse|Jso
if ($request->ajax()) {
return response()->json(['error' => '이미 동일한 글로벌 코드가 존재합니다.'], 400);
}
+
return redirect()->back()->with('error', '이미 동일한 글로벌 코드가 존재합니다.');
}
@@ -680,6 +696,7 @@ public function destroy(Request $request, int $id): RedirectResponse|JsonRespons
if ($request->ajax()) {
return response()->json(['error' => '테넌트를 먼저 선택해주세요.'], 400);
}
+
return redirect()->back()->with('error', '테넌트를 먼저 선택해주세요.');
}
@@ -690,6 +707,7 @@ public function destroy(Request $request, int $id): RedirectResponse|JsonRespons
if ($request->ajax()) {
return response()->json(['error' => '코드를 찾을 수 없습니다.'], 404);
}
+
return redirect()->back()->with('error', '코드를 찾을 수 없습니다.');
}
@@ -702,6 +720,7 @@ public function destroy(Request $request, int $id): RedirectResponse|JsonRespons
if ($request->ajax()) {
return response()->json(['error' => '글로벌 코드는 본사만 삭제할 수 있습니다.'], 403);
}
+
return redirect()->back()->with('error', '글로벌 코드는 본사만 삭제할 수 있습니다.');
}
@@ -710,6 +729,7 @@ public function destroy(Request $request, int $id): RedirectResponse|JsonRespons
if ($request->ajax()) {
return response()->json(['error' => '다른 테넌트의 코드는 삭제할 수 없습니다.'], 403);
}
+
return redirect()->back()->with('error', '다른 테넌트의 코드는 삭제할 수 없습니다.');
}
}
diff --git a/app/Http/Controllers/CommonCodeSyncController.php b/app/Http/Controllers/CommonCodeSyncController.php
index 455cc453..45d63a1f 100644
--- a/app/Http/Controllers/CommonCodeSyncController.php
+++ b/app/Http/Controllers/CommonCodeSyncController.php
@@ -21,6 +21,7 @@ class CommonCodeSyncController extends Controller
protected function getTenantId(): int
{
$tenantId = session('selected_tenant_id');
+
return ($tenantId && $tenantId !== 'all') ? (int) $tenantId : 1;
}
@@ -153,6 +154,7 @@ public function import(Request $request): JsonResponse
if ($exists) {
$skipped++;
+
continue;
}
@@ -170,7 +172,7 @@ public function import(Request $request): JsonResponse
return response()->json([
'success' => true,
- 'message' => "{$imported}개 코드가 동기화되었습니다." . ($skipped > 0 ? " ({$skipped}개 스킵)" : ''),
+ 'message' => "{$imported}개 코드가 동기화되었습니다.".($skipped > 0 ? " ({$skipped}개 스킵)" : ''),
'imported' => $imported,
'skipped' => $skipped,
]);
@@ -199,6 +201,7 @@ public function push(Request $request): JsonResponse
$localCodes = $this->getCodeList($validated['type']);
$selectedCodes = array_filter($localCodes, function ($code) use ($validated) {
$key = $this->makeCodeKey($code);
+
return in_array($key, $validated['code_keys']);
});
@@ -211,7 +214,7 @@ public function push(Request $request): JsonResponse
$response = Http::withHeaders([
'X-Menu-Sync-Key' => $env['api_key'],
'Accept' => 'application/json',
- ])->post(rtrim($env['url'], '/') . '/common-code-sync/import', [
+ ])->post(rtrim($env['url'], '/').'/common-code-sync/import', [
'codes' => array_values($selectedCodes),
]);
@@ -228,7 +231,7 @@ public function push(Request $request): JsonResponse
'error' => $response->json('error', '원격 서버 오류'),
], $response->status());
} catch (\Exception $e) {
- return response()->json(['error' => '연결 실패: ' . $e->getMessage()], 500);
+ return response()->json(['error' => '연결 실패: '.$e->getMessage()], 500);
}
}
@@ -261,6 +264,7 @@ public function pull(Request $request): JsonResponse
// 선택된 코드만 필터링
$selectedCodes = array_filter($remoteCodes, function ($code) use ($validated) {
$key = $this->makeCodeKey($code);
+
return in_array($key, $validated['code_keys']);
});
@@ -282,6 +286,7 @@ public function pull(Request $request): JsonResponse
if ($exists) {
$skipped++;
+
continue;
}
@@ -299,7 +304,7 @@ public function pull(Request $request): JsonResponse
return response()->json([
'success' => true,
- 'message' => "{$imported}개 코드가 동기화되었습니다." . ($skipped > 0 ? " ({$skipped}개 스킵)" : ''),
+ 'message' => "{$imported}개 코드가 동기화되었습니다.".($skipped > 0 ? " ({$skipped}개 스킵)" : ''),
'imported' => $imported,
'skipped' => $skipped,
]);
@@ -307,7 +312,8 @@ public function pull(Request $request): JsonResponse
/**
* 코드 목록 조회
- * @param string $type 'global', 'tenant', or 'all'
+ *
+ * @param string $type 'global', 'tenant', or 'all'
*/
private function getCodeList(string $type = 'all'): array
{
@@ -369,12 +375,12 @@ private function fetchRemoteCodes(array $env, string $type = 'all'): array
$response = Http::withHeaders([
'X-Menu-Sync-Key' => $env['api_key'],
'Accept' => 'application/json',
- ])->timeout(10)->get(rtrim($env['url'], '/') . '/common-code-sync/export', [
+ ])->timeout(10)->get(rtrim($env['url'], '/').'/common-code-sync/export', [
'type' => $type,
]);
if (! $response->successful()) {
- throw new \Exception('API 오류: HTTP ' . $response->status());
+ throw new \Exception('API 오류: HTTP '.$response->status());
}
$data = $response->json();
@@ -393,6 +399,7 @@ private function fetchRemoteCodes(array $env, string $type = 'all'): array
private function makeCodeKey(array $code): string
{
$tenantPart = $code['tenant_id'] ?? 'global';
+
return "{$tenantPart}:{$code['code_group']}:{$code['code']}";
}
@@ -401,8 +408,8 @@ private function makeCodeKey(array $code): string
*/
private function calculateDiff(array $localCodes, array $remoteCodes): array
{
- $localKeys = array_map(fn($c) => $this->makeCodeKey($c), $localCodes);
- $remoteKeys = array_map(fn($c) => $this->makeCodeKey($c), $remoteCodes);
+ $localKeys = array_map(fn ($c) => $this->makeCodeKey($c), $localCodes);
+ $remoteKeys = array_map(fn ($c) => $this->makeCodeKey($c), $remoteCodes);
return [
'local_only' => array_values(array_diff($localKeys, $remoteKeys)),
diff --git a/app/Http/Controllers/Credit/CreditController.php b/app/Http/Controllers/Credit/CreditController.php
index eae3efd7..f3081acc 100644
--- a/app/Http/Controllers/Credit/CreditController.php
+++ b/app/Http/Controllers/Credit/CreditController.php
@@ -26,7 +26,7 @@ public function inquiry(Request $request): View|Response
return response('', 200)->header('HX-Redirect', route('credit.inquiry.index'));
}
- $service = new CooconService();
+ $service = new CooconService;
$hasConfig = $service->hasConfig();
// 검색 조건
@@ -42,10 +42,10 @@ public function inquiry(Request $request): View|Response
// 기간 검색
if ($request->filled('start_date')) {
- $query->where('inquired_at', '>=', $request->input('start_date') . ' 00:00:00');
+ $query->where('inquired_at', '>=', $request->input('start_date').' 00:00:00');
}
if ($request->filled('end_date')) {
- $query->where('inquired_at', '<=', $request->input('end_date') . ' 23:59:59');
+ $query->where('inquired_at', '<=', $request->input('end_date').' 23:59:59');
}
// 이슈 있는 것만
@@ -79,9 +79,9 @@ public function search(Request $request): JsonResponse
$companyKey = preg_replace('/[^0-9]/', '', $request->input('company_key'));
- $cooconService = new CooconService();
+ $cooconService = new CooconService;
- if (!$cooconService->hasConfig()) {
+ if (! $cooconService->hasConfig()) {
return response()->json([
'success' => false,
'error' => '쿠콘 API 설정이 없습니다. 설정을 먼저 등록해주세요.',
@@ -92,7 +92,7 @@ public function search(Request $request): JsonResponse
$apiResult = $cooconService->getAllCreditInfo($companyKey);
// 국세청 사업자등록 상태 조회
- $ntsService = new NtsBusinessService();
+ $ntsService = new NtsBusinessService;
$ntsResult = $ntsService->getBusinessStatus($companyKey);
// DB에 저장 (tenant_id는 세션에서 가져옴)
@@ -354,14 +354,14 @@ public function toggleConfig(int $id): JsonResponse
{
$config = CooconConfig::findOrFail($id);
- if (!$config->is_active) {
+ if (! $config->is_active) {
// 같은 환경에서 활성화된 설정이 이미 있으면 비활성화
CooconConfig::where('environment', $config->environment)
->where('is_active', true)
->update(['is_active' => false]);
}
- $config->update(['is_active' => !$config->is_active]);
+ $config->update(['is_active' => ! $config->is_active]);
return response()->json([
'success' => true,
@@ -380,9 +380,9 @@ public function testConnection(Request $request): JsonResponse
]);
$companyKey = $request->input('company_key');
- $service = new CooconService();
+ $service = new CooconService;
- if (!$service->hasConfig()) {
+ if (! $service->hasConfig()) {
return response()->json([
'success' => false,
'error' => '쿠콘 API 설정이 없습니다.',
diff --git a/app/Http/Controllers/Credit/CreditUsageController.php b/app/Http/Controllers/Credit/CreditUsageController.php
index 9c4fed19..33cf09c7 100644
--- a/app/Http/Controllers/Credit/CreditUsageController.php
+++ b/app/Http/Controllers/Credit/CreditUsageController.php
@@ -44,8 +44,8 @@ public function index(Request $request): View|Response
$startDate = "{$year}-01-01 00:00:00";
$endDate = "{$year}-12-31 23:59:59";
} elseif ($viewType === 'custom') {
- $startDate = $request->input('start_date', date('Y-m-01')) . ' 00:00:00';
- $endDate = $request->input('end_date', date('Y-m-t')) . ' 23:59:59';
+ $startDate = $request->input('start_date', date('Y-m-01')).' 00:00:00';
+ $endDate = $request->input('end_date', date('Y-m-t')).' 23:59:59';
} else {
$startDate = "{$year}-{$month}-01 00:00:00";
$endDate = date('Y-m-t 23:59:59', strtotime($startDate));
@@ -116,7 +116,7 @@ private function getAllTenantsUsage(string $startDate, string $endDate, string $
$tenantId = $row->tenant_id;
$month = $row->month;
- if (!isset($monthlyData[$tenantId])) {
+ if (! isset($monthlyData[$tenantId])) {
$monthlyData[$tenantId] = [];
}
$monthlyData[$tenantId][$month] = $row->total_count;
@@ -173,7 +173,7 @@ private function getAllTenantsUsage(string $startDate, string $endDate, string $
}
// 정렬: 조회 건수 내림차순
- usort($details, fn($a, $b) => $b['count'] - $a['count']);
+ usort($details, fn ($a, $b) => $b['count'] - $a['count']);
return [
'total_count' => $totalCount,
@@ -228,7 +228,7 @@ private function getSingleTenantUsage(int $tenantId, string $startDate, string $
$existingMonths = collect($details)->pluck('month')->toArray();
for ($m = 1; $m <= 12; $m++) {
$monthKey = sprintf('%s-%02d', $year, $m);
- if (!in_array($monthKey, $existingMonths)) {
+ if (! in_array($monthKey, $existingMonths)) {
$details[] = [
'tenant_id' => $tenantId,
'tenant_name' => $tenant?->company_name ?? '(삭제됨)',
@@ -241,7 +241,7 @@ private function getSingleTenantUsage(int $tenantId, string $startDate, string $
}
}
// 월 순서로 정렬
- usort($details, fn($a, $b) => strcmp($a['month'], $b['month']));
+ usort($details, fn ($a, $b) => strcmp($a['month'], $b['month']));
}
return [
@@ -257,6 +257,7 @@ private function getSingleTenantUsage(int $tenantId, string $startDate, string $
private function calculateFee(int $count): int
{
$paidCount = max(0, $count - self::FREE_MONTHLY_QUOTA);
+
return $paidCount * self::ADDITIONAL_FEE_PER_INQUIRY;
}
}
diff --git a/app/Http/Controllers/DashboardCalendarController.php b/app/Http/Controllers/DashboardCalendarController.php
index 69785492..2308f8c6 100644
--- a/app/Http/Controllers/DashboardCalendarController.php
+++ b/app/Http/Controllers/DashboardCalendarController.php
@@ -7,10 +7,9 @@
use App\Models\System\Schedule;
use App\Services\GoogleCloudStorageService;
use Carbon\Carbon;
+use Illuminate\Contracts\View\View;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
-use Illuminate\Contracts\View\View;
-use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
@@ -174,7 +173,7 @@ public function uploadFiles(Request $request, int $scheduleId, GoogleCloudStorag
foreach ($request->file('files') as $file) {
$originalName = $file->getClientOriginalName();
- $storedName = Str::random(40) . '.' . $file->getClientOriginalExtension();
+ $storedName = Str::random(40).'.'.$file->getClientOriginalExtension();
$storagePath = "schedules/{$tenantId}/{$schedule->id}/{$storedName}";
// 로컬(tenant 디스크) 저장
@@ -215,7 +214,7 @@ public function uploadFiles(Request $request, int $scheduleId, GoogleCloudStorag
return response()->json([
'success' => true,
- 'message' => count($uploaded) . '개 파일이 업로드되었습니다.',
+ 'message' => count($uploaded).'개 파일이 업로드되었습니다.',
'files' => $uploaded,
]);
}
@@ -274,9 +273,16 @@ public function downloadFile(int $scheduleId, int $fileId)
*/
private function determineFileType(string $mimeType): string
{
- if (str_starts_with($mimeType, 'image/')) return 'image';
- if (str_contains($mimeType, 'spreadsheet') || str_contains($mimeType, 'excel')) return 'excel';
- if (str_contains($mimeType, 'zip') || str_contains($mimeType, 'rar') || str_contains($mimeType, 'archive')) return 'archive';
+ if (str_starts_with($mimeType, 'image/')) {
+ return 'image';
+ }
+ if (str_contains($mimeType, 'spreadsheet') || str_contains($mimeType, 'excel')) {
+ return 'excel';
+ }
+ if (str_contains($mimeType, 'zip') || str_contains($mimeType, 'rar') || str_contains($mimeType, 'archive')) {
+ return 'archive';
+ }
+
return 'document';
}
diff --git a/app/Http/Controllers/DevTools/ApiExplorerController.php b/app/Http/Controllers/DevTools/ApiExplorerController.php
index 23baf30f..8a96841f 100644
--- a/app/Http/Controllers/DevTools/ApiExplorerController.php
+++ b/app/Http/Controllers/DevTools/ApiExplorerController.php
@@ -461,13 +461,13 @@ public function users(): JsonResponse
// 세션에서 직접 테넌트 ID 조회 (관리자가 선택한 테넌트)
$selectedTenantId = session('selected_tenant_id');
- if (!$selectedTenantId) {
+ if (! $selectedTenantId) {
// 테넌트가 선택되지 않은 경우 로그인 사용자의 기본 테넌트 사용
$currentTenant = auth()->user()->tenants()
->where('is_default', true)
->first() ?? auth()->user()->tenants()->first();
- if (!$currentTenant) {
+ if (! $currentTenant) {
return response()->json([]);
}
@@ -477,7 +477,7 @@ public function users(): JsonResponse
// Tenant 모델에서 직접 조회 (사용자의 테넌트 관계와 무관하게)
$tenant = \App\Models\Tenants\Tenant::find($selectedTenantId);
- if (!$tenant) {
+ if (! $tenant) {
return response()->json([]);
}
@@ -510,7 +510,7 @@ public function issueToken(Request $request): JsonResponse
$user = \App\Models\User::find($validated['user_id']);
- if (!$user) {
+ if (! $user) {
return response()->json(['error' => '사용자를 찾을 수 없습니다.'], 404);
}
diff --git a/app/Http/Controllers/DocumentController.php b/app/Http/Controllers/DocumentController.php
index 92cca884..6ab267cf 100644
--- a/app/Http/Controllers/DocumentController.php
+++ b/app/Http/Controllers/DocumentController.php
@@ -248,6 +248,7 @@ public function show(int $id): View
->filter(fn ($lot) => $lot->total_qty < 0)
->map(function ($lot) {
$lot->total_qty = abs($lot->total_qty);
+
return $lot;
})
->values();
diff --git a/app/Http/Controllers/DocumentTemplateController.php b/app/Http/Controllers/DocumentTemplateController.php
index a2b40eec..4c7156d0 100644
--- a/app/Http/Controllers/DocumentTemplateController.php
+++ b/app/Http/Controllers/DocumentTemplateController.php
@@ -332,7 +332,7 @@ private function resolveDisplayText(?string $sourceTable, int $linkableId, ?arra
$title = is_object($record) ? ($record->$titleField ?? '') : ($record->$titleField ?? '');
$subtitle = $subtitleField ? (is_object($record) ? ($record->$subtitleField ?? '') : ($record->$subtitleField ?? '')) : '';
- return $title . ($subtitle ? " ({$subtitle})" : '');
+ return $title.($subtitle ? " ({$subtitle})" : '');
} catch (\Exception $e) {
return "ID: {$linkableId}";
}
diff --git a/app/Http/Controllers/ESign/EsignApiController.php b/app/Http/Controllers/ESign/EsignApiController.php
index a3478bff..2675681b 100644
--- a/app/Http/Controllers/ESign/EsignApiController.php
+++ b/app/Http/Controllers/ESign/EsignApiController.php
@@ -1059,7 +1059,7 @@ private function sendAlimtalk(
// 등록된 버튼 URL을 그대로 사용 (동적 URL 사용 시 템플릿 불일치 오류)
$buttons = ! empty($templateButtons) ? $templateButtons : [
['Name' => '계약서 확인하기', 'ButtonType' => 'WL',
- 'Url1' => 'https://mng.codebridge-x.com', 'Url2' => 'https://mng.codebridge-x.com'],
+ 'Url1' => 'https://mng.codebridge-x.com', 'Url2' => 'https://mng.codebridge-x.com'],
];
$receiverNum = preg_replace('/[^0-9]/', '', $signer->phone);
diff --git a/app/Http/Controllers/Finance/CardTransactionController.php b/app/Http/Controllers/Finance/CardTransactionController.php
index a548a056..5f5e3126 100644
--- a/app/Http/Controllers/Finance/CardTransactionController.php
+++ b/app/Http/Controllers/Finance/CardTransactionController.php
@@ -19,8 +19,8 @@ public function index(Request $request): JsonResponse
if ($search = $request->input('search')) {
$query->where(function ($q) use ($search) {
$q->where('merchant', 'like', "%{$search}%")
- ->orWhere('memo', 'like', "%{$search}%")
- ->orWhere('approval_no', 'like', "%{$search}%");
+ ->orWhere('memo', 'like', "%{$search}%")
+ ->orWhere('approval_no', 'like', "%{$search}%");
});
}
@@ -72,7 +72,7 @@ public function index(Request $request): JsonResponse
'total' => $transactions->count(),
'totalAmount' => $transactions->sum('amount'),
'approvedAmount' => $transactions->where('status', 'approved')->sum('amount'),
- 'cancelledAmount' => $transactions->where('status', 'cancelled')->sum(fn($t) => abs($t['amount'])),
+ 'cancelledAmount' => $transactions->where('status', 'cancelled')->sum(fn ($t) => abs($t['amount'])),
];
// 카드 목록
diff --git a/app/Http/Controllers/Finance/ConsultingFeeController.php b/app/Http/Controllers/Finance/ConsultingFeeController.php
index 82de601f..8ced65cb 100644
--- a/app/Http/Controllers/Finance/ConsultingFeeController.php
+++ b/app/Http/Controllers/Finance/ConsultingFeeController.php
@@ -17,14 +17,16 @@ public function index(Request $request): JsonResponse
if ($search = $request->input('search')) {
$query->where(function ($q) use ($search) {
$q->where('consultant', 'like', "%{$search}%")
- ->orWhere('customer', 'like', "%{$search}%");
+ ->orWhere('customer', 'like', "%{$search}%");
});
}
if ($status = $request->input('status')) {
- if ($status !== 'all') $query->where('status', $status);
+ if ($status !== 'all') {
+ $query->where('status', $status);
+ }
}
- $fees = $query->orderBy('date', 'desc')->get()->map(fn($item) => [
+ $fees = $query->orderBy('date', 'desc')->get()->map(fn ($item) => [
'id' => $item->id, 'date' => $item->date?->format('Y-m-d'),
'consultant' => $item->consultant, 'customer' => $item->customer,
'service' => $item->service, 'hours' => $item->hours,
@@ -82,6 +84,7 @@ public function destroy(int $id): JsonResponse
{
$tenantId = session('selected_tenant_id', 1);
ConsultingFee::forTenant($tenantId)->findOrFail($id)->delete();
+
return response()->json(['success' => true, 'message' => '컨설팅비가 삭제되었습니다.']);
}
}
diff --git a/app/Http/Controllers/Finance/CorporateCardController.php b/app/Http/Controllers/Finance/CorporateCardController.php
index c13e22b1..a7402d62 100644
--- a/app/Http/Controllers/Finance/CorporateCardController.php
+++ b/app/Http/Controllers/Finance/CorporateCardController.php
@@ -227,7 +227,7 @@ public function summary(): JsonResponse
$adjustedDate = $this->getAdjustedPaymentDate($tenantId, $nextMonth->year, $nextMonth->month, $paymentDay);
}
- $isAdjusted = !$originalDate->isSameDay($adjustedDate);
+ $isAdjusted = ! $originalDate->isSameDay($adjustedDate);
// 청구기간: 결제일 기준 전월 1일 ~ 결제일
$billingStart = $adjustedDate->copy()->subMonth()->startOfMonth();
@@ -283,7 +283,7 @@ public function updatePrepayment(Request $request): JsonResponse
$tenantId = session('selected_tenant_id', 1);
$yearMonth = $this->getBillingYearMonth($tenantId);
- $items = collect($request->input('items', []))->filter(fn($item) => ($item['amount'] ?? 0) > 0)->values()->toArray();
+ $items = collect($request->input('items', []))->filter(fn ($item) => ($item['amount'] ?? 0) > 0)->values()->toArray();
$amount = collect($items)->sum('amount');
$prepayment = CorporateCardPrepayment::updateOrCreate(
@@ -328,6 +328,7 @@ private function getBillingYearMonth(int $tenantId): string
private function createPaymentDate(int $year, int $month, int $day): Carbon
{
$maxDay = Carbon::create($year, $month)->daysInMonth;
+
return Carbon::create($year, $month, min($day, $maxDay));
}
@@ -367,7 +368,7 @@ private function getAdjustedPaymentDate(int $tenantId, int $year, int $month, in
private function calculateBillingUsage(int $tenantId, string $startDate, string $endDate, array $cardNumbers): array
{
// 카드번호 정규화 (하이픈 제거) + 원본↔정규화 매핑
- $normalizedNums = array_map(fn($num) => str_replace('-', '', $num), $cardNumbers);
+ $normalizedNums = array_map(fn ($num) => str_replace('-', '', $num), $cardNumbers);
if (empty($normalizedNums)) {
return ['total' => 0, 'perCard' => []];
diff --git a/app/Http/Controllers/Finance/CorporateVehicleController.php b/app/Http/Controllers/Finance/CorporateVehicleController.php
index 7a457ba7..60aa7ae5 100644
--- a/app/Http/Controllers/Finance/CorporateVehicleController.php
+++ b/app/Http/Controllers/Finance/CorporateVehicleController.php
@@ -45,8 +45,8 @@ public function list(Request $request): JsonResponse
$search = $request->search;
$query->where(function ($q) use ($search) {
$q->where('plate_number', 'like', "%{$search}%")
- ->orWhere('model', 'like', "%{$search}%")
- ->orWhere('driver', 'like', "%{$search}%");
+ ->orWhere('model', 'like', "%{$search}%")
+ ->orWhere('driver', 'like', "%{$search}%");
});
}
diff --git a/app/Http/Controllers/Finance/CustomerController.php b/app/Http/Controllers/Finance/CustomerController.php
index 02ce0dbc..d716ef40 100644
--- a/app/Http/Controllers/Finance/CustomerController.php
+++ b/app/Http/Controllers/Finance/CustomerController.php
@@ -19,18 +19,22 @@ public function index(Request $request): JsonResponse
if ($search = $request->input('search')) {
$query->where(function ($q) use ($search) {
$q->where('name', 'like', "%{$search}%")
- ->orWhere('ceo', 'like', "%{$search}%")
- ->orWhere('manager', 'like', "%{$search}%");
+ ->orWhere('ceo', 'like', "%{$search}%")
+ ->orWhere('manager', 'like', "%{$search}%");
});
}
if ($status = $request->input('status')) {
- if ($status !== 'all') $query->where('status', $status);
+ if ($status !== 'all') {
+ $query->where('status', $status);
+ }
}
if ($grade = $request->input('grade')) {
- if ($grade !== 'all') $query->where('grade', $grade);
+ if ($grade !== 'all') {
+ $query->where('grade', $grade);
+ }
}
- $customers = $query->orderBy('created_at', 'desc')->get()->map(fn($item) => [
+ $customers = $query->orderBy('created_at', 'desc')->get()->map(fn ($item) => [
'id' => $item->id, 'name' => $item->name, 'bizNo' => $item->biz_no,
'ceo' => $item->ceo, 'industry' => $item->industry, 'grade' => $item->grade,
'contact' => $item->contact, 'email' => $item->email, 'address' => $item->address,
@@ -90,6 +94,7 @@ public function destroy(int $id): JsonResponse
{
$tenantId = session('selected_tenant_id', 1);
Customer::forTenant($tenantId)->findOrFail($id)->delete();
+
return response()->json(['success' => true, 'message' => '고객사가 삭제되었습니다.']);
}
@@ -130,13 +135,14 @@ function ($attribute, $value, $fail) {
return response()->json(['ok' => false, 'message' => $e->getMessage()], 500);
} catch (\Throwable $e) {
Log::error('고객사 OCR 예상치 못한 오류', ['error' => $e->getMessage()]);
+
return response()->json(['ok' => false, 'message' => 'OCR 처리 중 오류가 발생했습니다.'], 500);
}
}
private function matchIndustry(string $bizType, string $bizItem): string
{
- $text = $bizType . ' ' . $bizItem;
+ $text = $bizType.' '.$bizItem;
$keywords = [
'IT/소프트웨어' => ['소프트웨어', 'IT', '정보통신', '전산', '컴퓨터', '인터넷', '데이터', '프로그램'],
@@ -162,8 +168,13 @@ private function buildCustomerMemo(array $raw): string
$parts = [];
$bizType = trim($raw['biz_type'] ?? '');
$bizItem = trim($raw['biz_item'] ?? '');
- if ($bizType) $parts[] = "[업태] {$bizType}";
- if ($bizItem) $parts[] = "[종목] {$bizItem}";
+ if ($bizType) {
+ $parts[] = "[업태] {$bizType}";
+ }
+ if ($bizItem) {
+ $parts[] = "[종목] {$bizItem}";
+ }
+
return implode(' / ', $parts);
}
}
diff --git a/app/Http/Controllers/Finance/CustomerSettlementController.php b/app/Http/Controllers/Finance/CustomerSettlementController.php
index eca0e8dc..aa889ba1 100644
--- a/app/Http/Controllers/Finance/CustomerSettlementController.php
+++ b/app/Http/Controllers/Finance/CustomerSettlementController.php
@@ -20,10 +20,12 @@ public function index(Request $request): JsonResponse
});
}
if ($status = $request->input('status')) {
- if ($status !== 'all') $query->where('status', $status);
+ if ($status !== 'all') {
+ $query->where('status', $status);
+ }
}
- $settlements = $query->orderBy('created_at', 'desc')->get()->map(fn($item) => [
+ $settlements = $query->orderBy('created_at', 'desc')->get()->map(fn ($item) => [
'id' => $item->id, 'period' => $item->period,
'customer' => $item->customer, 'totalSales' => $item->total_sales,
'commission' => $item->commission, 'expense' => $item->expense,
@@ -85,6 +87,7 @@ public function destroy(int $id): JsonResponse
{
$tenantId = session('selected_tenant_id', 1);
CustomerSettlement::forTenant($tenantId)->findOrFail($id)->delete();
+
return response()->json(['success' => true, 'message' => '정산이 삭제되었습니다.']);
}
}
diff --git a/app/Http/Controllers/Finance/DailyFundController.php b/app/Http/Controllers/Finance/DailyFundController.php
index 53ce76eb..d76e02c0 100644
--- a/app/Http/Controllers/Finance/DailyFundController.php
+++ b/app/Http/Controllers/Finance/DailyFundController.php
@@ -3,13 +3,12 @@
namespace App\Http\Controllers\Finance;
use App\Http\Controllers\Controller;
-use App\Models\Finance\DailyFundTransaction;
-use App\Models\Finance\DailyFundMemo;
use App\Models\Barobill\BankTransaction as BarobillBankTransaction;
use App\Models\Barobill\BankTransactionOverride;
+use App\Models\Finance\DailyFundMemo;
+use App\Models\Finance\DailyFundTransaction;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
-use Illuminate\Support\Facades\DB;
class DailyFundController extends Controller
{
@@ -179,14 +178,14 @@ public function periodReport(Request $request): JsonResponse
->whereBetween('trans_date', [$startDateYmd, $endDateYmd])
->orderBy('id', 'desc') // 최신 ID 우선 (올바른 잔액)
->get()
- ->unique(fn($tx) => $tx->unique_key)
+ ->unique(fn ($tx) => $tx->unique_key)
->sortByDesc('trans_date')
- ->sortByDesc(fn($tx) => $tx->trans_date . $tx->trans_time)
+ ->sortByDesc(fn ($tx) => $tx->trans_date.$tx->trans_time)
->values();
// 오버라이드 데이터 병합 (수정된 적요/내용)
if ($transactions->isNotEmpty()) {
- $uniqueKeys = $transactions->map(fn($t) => $t->unique_key)->toArray();
+ $uniqueKeys = $transactions->map(fn ($t) => $t->unique_key)->toArray();
$overrides = BankTransactionOverride::getByUniqueKeys($tenantId, $uniqueKeys);
$transactions = $transactions->map(function ($tx) use ($overrides) {
@@ -199,6 +198,7 @@ public function periodReport(Request $request): JsonResponse
$tx->cast = $override->modified_cast;
}
}
+
return $tx;
});
}
@@ -211,7 +211,7 @@ public function periodReport(Request $request): JsonResponse
$date = $tx->trans_date;
$accountNum = $tx->bank_account_num;
- if (!isset($dailyData[$date])) {
+ if (! isset($dailyData[$date])) {
$dailyData[$date] = [
'date' => $date,
'dateFormatted' => $this->formatDateKorean($date),
@@ -224,7 +224,7 @@ public function periodReport(Request $request): JsonResponse
}
// 계좌별 데이터 집계
- if (!isset($dailyData[$date]['accounts'][$accountNum])) {
+ if (! isset($dailyData[$date]['accounts'][$accountNum])) {
$dailyData[$date]['accounts'][$accountNum] = [
'bankName' => $tx->bank_name,
'accountNum' => $accountNum,
diff --git a/app/Http/Controllers/Finance/ExpenseController.php b/app/Http/Controllers/Finance/ExpenseController.php
index 1977ce8b..6d4230f4 100644
--- a/app/Http/Controllers/Finance/ExpenseController.php
+++ b/app/Http/Controllers/Finance/ExpenseController.php
@@ -17,17 +17,21 @@ public function index(Request $request): JsonResponse
if ($search = $request->input('search')) {
$query->where(function ($q) use ($search) {
$q->where('vendor', 'like', "%{$search}%")
- ->orWhere('description', 'like', "%{$search}%");
+ ->orWhere('description', 'like', "%{$search}%");
});
}
if ($status = $request->input('status')) {
- if ($status !== 'all') $query->where('status', $status);
+ if ($status !== 'all') {
+ $query->where('status', $status);
+ }
}
if ($category = $request->input('category')) {
- if ($category !== 'all') $query->where('category', $category);
+ if ($category !== 'all') {
+ $query->where('category', $category);
+ }
}
- $expenses = $query->orderBy('date', 'desc')->get()->map(fn($item) => [
+ $expenses = $query->orderBy('date', 'desc')->get()->map(fn ($item) => [
'id' => $item->id, 'date' => $item->date?->format('Y-m-d'),
'vendor' => $item->vendor, 'description' => $item->description,
'category' => $item->category, 'amount' => $item->amount,
@@ -87,6 +91,7 @@ public function destroy(int $id): JsonResponse
{
$tenantId = session('selected_tenant_id', 1);
Expense::forTenant($tenantId)->findOrFail($id)->delete();
+
return response()->json(['success' => true, 'message' => '지출이 삭제되었습니다.']);
}
}
diff --git a/app/Http/Controllers/Finance/FinanceDashboardController.php b/app/Http/Controllers/Finance/FinanceDashboardController.php
index d2649848..f4588351 100644
--- a/app/Http/Controllers/Finance/FinanceDashboardController.php
+++ b/app/Http/Controllers/Finance/FinanceDashboardController.php
@@ -7,7 +7,6 @@
use App\Models\Barobill\BankTransactionOverride;
use App\Models\Barobill\CardTransaction as BarobillCardTransaction;
use App\Models\Finance\BankAccount;
-use App\Models\Finance\FundSchedule;
use App\Services\BankAccountService;
use App\Services\FundScheduleService;
use Illuminate\Contracts\View\View;
@@ -53,7 +52,7 @@ public function index(): View
// 오버라이드 데이터 병합 (수정된 적요/내용)
if ($recentTransactions->isNotEmpty()) {
- $uniqueKeys = $recentTransactions->map(fn($t) => $t->unique_key)->toArray();
+ $uniqueKeys = $recentTransactions->map(fn ($t) => $t->unique_key)->toArray();
$overrides = BankTransactionOverride::getByUniqueKeys($tenantId, $uniqueKeys);
$recentTransactions = $recentTransactions->map(function ($transaction) use ($overrides) {
@@ -71,6 +70,7 @@ public function index(): View
} else {
$transaction->is_overridden = false;
}
+
return $transaction;
});
}
diff --git a/app/Http/Controllers/Finance/IncomeController.php b/app/Http/Controllers/Finance/IncomeController.php
index 551f7f06..b5a67dc1 100644
--- a/app/Http/Controllers/Finance/IncomeController.php
+++ b/app/Http/Controllers/Finance/IncomeController.php
@@ -17,13 +17,21 @@ public function index(Request $request): JsonResponse
if ($search = $request->input('search')) {
$query->where(function ($q) use ($search) {
$q->where('customer', 'like', "%{$search}%")
- ->orWhere('description', 'like', "%{$search}%");
+ ->orWhere('description', 'like', "%{$search}%");
});
}
- if ($status = $request->input('status')) { if ($status !== 'all') $query->where('status', $status); }
- if ($category = $request->input('category')) { if ($category !== 'all') $query->where('category', $category); }
+ if ($status = $request->input('status')) {
+ if ($status !== 'all') {
+ $query->where('status', $status);
+ }
+ }
+ if ($category = $request->input('category')) {
+ if ($category !== 'all') {
+ $query->where('category', $category);
+ }
+ }
- $incomes = $query->orderBy('date', 'desc')->get()->map(fn($item) => [
+ $incomes = $query->orderBy('date', 'desc')->get()->map(fn ($item) => [
'id' => $item->id, 'date' => $item->date?->format('Y-m-d'),
'customer' => $item->customer, 'description' => $item->description,
'category' => $item->category, 'amount' => $item->amount,
@@ -80,6 +88,7 @@ public function destroy(int $id): JsonResponse
{
$tenantId = session('selected_tenant_id', 1);
Income::forTenant($tenantId)->findOrFail($id)->delete();
+
return response()->json(['success' => true, 'message' => '수입이 삭제되었습니다.']);
}
}
diff --git a/app/Http/Controllers/Finance/PurchaseController.php b/app/Http/Controllers/Finance/PurchaseController.php
index 308a9162..465d58aa 100644
--- a/app/Http/Controllers/Finance/PurchaseController.php
+++ b/app/Http/Controllers/Finance/PurchaseController.php
@@ -17,17 +17,21 @@ public function index(Request $request): JsonResponse
if ($search = $request->input('search')) {
$query->where(function ($q) use ($search) {
$q->where('vendor', 'like', "%{$search}%")
- ->orWhere('item', 'like', "%{$search}%");
+ ->orWhere('item', 'like', "%{$search}%");
});
}
if ($status = $request->input('status')) {
- if ($status !== 'all') $query->where('status', $status);
+ if ($status !== 'all') {
+ $query->where('status', $status);
+ }
}
if ($category = $request->input('category')) {
- if ($category !== 'all') $query->where('category', $category);
+ if ($category !== 'all') {
+ $query->where('category', $category);
+ }
}
- $purchases = $query->orderBy('date', 'desc')->get()->map(fn($item) => [
+ $purchases = $query->orderBy('date', 'desc')->get()->map(fn ($item) => [
'id' => $item->id, 'date' => $item->date?->format('Y-m-d'),
'vendor' => $item->vendor, 'item' => $item->item,
'category' => $item->category, 'amount' => $item->amount,
@@ -85,6 +89,7 @@ public function destroy(int $id): JsonResponse
{
$tenantId = session('selected_tenant_id', 1);
Purchase::forTenant($tenantId)->findOrFail($id)->delete();
+
return response()->json(['success' => true, 'message' => '매입이 삭제되었습니다.']);
}
}
diff --git a/app/Http/Controllers/Finance/RefundController.php b/app/Http/Controllers/Finance/RefundController.php
index 83938748..85600fed 100644
--- a/app/Http/Controllers/Finance/RefundController.php
+++ b/app/Http/Controllers/Finance/RefundController.php
@@ -18,7 +18,7 @@ public function index(Request $request): JsonResponse
if ($search = $request->input('search')) {
$query->where(function ($q) use ($search) {
$q->where('customer_name', 'like', "%{$search}%")
- ->orWhere('product_name', 'like', "%{$search}%");
+ ->orWhere('product_name', 'like', "%{$search}%");
});
}
diff --git a/app/Http/Controllers/Finance/SalesCommissionController.php b/app/Http/Controllers/Finance/SalesCommissionController.php
index 3f915077..aeb9a532 100644
--- a/app/Http/Controllers/Finance/SalesCommissionController.php
+++ b/app/Http/Controllers/Finance/SalesCommissionController.php
@@ -27,7 +27,7 @@ public function __construct(
public function index(Request $request): View|Response
{
// HTMX 요청 시 전체 페이지로 리다이렉트 (JavaScript 필요)
- if ($request->header('HX-Request') && !$request->header('HX-Boosted')) {
+ if ($request->header('HX-Request') && ! $request->header('HX-Boosted')) {
return response('', 200)->header('HX-Redirect', route('finance.sales-commissions.index'));
}
@@ -77,7 +77,7 @@ public function show(int $id): JsonResponse
{
$commission = $this->service->getCommissionById($id);
- if (!$commission) {
+ if (! $commission) {
return response()->json([
'success' => false,
'message' => '정산 정보를 찾을 수 없습니다.',
@@ -377,9 +377,9 @@ public function export(Request $request)
// 전체 데이터 조회 (페이지네이션 없이)
$commissions = SalesCommission::query()
->with(['tenant', 'partner.user', 'manager'])
- ->when(!empty($filters['status']), fn($q) => $q->where('status', $filters['status']))
- ->when(!empty($filters['payment_type']), fn($q) => $q->where('payment_type', $filters['payment_type']))
- ->when(!empty($filters['partner_id']), fn($q) => $q->where('partner_id', $filters['partner_id']))
+ ->when(! empty($filters['status']), fn ($q) => $q->where('status', $filters['status']))
+ ->when(! empty($filters['payment_type']), fn ($q) => $q->where('payment_type', $filters['payment_type']))
+ ->when(! empty($filters['partner_id']), fn ($q) => $q->where('partner_id', $filters['partner_id']))
->forScheduledMonth($year, $month)
->orderBy('scheduled_payment_date')
->get();
@@ -402,7 +402,7 @@ public function export(Request $request)
fputcsv($file, [
'번호', '테넌트', '입금구분', '입금액', '입금일',
'기준액', '영업파트너', '파트너수당', '매니저', '매니저수당',
- '지급예정일', '상태', '실제지급일'
+ '지급예정일', '상태', '실제지급일',
]);
// 데이터
diff --git a/app/Http/Controllers/Finance/SalesRecordController.php b/app/Http/Controllers/Finance/SalesRecordController.php
index 4f00b582..2b293841 100644
--- a/app/Http/Controllers/Finance/SalesRecordController.php
+++ b/app/Http/Controllers/Finance/SalesRecordController.php
@@ -17,17 +17,21 @@ public function index(Request $request): JsonResponse
if ($search = $request->input('search')) {
$query->where(function ($q) use ($search) {
$q->where('customer', 'like', "%{$search}%")
- ->orWhere('project', 'like', "%{$search}%");
+ ->orWhere('project', 'like', "%{$search}%");
});
}
if ($status = $request->input('status')) {
- if ($status !== 'all') $query->where('status', $status);
+ if ($status !== 'all') {
+ $query->where('status', $status);
+ }
}
if ($type = $request->input('type')) {
- if ($type !== 'all') $query->where('type', $type);
+ if ($type !== 'all') {
+ $query->where('type', $type);
+ }
}
- $records = $query->orderBy('date', 'desc')->get()->map(fn($item) => [
+ $records = $query->orderBy('date', 'desc')->get()->map(fn ($item) => [
'id' => $item->id, 'date' => $item->date?->format('Y-m-d'),
'customer' => $item->customer, 'project' => $item->project,
'type' => $item->type, 'taxType' => $item->tax_type ?? 'taxable',
@@ -93,6 +97,7 @@ public function destroy(int $id): JsonResponse
{
$tenantId = session('selected_tenant_id', 1);
SalesRecord::forTenant($tenantId)->findOrFail($id)->delete();
+
return response()->json(['success' => true, 'message' => '매출이 삭제되었습니다.']);
}
}
diff --git a/app/Http/Controllers/Finance/SubscriptionController.php b/app/Http/Controllers/Finance/SubscriptionController.php
index cbb5ed21..862af3b2 100644
--- a/app/Http/Controllers/Finance/SubscriptionController.php
+++ b/app/Http/Controllers/Finance/SubscriptionController.php
@@ -20,10 +20,12 @@ public function index(Request $request): JsonResponse
});
}
if ($status = $request->input('status')) {
- if ($status !== 'all') $query->where('status', $status);
+ if ($status !== 'all') {
+ $query->where('status', $status);
+ }
}
- $subscriptions = $query->orderBy('created_at', 'desc')->get()->map(fn($item) => [
+ $subscriptions = $query->orderBy('created_at', 'desc')->get()->map(fn ($item) => [
'id' => $item->id, 'customer' => $item->customer,
'plan' => $item->plan, 'monthlyFee' => $item->monthly_fee,
'billingCycle' => $item->billing_cycle,
@@ -87,6 +89,7 @@ public function destroy(int $id): JsonResponse
{
$tenantId = session('selected_tenant_id', 1);
Subscription::forTenant($tenantId)->findOrFail($id)->delete();
+
return response()->json(['success' => true, 'message' => '구독이 삭제되었습니다.']);
}
}
diff --git a/app/Http/Controllers/Finance/TradingPartnerController.php b/app/Http/Controllers/Finance/TradingPartnerController.php
index bc62ce27..69313e6d 100644
--- a/app/Http/Controllers/Finance/TradingPartnerController.php
+++ b/app/Http/Controllers/Finance/TradingPartnerController.php
@@ -19,8 +19,8 @@ public function index(Request $request): JsonResponse
if ($search = $request->input('search')) {
$query->where(function ($q) use ($search) {
$q->where('name', 'like', "%{$search}%")
- ->orWhere('ceo', 'like', "%{$search}%")
- ->orWhere('manager', 'like', "%{$search}%");
+ ->orWhere('ceo', 'like', "%{$search}%")
+ ->orWhere('manager', 'like', "%{$search}%");
});
}
diff --git a/app/Http/Controllers/Finance/VatRecordController.php b/app/Http/Controllers/Finance/VatRecordController.php
index 8a3d32bd..321c3ae5 100644
--- a/app/Http/Controllers/Finance/VatRecordController.php
+++ b/app/Http/Controllers/Finance/VatRecordController.php
@@ -3,11 +3,11 @@
namespace App\Http\Controllers\Finance;
use App\Http\Controllers\Controller;
-use App\Models\Finance\VatRecord;
use App\Models\Barobill\CardTransaction as BarobillCardTransaction;
-use App\Models\Barobill\CardTransactionSplit;
use App\Models\Barobill\CardTransactionHide;
+use App\Models\Barobill\CardTransactionSplit;
use App\Models\Barobill\HometaxInvoice;
+use App\Models\Finance\VatRecord;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -43,7 +43,7 @@ public function index(Request $request): JsonResponse
$hometaxSalesRecords = $hometaxSales->map(function ($inv) use ($period, $taxTypeMap) {
return [
- 'id' => 'hometax_' . $inv->id,
+ 'id' => 'hometax_'.$inv->id,
'period' => $period,
'type' => 'sales',
'taxType' => $taxTypeMap[$inv->tax_type] ?? 'taxable',
@@ -69,7 +69,7 @@ public function index(Request $request): JsonResponse
$hometaxPurchaseRecords = $hometaxPurchases->map(function ($inv) use ($period, $taxTypeMap) {
return [
- 'id' => 'hometax_' . $inv->id,
+ 'id' => 'hometax_'.$inv->id,
'period' => $period,
'type' => 'purchase',
'taxType' => $taxTypeMap[$inv->tax_type] ?? 'taxable',
@@ -104,7 +104,7 @@ public function index(Request $request): JsonResponse
foreach ($splitsByKey as $fullKey => $splits) {
$parts = explode('|', $fullKey);
if (count($parts) >= 3) {
- $partialKey = $parts[0] . '|' . $parts[1] . '|' . $parts[2];
+ $partialKey = $parts[0].'|'.$parts[1].'|'.$parts[2];
$splitsByPartialKey[$partialKey] = $splits;
}
}
@@ -117,8 +117,8 @@ public function index(Request $request): JsonResponse
// 분개 매칭: 정확한 키 → 부분키(금액 제외) 순으로 시도
$splits = $splitsByKey[$card->unique_key] ?? null;
- if (!$splits) {
- $cardPartialKey = $card->card_num . '|' . $card->use_dt . '|' . $card->approval_num;
+ if (! $splits) {
+ $cardPartialKey = $card->card_num.'|'.$card->use_dt.'|'.$card->approval_num;
$splits = $splitsByPartialKey[$cardPartialKey] ?? null;
}
@@ -127,7 +127,7 @@ public function index(Request $request): JsonResponse
foreach ($splits as $split) {
if ($split->deduction_type === 'deductible') {
$cardRecords->push([
- 'id' => 'card_split_' . $split->id,
+ 'id' => 'card_split_'.$split->id,
'period' => $period,
'type' => 'purchase',
'taxType' => 'taxable',
@@ -153,7 +153,7 @@ public function index(Request $request): JsonResponse
$effectiveTax = $card->modified_tax ?? $card->tax;
$cardRecords->push([
- 'id' => 'card_' . $card->id,
+ 'id' => 'card_'.$card->id,
'period' => $period,
'type' => 'purchase',
'taxType' => 'taxable',
@@ -269,13 +269,13 @@ public function index(Request $request): JsonResponse
// 확정(C) 기간이면 대응하는 예정(P)의 netVat를 계산
if ($period && str_ends_with($period, 'C')) {
try {
- $prelimPeriod = substr($period, 0, -1) . 'P';
+ $prelimPeriod = substr($period, 0, -1).'P';
$stats['preliminaryVat'] = $this->calculatePeriodNetVat($tenantId, $prelimPeriod);
} catch (\Throwable $e) {
\Log::error('예정 세액 계산 실패', [
'message' => $e->getMessage(),
- 'file' => $e->getFile() . ':' . $e->getLine(),
- 'trace' => array_slice(array_map(fn($t) => ($t['file'] ?? '') . ':' . ($t['line'] ?? '') . ' ' . ($t['function'] ?? ''), $e->getTrace()), 0, 5),
+ 'file' => $e->getFile().':'.$e->getLine(),
+ 'trace' => array_slice(array_map(fn ($t) => ($t['file'] ?? '').':'.($t['line'] ?? '').' '.($t['function'] ?? ''), $e->getTrace()), 0, 5),
'tenant_id' => $tenantId,
'period' => $prelimPeriod ?? null,
]);
@@ -385,7 +385,7 @@ public function destroy(int $id): JsonResponse
private function calculatePeriodNetVat(int $tenantId, string $period): int
{
[$startDate, $endDate] = $this->periodToDateRange($period);
- if (!$startDate || !$endDate) {
+ if (! $startDate || ! $endDate) {
return 0;
}
@@ -422,7 +422,7 @@ private function calculatePeriodNetVat(int $tenantId, string $period): int
foreach ($splitsByKey as $fullKey => $splits) {
$parts = explode('|', $fullKey);
if (count($parts) >= 3) {
- $partialKey = $parts[0] . '|' . $parts[1] . '|' . $parts[2];
+ $partialKey = $parts[0].'|'.$parts[1].'|'.$parts[2];
$splitsByPartialKey[$partialKey] = $splits;
}
}
@@ -433,8 +433,8 @@ private function calculatePeriodNetVat(int $tenantId, string $period): int
}
$splits = $splitsByKey[$card->unique_key] ?? null;
- if (!$splits) {
- $cardPartialKey = $card->card_num . '|' . $card->use_dt . '|' . $card->approval_num;
+ if (! $splits) {
+ $cardPartialKey = $card->card_num.'|'.$card->use_dt.'|'.$card->approval_num;
$splits = $splitsByPartialKey[$cardPartialKey] ?? null;
}
diff --git a/app/Http/Controllers/Finance/VehicleLogController.php b/app/Http/Controllers/Finance/VehicleLogController.php
index 9c568b5e..dea385f9 100644
--- a/app/Http/Controllers/Finance/VehicleLogController.php
+++ b/app/Http/Controllers/Finance/VehicleLogController.php
@@ -71,10 +71,10 @@ public function list(Request $request): JsonResponse
$search = $request->search;
$query->where(function ($q) use ($search) {
$q->where('driver_name', 'like', "%{$search}%")
- ->orWhere('department', 'like', "%{$search}%")
- ->orWhere('departure_name', 'like', "%{$search}%")
- ->orWhere('arrival_name', 'like', "%{$search}%")
- ->orWhere('note', 'like', "%{$search}%");
+ ->orWhere('department', 'like', "%{$search}%")
+ ->orWhere('departure_name', 'like', "%{$search}%")
+ ->orWhere('arrival_name', 'like', "%{$search}%")
+ ->orWhere('note', 'like', "%{$search}%");
});
}
@@ -233,9 +233,9 @@ public function summary(Request $request): JsonResponse
COUNT(*) as count,
SUM(distance_km) as total_distance
')
- ->groupBy('trip_type')
- ->get()
- ->keyBy('trip_type');
+ ->groupBy('trip_type')
+ ->get()
+ ->keyBy('trip_type');
$tripTypes = VehicleLog::getTripTypes();
$result = [];
diff --git a/app/Http/Controllers/Finance/VehicleMaintenanceController.php b/app/Http/Controllers/Finance/VehicleMaintenanceController.php
index 12eb8802..c4c6ad38 100644
--- a/app/Http/Controllers/Finance/VehicleMaintenanceController.php
+++ b/app/Http/Controllers/Finance/VehicleMaintenanceController.php
@@ -71,8 +71,8 @@ public function list(Request $request): JsonResponse
$search = $request->search;
$query->where(function ($q) use ($search) {
$q->where('description', 'like', "%{$search}%")
- ->orWhere('vendor', 'like', "%{$search}%")
- ->orWhere('memo', 'like', "%{$search}%");
+ ->orWhere('vendor', 'like', "%{$search}%")
+ ->orWhere('memo', 'like', "%{$search}%");
});
}
diff --git a/app/Http/Controllers/Juil/ConstructionSitePhotoController.php b/app/Http/Controllers/Juil/ConstructionSitePhotoController.php
index c6cb5f25..8063a176 100644
--- a/app/Http/Controllers/Juil/ConstructionSitePhotoController.php
+++ b/app/Http/Controllers/Juil/ConstructionSitePhotoController.php
@@ -43,7 +43,7 @@ public function show(int $id): JsonResponse
{
$photo = ConstructionSitePhoto::with(['user', 'rows'])->find($id);
- if (!$photo) {
+ if (! $photo) {
return response()->json([
'success' => false,
'message' => '사진대지를 찾을 수 없습니다.',
@@ -77,7 +77,7 @@ public function uploadPhoto(Request $request, int $id, int $rowId): JsonResponse
{
$photo = ConstructionSitePhoto::find($id);
- if (!$photo) {
+ if (! $photo) {
return response()->json([
'success' => false,
'message' => '사진대지를 찾을 수 없습니다.',
@@ -88,7 +88,7 @@ public function uploadPhoto(Request $request, int $id, int $rowId): JsonResponse
->where('construction_site_photo_id', $id)
->first();
- if (!$row) {
+ if (! $row) {
return response()->json([
'success' => false,
'message' => '사진 행을 찾을 수 없습니다.',
@@ -102,7 +102,7 @@ public function uploadPhoto(Request $request, int $id, int $rowId): JsonResponse
$result = $this->service->uploadPhoto($row, $request->file('photo'), $validated['type']);
- if (!$result) {
+ if (! $result) {
return response()->json([
'success' => false,
'message' => '사진 업로드에 실패했습니다.',
@@ -120,7 +120,7 @@ public function update(Request $request, int $id): JsonResponse
{
$photo = ConstructionSitePhoto::find($id);
- if (!$photo) {
+ if (! $photo) {
return response()->json([
'success' => false,
'message' => '사진대지를 찾을 수 없습니다.',
@@ -146,7 +146,7 @@ public function destroy(int $id): JsonResponse
{
$photo = ConstructionSitePhoto::with('rows')->find($id);
- if (!$photo) {
+ if (! $photo) {
return response()->json([
'success' => false,
'message' => '사진대지를 찾을 수 없습니다.',
@@ -165,7 +165,7 @@ public function deletePhoto(int $id, int $rowId, string $type): JsonResponse
{
$photo = ConstructionSitePhoto::find($id);
- if (!$photo) {
+ if (! $photo) {
return response()->json([
'success' => false,
'message' => '사진대지를 찾을 수 없습니다.',
@@ -176,14 +176,14 @@ public function deletePhoto(int $id, int $rowId, string $type): JsonResponse
->where('construction_site_photo_id', $id)
->first();
- if (!$row) {
+ if (! $row) {
return response()->json([
'success' => false,
'message' => '사진 행을 찾을 수 없습니다.',
], 404);
}
- if (!in_array($type, ['before', 'during', 'after'])) {
+ if (! in_array($type, ['before', 'during', 'after'])) {
return response()->json([
'success' => false,
'message' => '올바르지 않은 사진 유형입니다.',
@@ -203,7 +203,7 @@ public function downloadPhoto(Request $request, int $id, int $rowId, string $typ
{
$photo = ConstructionSitePhoto::find($id);
- if (!$photo) {
+ if (! $photo) {
return response()->json([
'success' => false,
'message' => '사진대지를 찾을 수 없습니다.',
@@ -214,23 +214,23 @@ public function downloadPhoto(Request $request, int $id, int $rowId, string $typ
->where('construction_site_photo_id', $id)
->first();
- if (!$row) {
+ if (! $row) {
return response()->json([
'success' => false,
'message' => '사진 행을 찾을 수 없습니다.',
], 404);
}
- if (!in_array($type, ['before', 'during', 'after'])) {
+ if (! in_array($type, ['before', 'during', 'after'])) {
return response()->json([
'success' => false,
'message' => '올바르지 않은 사진 유형입니다.',
], 422);
}
- $path = $row->{$type . '_photo_path'};
+ $path = $row->{$type.'_photo_path'};
- if (!$path) {
+ if (! $path) {
return response()->json([
'success' => false,
'message' => '파일을 찾을 수 없습니다.',
@@ -240,7 +240,7 @@ public function downloadPhoto(Request $request, int $id, int $rowId, string $typ
$googleCloudService = app(GoogleCloudService::class);
$content = $googleCloudService->downloadFromStorage($path);
- if (!$content) {
+ if (! $content) {
return response()->json([
'success' => false,
'message' => '파일 다운로드에 실패했습니다.',
@@ -248,7 +248,7 @@ public function downloadPhoto(Request $request, int $id, int $rowId, string $typ
}
$extension = pathinfo($path, PATHINFO_EXTENSION) ?: 'jpg';
- $mimeType = 'image/' . ($extension === 'jpg' ? 'jpeg' : $extension);
+ $mimeType = 'image/'.($extension === 'jpg' ? 'jpeg' : $extension);
$typeLabel = match ($type) {
'before' => '작업전',
@@ -273,7 +273,7 @@ public function addRow(int $id): JsonResponse
{
$photo = ConstructionSitePhoto::find($id);
- if (!$photo) {
+ if (! $photo) {
return response()->json([
'success' => false,
'message' => '사진대지를 찾을 수 없습니다.',
@@ -293,7 +293,7 @@ public function deleteRow(int $id, int $rowId): JsonResponse
{
$photo = ConstructionSitePhoto::with('rows')->find($id);
- if (!$photo) {
+ if (! $photo) {
return response()->json([
'success' => false,
'message' => '사진대지를 찾을 수 없습니다.',
@@ -309,7 +309,7 @@ public function deleteRow(int $id, int $rowId): JsonResponse
$row = $photo->rows->firstWhere('id', $rowId);
- if (!$row) {
+ if (! $row) {
return response()->json([
'success' => false,
'message' => '사진 행을 찾을 수 없습니다.',
diff --git a/app/Http/Controllers/Juil/MeetingMinuteController.php b/app/Http/Controllers/Juil/MeetingMinuteController.php
index 309b9313..7f2a693c 100644
--- a/app/Http/Controllers/Juil/MeetingMinuteController.php
+++ b/app/Http/Controllers/Juil/MeetingMinuteController.php
@@ -2,7 +2,6 @@
namespace App\Http\Controllers\Juil;
-use App\Helpers\AiTokenHelper;
use App\Http\Controllers\Controller;
use App\Models\Juil\MeetingMinute;
use App\Services\GoogleCloudService;
@@ -172,7 +171,7 @@ public function saveSegments(Request $request, int $id): JsonResponse
return response()->json([
'success' => false,
- 'message' => '세그먼트 저장 중 오류가 발생했습니다: ' . $e->getMessage(),
+ 'message' => '세그먼트 저장 중 오류가 발생했습니다: '.$e->getMessage(),
], 500);
}
}
@@ -310,7 +309,7 @@ public function downloadAudio(Request $request, int $id): Response|JsonResponse
}
$extension = pathinfo($meeting->audio_file_path, PATHINFO_EXTENSION) ?: 'webm';
- $mimeType = 'audio/' . $extension;
+ $mimeType = 'audio/'.$extension;
$safeTitle = preg_replace('/[\/\\\\:*?"<>|]/', '_', $meeting->title);
$filename = "{$safeTitle}.{$extension}";
diff --git a/app/Http/Controllers/Lab/StrategyController.php b/app/Http/Controllers/Lab/StrategyController.php
index 94785cc5..95e9a4b8 100644
--- a/app/Http/Controllers/Lab/StrategyController.php
+++ b/app/Http/Controllers/Lab/StrategyController.php
@@ -22,6 +22,7 @@ private function handlePresentationPage(Request $request, string $routeName): ?R
if ($request->header('HX-Request')) {
return response('', 200)->header('HX-Redirect', route($routeName));
}
+
return null;
}
@@ -33,6 +34,7 @@ public function labor(Request $request): View|Response
if ($request->header('HX-Request')) {
return response('', 200)->header('HX-Redirect', route('lab.strategy.labor'));
}
+
return view('lab.strategy.labor');
}
@@ -44,6 +46,7 @@ public function chatbot(Request $request): View|Response
if ($request->header('HX-Request')) {
return response('', 200)->header('HX-Redirect', route('lab.strategy.chatbot'));
}
+
return view('lab.strategy.chatbot');
}
@@ -55,6 +58,7 @@ public function knowledgeSearch(Request $request): View|Response
if ($request->header('HX-Request')) {
return response('', 200)->header('HX-Redirect', route('lab.strategy.knowledge-search'));
}
+
return view('lab.strategy.knowledge-search');
}
@@ -66,6 +70,7 @@ public function chatbotCompare(Request $request): View|Response
if ($request->header('HX-Request')) {
return response('', 200)->header('HX-Redirect', route('lab.strategy.chatbot-compare'));
}
+
return view('lab.strategy.chatbot-compare');
}
@@ -77,6 +82,7 @@ public function ragStartups(Request $request): View|Response
if ($request->header('HX-Request')) {
return response('', 200)->header('HX-Redirect', route('lab.strategy.rag-startups'));
}
+
return view('lab.strategy.rag-startups');
}
@@ -88,6 +94,7 @@ public function douzone(Request $request): View|Response
if ($request->header('HX-Request')) {
return response('', 200)->header('HX-Redirect', route('lab.strategy.douzone'));
}
+
return view('lab.strategy.douzone');
}
@@ -99,6 +106,7 @@ public function confluenceVsNotion(Request $request): View|Response
if ($request->header('HX-Request')) {
return response('', 200)->header('HX-Redirect', route('lab.strategy.confluence-vs-notion'));
}
+
return view('lab.strategy.confluence-vs-notion');
}
@@ -110,6 +118,7 @@ public function salesStrategy(Request $request): View|Response
if ($request->header('HX-Request')) {
return response('', 200)->header('HX-Redirect', route('lab.strategy.sales-strategy'));
}
+
return view('lab.strategy.sales-strategy');
}
}
diff --git a/app/Http/Controllers/MenuSyncController.php b/app/Http/Controllers/MenuSyncController.php
index 389fa1ea..3745e366 100644
--- a/app/Http/Controllers/MenuSyncController.php
+++ b/app/Http/Controllers/MenuSyncController.php
@@ -21,6 +21,7 @@ class MenuSyncController extends Controller
protected function getTenantId(): int
{
$tenantId = session('selected_tenant_id');
+
return ($tenantId && $tenantId !== 'all') ? (int) $tenantId : 1;
}
@@ -229,7 +230,7 @@ public function push(Request $request): JsonResponse
$response = Http::withHeaders([
'X-Menu-Sync-Key' => $env['api_key'],
'Accept' => 'application/json',
- ])->post(rtrim($env['url'], '/') . '/menu-sync/import', [
+ ])->post(rtrim($env['url'], '/').'/menu-sync/import', [
'menus' => $menuData,
]);
@@ -244,7 +245,7 @@ public function push(Request $request): JsonResponse
'error' => $response->json('error', '원격 서버 오류'),
], $response->status());
} catch (\Exception $e) {
- return response()->json(['error' => '연결 실패: ' . $e->getMessage()], 500);
+ return response()->json(['error' => '연결 실패: '.$e->getMessage()], 500);
}
}
@@ -307,10 +308,11 @@ public function testConnection(Request $request): JsonResponse
$response = Http::withHeaders([
'X-Menu-Sync-Key' => $validated['api_key'],
'Accept' => 'application/json',
- ])->timeout(10)->get(rtrim($validated['url'], '/') . '/menu-sync/export');
+ ])->timeout(10)->get(rtrim($validated['url'], '/').'/menu-sync/export');
if ($response->successful()) {
$data = $response->json();
+
return response()->json([
'success' => true,
'message' => '연결 성공',
@@ -321,12 +323,12 @@ public function testConnection(Request $request): JsonResponse
return response()->json([
'success' => false,
- 'message' => 'API 오류: ' . $response->status(),
+ 'message' => 'API 오류: '.$response->status(),
]);
} catch (\Exception $e) {
return response()->json([
'success' => false,
- 'message' => '연결 실패: ' . $e->getMessage(),
+ 'message' => '연결 실패: '.$e->getMessage(),
]);
}
}
@@ -394,12 +396,12 @@ private function fetchRemoteMenus(array $env): array
$response = Http::withHeaders([
'X-Menu-Sync-Key' => $env['api_key'],
'Accept' => 'application/json',
- ])->timeout(10)->get(rtrim($env['url'], '/') . '/menu-sync/export', [
+ ])->timeout(10)->get(rtrim($env['url'], '/').'/menu-sync/export', [
'tenant_id' => $this->getTenantId(), // 현재 선택된 테넌트 전달
]);
if (! $response->successful()) {
- throw new \Exception('API 오류: HTTP ' . $response->status());
+ throw new \Exception('API 오류: HTTP '.$response->status());
}
$data = $response->json();
@@ -440,6 +442,7 @@ private function flattenMenuNames(array $menus, string $prefix = ''): array
$names = array_merge($names, $this->flattenMenuNames($menu['children'], $fullName));
}
}
+
return $names;
}
diff --git a/app/Http/Controllers/Sales/AdminProspectController.php b/app/Http/Controllers/Sales/AdminProspectController.php
index c13bb327..a0671c80 100644
--- a/app/Http/Controllers/Sales/AdminProspectController.php
+++ b/app/Http/Controllers/Sales/AdminProspectController.php
@@ -25,7 +25,7 @@ class AdminProspectController extends Controller
*/
private function checkAdminAccess(): void
{
- if (!auth()->user()->isAdmin() && !auth()->user()->isSuperAdmin()) {
+ if (! auth()->user()->isAdmin() && ! auth()->user()->isSuperAdmin()) {
abort(403, '관리자만 접근할 수 있습니다.');
}
}
@@ -45,7 +45,7 @@ private function getPaymentTypeForField(string $field): string
*/
private function loadMergedCommission(?SalesTenantManagement $management): ?object
{
- if (!$management) {
+ if (! $management) {
return null;
}
@@ -58,12 +58,12 @@ private function loadMergedCommission(?SalesTenantManagement $management): ?obje
$balance = $commissions->firstWhere('payment_type', SalesCommission::PAYMENT_BALANCE);
// balance 레코드가 없으면 기존 단일 레코드 그대로 반환 (하위호환)
- if (!$balance) {
+ if (! $balance) {
return $deposit ?? $commissions->first();
}
// 1차 필드는 deposit, 2차 필드는 balance에서 가져옴
- $merged = new \stdClass();
+ $merged = new \stdClass;
$merged->first_payment_at = $deposit?->first_payment_at;
$merged->first_partner_paid_at = $deposit?->first_partner_paid_at;
$merged->second_payment_at = $balance->second_payment_at;
@@ -118,7 +118,7 @@ public function modalShow(int $id): View
// 파트너 타입
$partnerType = $management->salesPartner?->partner_type;
- if (!$partnerType && $prospect->registered_by) {
+ if (! $partnerType && $prospect->registered_by) {
$partnerType = SalesPartner::where('user_id', $prospect->registered_by)->value('partner_type');
}
$partnerType = $partnerType ?? 'individual';
@@ -161,7 +161,7 @@ private function getIndexData(Request $request): array
$query = TenantProspect::with(['registeredBy', 'tenant']);
// 검색
- if (!empty($filters['search'])) {
+ if (! empty($filters['search'])) {
$search = $filters['search'];
$query->where(function ($q) use ($search) {
$q->where('company_name', 'like', "%{$search}%")
@@ -174,7 +174,7 @@ private function getIndexData(Request $request): array
// 상태 필터
$isProgressCompleteFilter = ($filters['status'] === 'progress_complete');
$isHandoverFilter = ($filters['status'] === 'handover');
- if (!empty($filters['status']) && !$isProgressCompleteFilter && !$isHandoverFilter) {
+ if (! empty($filters['status']) && ! $isProgressCompleteFilter && ! $isHandoverFilter) {
$query->where('status', $filters['status']);
}
@@ -185,7 +185,7 @@ private function getIndexData(Request $request): array
}
// 영업파트너 필터
- if (!empty($filters['registered_by'])) {
+ if (! empty($filters['registered_by'])) {
$query->where('registered_by', $filters['registered_by']);
}
@@ -215,7 +215,7 @@ private function getIndexData(Request $request): array
// 파트너 타입: management → registered_by 순으로 조회
$partnerType = $management?->salesPartner?->partner_type;
- if (!$partnerType && $prospect->registered_by) {
+ if (! $partnerType && $prospect->registered_by) {
$partnerType = SalesPartner::where('user_id', $prospect->registered_by)->value('partner_type');
}
$prospect->partner_type = $partnerType ?? 'individual';
@@ -264,7 +264,7 @@ private function getIndexData(Request $request): array
// 파트너 타입: management → registered_by 순으로 조회
$partnerType = $management?->salesPartner?->partner_type;
- if (!$partnerType && $prospect->registered_by) {
+ if (! $partnerType && $prospect->registered_by) {
$partnerType = SalesPartner::where('user_id', $prospect->registered_by)->value('partner_type');
}
$prospect->partner_type = $partnerType ?? 'individual';
@@ -314,7 +314,7 @@ public function updateHqStatus(int $id, Request $request)
$this->checkAdminAccess();
$request->validate([
- 'hq_status' => 'required|in:' . implode(',', array_keys(SalesTenantManagement::$hqStatusLabels)),
+ 'hq_status' => 'required|in:'.implode(',', array_keys(SalesTenantManagement::$hqStatusLabels)),
]);
$prospect = TenantProspect::findOrFail($id);
@@ -410,7 +410,7 @@ public function updateCommissionDate(int $id, Request $request)
// 파트너 resolve → 요율 결정
$partner = $management->salesPartner;
- if (!$partner && $prospect->registered_by) {
+ if (! $partner && $prospect->registered_by) {
$partner = SalesPartner::where('user_id', $prospect->registered_by)->first();
}
$isGroup = $partner?->isGroup() ?? false;
@@ -557,7 +557,7 @@ public function updateReferrerCommission(int $id, Request $request)
// 단체 파트너는 수동 수정 불가
$partner = $management->salesPartner;
- if (!$partner && $prospect->registered_by) {
+ if (! $partner && $prospect->registered_by) {
$partner = SalesPartner::where('user_id', $prospect->registered_by)->first();
}
if ($partner && $partner->isGroup()) {
@@ -619,7 +619,7 @@ public function clearCommissionDate(int $id, Request $request)
$prospect = TenantProspect::findOrFail($id);
$management = SalesTenantManagement::where('tenant_prospect_id', $prospect->id)->first();
- if (!$management) {
+ if (! $management) {
return response()->json(['success' => false, 'message' => '관리 정보가 없습니다.']);
}
@@ -632,7 +632,7 @@ public function clearCommissionDate(int $id, Request $request)
->where('payment_type', $paymentType)
->first();
- if (!$commission) {
+ if (! $commission) {
return response()->json(['success' => false, 'message' => '수당 정보가 없습니다.']);
}
$updateData = [$field => null];
diff --git a/app/Http/Controllers/Sales/ConsultationController.php b/app/Http/Controllers/Sales/ConsultationController.php
index 40265ddb..d2f3308d 100644
--- a/app/Http/Controllers/Sales/ConsultationController.php
+++ b/app/Http/Controllers/Sales/ConsultationController.php
@@ -114,7 +114,7 @@ public function uploadAudio(Request $request, GoogleCloudStorageService $gcs): J
// 파일 저장
$file = $request->file('audio');
- $fileName = 'audio_' . now()->format('Ymd_His') . '_' . uniqid() . '.' . $file->getClientOriginalExtension();
+ $fileName = 'audio_'.now()->format('Ymd_His').'_'.uniqid().'.'.$file->getClientOriginalExtension();
$localPath = $file->storeAs("tenant/consultations/{$tenantId}", $fileName, 'local');
$fileSize = $file->getSize();
@@ -154,7 +154,7 @@ public function uploadAudio(Request $request, GoogleCloudStorageService $gcs): J
'formatted_duration' => $consultation->formatted_duration,
'created_by_name' => $consultation->creator->name,
'created_at' => $consultation->created_at->format('Y-m-d H:i'),
- 'has_gcs' => !empty($gcsUri),
+ 'has_gcs' => ! empty($gcsUri),
],
]);
}
@@ -178,7 +178,7 @@ public function uploadFile(Request $request): JsonResponse
// 파일 저장
$file = $request->file('file');
$originalName = $file->getClientOriginalName();
- $fileName = now()->format('Ymd_His') . '_' . uniqid() . '_' . $originalName;
+ $fileName = now()->format('Ymd_His').'_'.uniqid().'_'.$originalName;
$path = $file->storeAs("tenant/attachments/{$tenantId}", $fileName, 'local');
// DB에 저장
@@ -229,7 +229,7 @@ public function downloadAudio(int $consultationId, GoogleCloudStorageService $gc
// GCS에 저장된 경우 서명된 URL로 리다이렉트
if ($consultation->gcs_uri) {
- $objectName = str_replace('gs://' . $gcs->getBucketName() . '/', '', $consultation->gcs_uri);
+ $objectName = str_replace('gs://'.$gcs->getBucketName().'/', '', $consultation->gcs_uri);
$signedUrl = $gcs->getSignedUrl($objectName, 60);
if ($signedUrl) {
@@ -240,7 +240,7 @@ public function downloadAudio(int $consultationId, GoogleCloudStorageService $gc
// 로컬 파일 다운로드
$localPath = Storage::disk('local')->path($consultation->file_path);
- if (!file_exists($localPath)) {
+ if (! file_exists($localPath)) {
abort(404, '파일을 찾을 수 없습니다.');
}
@@ -250,11 +250,11 @@ public function downloadAudio(int $consultationId, GoogleCloudStorageService $gc
'wav' => 'audio/wav',
'mp3' => 'audio/mpeg',
'ogg' => 'audio/ogg',
- 'm4a' => 'audio/mp4'
+ 'm4a' => 'audio/mp4',
];
$contentType = $mimeTypes[$extension] ?? 'audio/webm';
- $downloadFileName = '상담녹음_' . $consultation->created_at->format('Ymd_His') . '.' . $extension;
+ $downloadFileName = '상담녹음_'.$consultation->created_at->format('Ymd_His').'.'.$extension;
return response()->download($localPath, $downloadFileName, [
'Content-Type' => $contentType,
@@ -274,7 +274,7 @@ public function downloadFile(int $consultationId): BinaryFileResponse
$localPath = Storage::disk('local')->path($consultation->file_path);
- if (!file_exists($localPath)) {
+ if (! file_exists($localPath)) {
abort(404, '파일을 찾을 수 없습니다.');
}
@@ -359,7 +359,7 @@ public function prospectUploadAudio(Request $request, GoogleCloudStorageService
$duration = $request->input('duration');
$file = $request->file('audio');
- $fileName = 'audio_' . now()->format('Ymd_His') . '_' . uniqid() . '.' . $file->getClientOriginalExtension();
+ $fileName = 'audio_'.now()->format('Ymd_His').'_'.uniqid().'.'.$file->getClientOriginalExtension();
$localPath = $file->storeAs("prospect/consultations/{$prospectId}", $fileName, 'local');
$fileSize = $file->getSize();
@@ -397,7 +397,7 @@ public function prospectUploadAudio(Request $request, GoogleCloudStorageService
'formatted_duration' => $consultation->formatted_duration,
'created_by_name' => $consultation->creator->name,
'created_at' => $consultation->created_at->format('Y-m-d H:i'),
- 'has_gcs' => !empty($gcsUri),
+ 'has_gcs' => ! empty($gcsUri),
],
]);
}
@@ -420,7 +420,7 @@ public function prospectUploadFile(Request $request): JsonResponse
$file = $request->file('file');
$originalName = $file->getClientOriginalName();
- $fileName = now()->format('Ymd_His') . '_' . uniqid() . '_' . $originalName;
+ $fileName = now()->format('Ymd_His').'_'.uniqid().'_'.$originalName;
$path = $file->storeAs("prospect/attachments/{$prospectId}", $fileName, 'local');
$consultation = SalesConsultation::createFileByProspect(
diff --git a/app/Http/Controllers/Sales/SalesContractController.php b/app/Http/Controllers/Sales/SalesContractController.php
index 0bb1b661..62248dd4 100644
--- a/app/Http/Controllers/Sales/SalesContractController.php
+++ b/app/Http/Controllers/Sales/SalesContractController.php
@@ -89,7 +89,7 @@ public function saveProducts(Request $request): JsonResponse
} catch (\Exception $e) {
return response()->json([
'success' => false,
- 'message' => '저장 중 오류가 발생했습니다: ' . $e->getMessage(),
+ 'message' => '저장 중 오류가 발생했습니다: '.$e->getMessage(),
], 500);
}
}
diff --git a/app/Http/Controllers/Sales/SalesDashboardController.php b/app/Http/Controllers/Sales/SalesDashboardController.php
index 9b640923..fbcb41f7 100644
--- a/app/Http/Controllers/Sales/SalesDashboardController.php
+++ b/app/Http/Controllers/Sales/SalesDashboardController.php
@@ -141,7 +141,7 @@ private function getDashboardData(Request $request): array
],
];
- if (!$isGroupPartner) {
+ if (! $isGroupPartner) {
$commissionByRole[] = [
'name' => '관리자',
'rate' => null, // 1개월 구독료 (퍼센트가 아닌 고정 금액)
@@ -181,7 +181,7 @@ private function getDashboardData(Request $request): array
// 수당 계산: 개발비 × 요율% (개인 20%, 단체 30%) - 1차/2차 분할은 calculateExpectedCommissionSummary에서 처리
$handoverPartnerRate = $isGroupPartner ? 0.30 : 0.20;
- $handoverPartnerCommission = (int)($handoverTotalRegFee * $handoverPartnerRate);
+ $handoverPartnerCommission = (int) ($handoverTotalRegFee * $handoverPartnerRate);
// 내가 매니저로 지정된 인계 완료 건의 수당 계산
$managedHandoverManagements = SalesTenantManagement::where('manager_user_id', $currentUserId)
@@ -190,7 +190,7 @@ private function getDashboardData(Request $request): array
$managedHandoverManagementIds = $managedHandoverManagements->pluck('id')->toArray();
// 매니저 수당: 1개월 구독료 (퍼센트가 아닌 고정 금액)
- $handoverManagerCommission = (int)SalesContractProduct::whereIn('management_id', $managedHandoverManagementIds)
+ $handoverManagerCommission = (int) SalesContractProduct::whereIn('management_id', $managedHandoverManagementIds)
->sum('subscription_fee');
// 기존 수당에 인계 완료 수당 추가
@@ -202,7 +202,7 @@ private function getDashboardData(Request $request): array
// 역할별 수당 업데이트 (실제 지급된 수당 기준)
// 참고: 예상 수당은 나중에 $totalExpectedCommission으로 별도 계산됨
$commissionByRole[0]['amount'] = $partnerCommissionTotal;
- if (!$isGroupPartner) {
+ if (! $isGroupPartner) {
$commissionByRole[1]['amount'] = $managerCommissionTotal;
}
@@ -278,7 +278,7 @@ private function getDashboardData(Request $request): array
->toArray();
$devInProgressRegFee = SalesContractProduct::whereIn('management_id', $devInProgressManagementIds)
->sum('registration_fee');
- $expectedFromDevInProgress = (int)($devInProgressRegFee * $handoverPartnerRate); // 개발비 × 요율 (개인 20%, 단체 30%)
+ $expectedFromDevInProgress = (int) ($devInProgressRegFee * $handoverPartnerRate); // 개발비 × 요율 (개인 20%, 단체 30%)
// 2) 인계 완료 중 지급 미완료 건
$handoverUnpaidRegFee = SalesContractProduct::whereIn('management_id', $handoverManagementIds)
@@ -288,7 +288,7 @@ private function getDashboardData(Request $request): array
->whereIn('management_id', $handoverManagementIds)
->where('status', SalesCommission::STATUS_PAID)
->sum('partner_commission');
- $expectedFromHandover = (int)($handoverUnpaidRegFee * $handoverPartnerRate) - $paidCommissionFromHandover;
+ $expectedFromHandover = (int) ($handoverUnpaidRegFee * $handoverPartnerRate) - $paidCommissionFromHandover;
$expectedFromHandover = max(0, $expectedFromHandover);
// 총 예상 수당 (지급 완료 제외)
@@ -383,7 +383,7 @@ public function assignManager(int $tenantId, Request $request): JsonResponse
} else {
// 특정 매니저 지정
$manager = User::find($managerId);
- if (!$manager) {
+ if (! $manager) {
return response()->json([
'success' => false,
'message' => '매니저를 찾을 수 없습니다.',
@@ -428,7 +428,7 @@ public function assignProspectManager(int $prospectId, Request $request): JsonRe
} else {
// 특정 매니저 지정
$manager = User::find($managerId);
- if (!$manager) {
+ if (! $manager) {
return response()->json([
'success' => false,
'message' => '매니저를 찾을 수 없습니다.',
@@ -581,7 +581,7 @@ private function getManagerOnlyProspects(int $currentUserId): array
$prospect = $management->tenantProspect;
// 내가 등록한 건은 제외 (순수하게 매니저로만 참여한 건만)
- if (!$prospect || $prospect->registered_by === $currentUserId) {
+ if (! $prospect || $prospect->registered_by === $currentUserId) {
continue;
}
@@ -615,7 +615,7 @@ private function getManagerOnlyProspects(int $currentUserId): array
foreach ($tenantManagements as $management) {
$tenant = $management->tenant;
- if (!$tenant) {
+ if (! $tenant) {
continue;
}
@@ -676,12 +676,12 @@ private function calculatePartnerSummaryStats(array $partnerIds, int $currentUse
// 개인 파트너 예상 수당: 1개월 구독료
$individualProspectIds = TenantProspect::whereIn('registered_by', $individualPartnerIds)->pluck('id')->toArray();
$individualMgmtIds = SalesTenantManagement::whereIn('tenant_prospect_id', $individualProspectIds)->pluck('id')->toArray();
- $individualExpected = (int)SalesContractProduct::whereIn('management_id', $individualMgmtIds)->sum('subscription_fee');
+ $individualExpected = (int) SalesContractProduct::whereIn('management_id', $individualMgmtIds)->sum('subscription_fee');
// 단체 파트너 예상 수당: 개발비 × 3%
$groupProspectIds = TenantProspect::whereIn('registered_by', $groupPartnerUserIds)->pluck('id')->toArray();
$groupMgmtIds = SalesTenantManagement::whereIn('tenant_prospect_id', $groupProspectIds)->pluck('id')->toArray();
- $groupExpected = (int)(SalesContractProduct::whereIn('management_id', $groupMgmtIds)->sum('registration_fee') * 0.03);
+ $groupExpected = (int) (SalesContractProduct::whereIn('management_id', $groupMgmtIds)->sum('registration_fee') * 0.03);
$expectedFromFee = $individualExpected + $groupExpected;
@@ -727,16 +727,16 @@ private function calculatePartnerSummaryStats(array $partnerIds, int $currentUse
'expected_commission' => $expectedCommission,
'paid_commission' => $paidManagerCommission,
'first_commission' => [
- 'total' => (int)$halfExpected,
- 'pending' => (int)$halfPending,
- 'scheduled' => (int)$halfScheduled,
- 'paid' => (int)$halfPaid,
+ 'total' => (int) $halfExpected,
+ 'pending' => (int) $halfPending,
+ 'scheduled' => (int) $halfScheduled,
+ 'paid' => (int) $halfPaid,
],
'second_commission' => [
- 'total' => (int)$halfExpected,
- 'pending' => (int)$halfPending,
- 'scheduled' => (int)$halfScheduled,
- 'paid' => (int)$halfPaid,
+ 'total' => (int) $halfExpected,
+ 'pending' => (int) $halfPending,
+ 'scheduled' => (int) $halfScheduled,
+ 'paid' => (int) $halfPaid,
],
];
}
@@ -782,8 +782,8 @@ private function getPartnerActivitiesDetail($recruitedPartners, int $currentUser
// 단체 파트너: 협업지원금(개발비 × 3%), 개인 파트너: 관리자 수당(1개월 구독료)
$isRecruitedGroupPartner = $salesPartner && $salesPartner->isGroup();
$expectedCommission = $isRecruitedGroupPartner
- ? (int)($totalRegistrationFee * 0.03)
- : (int)$totalSubscriptionFee;
+ ? (int) ($totalRegistrationFee * 0.03)
+ : (int) $totalSubscriptionFee;
// 최종 수당 (확정 + 예상 중 큰 값)
$managerCommission = max($confirmedCommission, $expectedCommission);
@@ -864,7 +864,7 @@ private function getPartnerActivitiesDetail($recruitedPartners, int $currentUser
// 역할 정보
$roles = $partner->userRoles->pluck('role.name')->filter()->toArray();
- $roleLabel = !empty($roles) ? implode(', ', $roles) : '영업';
+ $roleLabel = ! empty($roles) ? implode(', ', $roles) : '영업';
$activities[] = [
'partner' => $partner,
@@ -912,7 +912,7 @@ private function getCommissionData(): array
*/
private function getAllManagerUsers()
{
- return User::whereHas('userRoles.role', fn($q) => $q->where('name', 'manager'))
+ return User::whereHas('userRoles.role', fn ($q) => $q->where('name', 'manager'))
->where('is_active', true)
->where('id', '!=', auth()->id()) // 본인 제외
->get(['id', 'name', 'email']);
@@ -930,7 +930,7 @@ public function searchManagers(Request $request): JsonResponse
// 디버깅: SQL 쿼리 로깅
\DB::enableQueryLog();
- $managers = User::whereHas('userRoles.role', fn($q) => $q->where('name', 'manager'))
+ $managers = User::whereHas('userRoles.role', fn ($q) => $q->where('name', 'manager'))
->where('is_active', true)
->where('id', '!=', $authId)
->when($query, function ($q) use ($query) {
@@ -1012,24 +1012,24 @@ private function calculateExpectedCommissionSummary($commissions, int $totalExpe
return [
'scheduled_this_month' => $commissions
->where('status', SalesCommission::STATUS_APPROVED)
- ->filter(fn($c) => $c->scheduled_payment_date?->format('Y-m') === $thisMonth)
+ ->filter(fn ($c) => $c->scheduled_payment_date?->format('Y-m') === $thisMonth)
->sum('partner_commission'),
'total_received' => $paidCommission,
'pending_amount' => $pendingAmount,
'contracts_this_month' => $commissions
- ->filter(fn($c) => $c->payment_date >= $thisMonthStart && $c->payment_date <= $thisMonthEnd)
+ ->filter(fn ($c) => $c->payment_date >= $thisMonthStart && $c->payment_date <= $thisMonthEnd)
->count(),
'first_commission' => [
- 'total' => (int)$halfExpected,
- 'pending' => (int)$halfPending,
- 'scheduled' => (int)$halfScheduled,
- 'paid' => (int)$halfPaid,
+ 'total' => (int) $halfExpected,
+ 'pending' => (int) $halfPending,
+ 'scheduled' => (int) $halfScheduled,
+ 'paid' => (int) $halfPaid,
],
'second_commission' => [
- 'total' => (int)$halfExpected,
- 'pending' => (int)$halfPending,
- 'scheduled' => (int)$halfScheduled,
- 'paid' => (int)$halfPaid,
+ 'total' => (int) $halfExpected,
+ 'pending' => (int) $halfPending,
+ 'scheduled' => (int) $halfScheduled,
+ 'paid' => (int) $halfPaid,
],
'total_commission' => $totalExpectedCommission,
];
@@ -1053,7 +1053,7 @@ private function calculateCommissionSummaryFromCollection($commissions): array
return [
'scheduled_this_month' => $commissions
->where('status', SalesCommission::STATUS_APPROVED)
- ->filter(fn($c) => $c->scheduled_payment_date?->format('Y-m') === $thisMonth)
+ ->filter(fn ($c) => $c->scheduled_payment_date?->format('Y-m') === $thisMonth)
->sum('partner_commission'),
'total_received' => $commissions
->where('status', SalesCommission::STATUS_PAID)
@@ -1062,7 +1062,7 @@ private function calculateCommissionSummaryFromCollection($commissions): array
->where('status', SalesCommission::STATUS_PENDING)
->sum('partner_commission'),
'contracts_this_month' => $commissions
- ->filter(fn($c) => $c->payment_date >= $thisMonthStart && $c->payment_date <= $thisMonthEnd)
+ ->filter(fn ($c) => $c->payment_date >= $thisMonthStart && $c->payment_date <= $thisMonthEnd)
->count(),
'first_commission' => $firstCommission,
'second_commission' => $secondCommission,
diff --git a/app/Http/Controllers/Sales/SalesDevelopmentApprovalController.php b/app/Http/Controllers/Sales/SalesDevelopmentApprovalController.php
index ed2c8e05..6de3c98a 100644
--- a/app/Http/Controllers/Sales/SalesDevelopmentApprovalController.php
+++ b/app/Http/Controllers/Sales/SalesDevelopmentApprovalController.php
@@ -24,7 +24,7 @@ public function __construct(
public function index(Request $request): View|Response
{
// 권한 체크: admin 역할만 접근 가능
- if (!auth()->user()->isAdmin()) {
+ if (! auth()->user()->isAdmin()) {
abort(403, '접근 권한이 없습니다.');
}
@@ -62,7 +62,7 @@ public function index(Request $request): View|Response
public function approve(Request $request, int $id)
{
// 권한 체크
- if (!auth()->user()->isAdmin()) {
+ if (! auth()->user()->isAdmin()) {
abort(403, '접근 권한이 없습니다.');
}
@@ -97,7 +97,7 @@ public function approve(Request $request, int $id)
public function reject(Request $request, int $id)
{
// 권한 체크
- if (!auth()->user()->isAdmin()) {
+ if (! auth()->user()->isAdmin()) {
abort(403, '접근 권한이 없습니다.');
}
@@ -136,7 +136,7 @@ public function reject(Request $request, int $id)
public function updateStatus(Request $request, int $id)
{
// 권한 체크
- if (!auth()->user()->isAdmin()) {
+ if (! auth()->user()->isAdmin()) {
abort(403, '접근 권한이 없습니다.');
}
@@ -176,7 +176,7 @@ public function updateStatus(Request $request, int $id)
public function revertToPending(Request $request, int $id)
{
// 권한 체크
- if (!auth()->user()->isAdmin()) {
+ if (! auth()->user()->isAdmin()) {
abort(403, '접근 권한이 없습니다.');
}
@@ -211,7 +211,7 @@ public function revertToPending(Request $request, int $id)
public function detail(int $id): View
{
// 권한 체크
- if (!auth()->user()->isAdmin()) {
+ if (! auth()->user()->isAdmin()) {
abort(403, '접근 권한이 없습니다.');
}
diff --git a/app/Http/Controllers/Sales/SalesManagerController.php b/app/Http/Controllers/Sales/SalesManagerController.php
index c75b62f3..7a23b03e 100644
--- a/app/Http/Controllers/Sales/SalesManagerController.php
+++ b/app/Http/Controllers/Sales/SalesManagerController.php
@@ -199,7 +199,7 @@ public function update(Request $request, int $id)
$validated = $request->validate([
'name' => 'required|string|max:100',
- 'email' => 'required|email|max:255|unique:users,email,' . $id,
+ 'email' => 'required|email|max:255|unique:users,email,'.$id,
'phone' => 'nullable|string|max:20',
'password' => 'nullable|string|min:4|confirmed',
'role_ids' => 'required|array|min:1',
@@ -242,7 +242,7 @@ public function update(Request $request, int $id)
public function destroy(int $id)
{
// 권한 체크: admin 역할만 삭제 가능
- if (!auth()->user()->isAdmin()) {
+ if (! auth()->user()->isAdmin()) {
abort(403, '삭제 권한이 없습니다.');
}
@@ -298,6 +298,7 @@ public function delegateRole(Request $request, int $id)
$this->service->delegateRole($fromUser, $toUser, $validated['role_name']);
$roleLabel = '상담매니저';
+
return redirect()->back()
->with('success', "{$roleLabel} 역할이 {$toUser->name}님에게 위임되었습니다.");
} catch (\InvalidArgumentException $e) {
@@ -319,6 +320,7 @@ public function assignRole(Request $request, int $id)
$this->service->assignRole($partner, $validated['role_name']);
$roleLabels = ['sales' => '영업파트너', 'manager' => '상담매니저'];
+
return redirect()->back()
->with('success', "{$roleLabels[$validated['role_name']]} 역할이 부여되었습니다.");
}
@@ -336,6 +338,7 @@ public function removeRole(Request $request, int $id)
$this->service->removeRole($partner, $validated['role_name']);
$roleLabels = ['sales' => '영업파트너', 'manager' => '상담매니저'];
+
return redirect()->back()
->with('success', "{$roleLabels[$validated['role_name']]} 역할이 제거되었습니다.");
}
@@ -371,7 +374,7 @@ public function deleteDocument(int $id, int $documentId)
public function approvals(Request $request): View|Response
{
// 권한 체크: admin 역할만 접근 가능
- if (!auth()->user()->isAdmin()) {
+ if (! auth()->user()->isAdmin()) {
abort(403, '접근 권한이 없습니다.');
}
@@ -404,7 +407,7 @@ public function approvals(Request $request): View|Response
public function approveFromList(Request $request, int $id)
{
// 권한 체크
- if (!auth()->user()->isAdmin()) {
+ if (! auth()->user()->isAdmin()) {
abort(403, '접근 권한이 없습니다.');
}
@@ -428,7 +431,7 @@ public function approveFromList(Request $request, int $id)
public function rejectFromList(Request $request, int $id)
{
// 권한 체크
- if (!auth()->user()->isAdmin()) {
+ if (! auth()->user()->isAdmin()) {
abort(403, '접근 권한이 없습니다.');
}
diff --git a/app/Http/Controllers/Sales/SalesProductController.php b/app/Http/Controllers/Sales/SalesProductController.php
index be331146..a6f5fe0b 100644
--- a/app/Http/Controllers/Sales/SalesProductController.php
+++ b/app/Http/Controllers/Sales/SalesProductController.php
@@ -27,7 +27,7 @@ public function index(Request $request): View|Response
$categories = SalesProductCategory::active()
->ordered()
- ->with(['products' => fn($q) => $q->ordered()])
+ ->with(['products' => fn ($q) => $q->ordered()])
->get();
$currentCategoryCode = $request->input('category', $categories->first()?->code);
@@ -43,7 +43,7 @@ public function productList(Request $request): View
{
$categoryCode = $request->input('category');
$category = SalesProductCategory::where('code', $categoryCode)
- ->with(['products' => fn($q) => $q->ordered()])
+ ->with(['products' => fn ($q) => $q->ordered()])
->first();
return view('sales.products.partials.product-list', compact('category'));
@@ -144,7 +144,7 @@ public function destroy(int $id): JsonResponse
public function toggleActive(int $id): JsonResponse
{
$product = SalesProduct::findOrFail($id);
- $product->update(['is_active' => !$product->is_active]);
+ $product->update(['is_active' => ! $product->is_active]);
return response()->json([
'success' => true,
@@ -268,7 +268,7 @@ public function getProductsApi(): JsonResponse
{
$categories = SalesProductCategory::active()
->ordered()
- ->with(['products' => fn($q) => $q->active()->ordered()])
+ ->with(['products' => fn ($q) => $q->active()->ordered()])
->get();
return response()->json([
diff --git a/app/Http/Controllers/Sales/SalesProspectController.php b/app/Http/Controllers/Sales/SalesProspectController.php
index b9f85555..3dd68380 100644
--- a/app/Http/Controllers/Sales/SalesProspectController.php
+++ b/app/Http/Controllers/Sales/SalesProspectController.php
@@ -99,19 +99,19 @@ public function store(Request $request)
]);
// 명함 이미지 저장 (Base64)
- if (!empty($validated['business_card_image_data'])) {
+ if (! empty($validated['business_card_image_data'])) {
$validated['business_card_image'] = $this->saveBase64Image($validated['business_card_image_data'], 'business-cards');
}
unset($validated['business_card_image_data']);
// 신분증 이미지 저장 (Base64)
- if (!empty($validated['id_card_image_data'])) {
+ if (! empty($validated['id_card_image_data'])) {
$validated['id_card_image'] = $this->saveBase64Image($validated['id_card_image_data'], 'id-cards');
}
unset($validated['id_card_image_data']);
// 통장사본 이미지 저장 (Base64)
- if (!empty($validated['bankbook_image_data'])) {
+ if (! empty($validated['bankbook_image_data'])) {
$validated['bankbook_image'] = $this->saveBase64Image($validated['bankbook_image_data'], 'bankbooks');
}
unset($validated['bankbook_image_data']);
@@ -132,7 +132,7 @@ public function show(int $id): View
'salesManager',
'products',
'scenarios',
- 'consultations.manager'
+ 'consultations.manager',
])->findOrFail($id);
$managers = SalesManager::active()
@@ -250,7 +250,7 @@ private function saveBase64Image(string $base64Data, string $folder): ?string
return null;
}
- $filename = $folder . '/' . date('Ymd') . '_' . uniqid() . '.' . $extension;
+ $filename = $folder.'/'.date('Ymd').'_'.uniqid().'.'.$extension;
Storage::disk('public')->put($filename, $imageData);
return $filename;
diff --git a/app/Http/Controllers/Sales/SalesScenarioController.php b/app/Http/Controllers/Sales/SalesScenarioController.php
index d2acd2bd..b4328b26 100644
--- a/app/Http/Controllers/Sales/SalesScenarioController.php
+++ b/app/Http/Controllers/Sales/SalesScenarioController.php
@@ -7,9 +7,9 @@
use App\Models\Sales\SalesTenantManagement;
use App\Models\Sales\TenantProspect;
use App\Models\Tenants\Tenant;
+use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
-use Illuminate\Http\JsonResponse;
use Illuminate\View\View;
/**
diff --git a/app/Http/Controllers/Sales/TenantProspectController.php b/app/Http/Controllers/Sales/TenantProspectController.php
index 1a707b45..5831995c 100644
--- a/app/Http/Controllers/Sales/TenantProspectController.php
+++ b/app/Http/Controllers/Sales/TenantProspectController.php
@@ -71,7 +71,7 @@ public function store(Request $request)
// 등록 가능 여부 확인
$checkResult = $this->service->canRegister($validated['business_number']);
- if (!$checkResult['can_register']) {
+ if (! $checkResult['can_register']) {
return redirect()->back()
->withInput()
->with('error', $checkResult['reason']);
@@ -172,7 +172,7 @@ public function destroy(int $id)
}
// 관리자만 삭제 가능
- if (!auth()->user()->isAdmin()) {
+ if (! auth()->user()->isAdmin()) {
return redirect()->route('sales.prospects.index')
->with('error', '삭제 권한이 없습니다. 본사 운영팀에 문의하세요.');
}
@@ -257,7 +257,7 @@ public function deleteAttachment(Request $request, int $id)
$type = $request->get('type');
$allowedTypes = ['business_card', 'id_card', 'bankbook'];
- if (!in_array($type, $allowedTypes)) {
+ if (! in_array($type, $allowedTypes)) {
return response()->json(['success' => false, 'message' => '잘못된 요청입니다.'], 400);
}
diff --git a/app/Http/Controllers/System/AiVoiceRecordingController.php b/app/Http/Controllers/System/AiVoiceRecordingController.php
index 2eafcd16..7434cccf 100644
--- a/app/Http/Controllers/System/AiVoiceRecordingController.php
+++ b/app/Http/Controllers/System/AiVoiceRecordingController.php
@@ -9,7 +9,6 @@
use App\Services\GoogleCloudService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
-use Illuminate\Support\Str;
use Illuminate\View\View;
use Symfony\Component\HttpFoundation\Response;
diff --git a/app/Http/Controllers/System/HolidayController.php b/app/Http/Controllers/System/HolidayController.php
index 2d88475d..2307bf34 100644
--- a/app/Http/Controllers/System/HolidayController.php
+++ b/app/Http/Controllers/System/HolidayController.php
@@ -158,6 +158,7 @@ public function bulkStore(Request $request): JsonResponse
if ($exists) {
$skipped++;
+
continue;
}
diff --git a/app/Http/Controllers/System/SystemAlertController.php b/app/Http/Controllers/System/SystemAlertController.php
index e0e2de78..cffdf8f7 100644
--- a/app/Http/Controllers/System/SystemAlertController.php
+++ b/app/Http/Controllers/System/SystemAlertController.php
@@ -38,10 +38,10 @@ public function index(Request $request): View
// 날짜 범위 필터
if ($request->filled('date_from')) {
- $query->where('created_at', '>=', $request->date_from . ' 00:00:00');
+ $query->where('created_at', '>=', $request->date_from.' 00:00:00');
}
if ($request->filled('date_to')) {
- $query->where('created_at', '<=', $request->date_to . ' 23:59:59');
+ $query->where('created_at', '<=', $request->date_to.' 23:59:59');
}
$alerts = $query->paginate(50)->withQueryString();
@@ -95,4 +95,4 @@ public function markAllAsRead(): Response
return response('', 200, ['HX-Refresh' => 'true']);
}
-}
\ No newline at end of file
+}
diff --git a/app/Http/Controllers/TenantSettingController.php b/app/Http/Controllers/TenantSettingController.php
index 1d342363..ecf362a3 100644
--- a/app/Http/Controllers/TenantSettingController.php
+++ b/app/Http/Controllers/TenantSettingController.php
@@ -124,4 +124,4 @@ public function store(Request $request): RedirectResponse
return redirect()->route('tenant-settings.index')
->with('success', '설정이 저장되었습니다.');
}
-}
\ No newline at end of file
+}
diff --git a/app/Http/Controllers/Video/TutorialVideoController.php b/app/Http/Controllers/Video/TutorialVideoController.php
index 253af8d8..71dc0130 100644
--- a/app/Http/Controllers/Video/TutorialVideoController.php
+++ b/app/Http/Controllers/Video/TutorialVideoController.php
@@ -43,7 +43,7 @@ public function upload(Request $request): JsonResponse
'screenshots.*' => 'required|image|max:10240', // 최대 10MB
]);
- $uploadDir = storage_path('app/tutorial_uploads/' . auth()->id() . '/' . time());
+ $uploadDir = storage_path('app/tutorial_uploads/'.auth()->id().'/'.time());
if (! is_dir($uploadDir)) {
mkdir($uploadDir, 0755, true);
}
@@ -52,7 +52,7 @@ public function upload(Request $request): JsonResponse
foreach ($request->file('screenshots') as $i => $file) {
$filename = sprintf('screenshot_%02d.%s', $i + 1, $file->getClientOriginalExtension());
$file->move($uploadDir, $filename);
- $paths[] = $uploadDir . '/' . $filename;
+ $paths[] = $uploadDir.'/'.$filename;
}
return response()->json([
@@ -79,7 +79,7 @@ public function analyze(Request $request): JsonResponse
if (! file_exists($path)) {
return response()->json([
'success' => false,
- 'message' => '업로드된 파일을 찾을 수 없습니다: ' . basename($path),
+ 'message' => '업로드된 파일을 찾을 수 없습니다: '.basename($path),
], 400);
}
}
@@ -93,7 +93,7 @@ public function analyze(Request $request): JsonResponse
return response()->json([
'success' => false,
- 'message' => 'AI 분석 중 오류가 발생했습니다: ' . $e->getMessage(),
+ 'message' => 'AI 분석 중 오류가 발생했습니다: '.$e->getMessage(),
], 500);
}
@@ -188,7 +188,7 @@ public function download(int $id): BinaryFileResponse|RedirectResponse|JsonRespo
return response()->json(['message' => '영상 파일을 찾을 수 없습니다.'], 404);
}
- $filename = 'tutorial_' . ($tutorial->title ? preg_replace('/[^a-zA-Z0-9가-힣_\-.]/', '_', $tutorial->title) : $tutorial->id) . '.mp4';
+ $filename = 'tutorial_'.($tutorial->title ? preg_replace('/[^a-zA-Z0-9가-힣_\-.]/', '_', $tutorial->title) : $tutorial->id).'.mp4';
return response()->download($tutorial->output_path, $filename, [
'Content-Type' => 'video/mp4',
diff --git a/app/Http/Controllers/Video/Veo3Controller.php b/app/Http/Controllers/Video/Veo3Controller.php
index f206241c..fb2566c7 100644
--- a/app/Http/Controllers/Video/Veo3Controller.php
+++ b/app/Http/Controllers/Video/Veo3Controller.php
@@ -355,12 +355,12 @@ private function buildYoutubeText(VideoGeneration $video, array $scenario, array
// 해시태그 생성
$hashtags = ['#shorts', '#쇼츠'];
if ($keyword) {
- $hashtags[] = '#' . str_replace(' ', '', $keyword);
+ $hashtags[] = '#'.str_replace(' ', '', $keyword);
}
// 시나리오에서 추가 태그 추출
$bgmMood = $scenario['bgm_mood'] ?? '';
if ($bgmMood) {
- $hashtags[] = '#' . $bgmMood;
+ $hashtags[] = '#'.$bgmMood;
}
$hashtags = array_merge($hashtags, ['#건강', '#건강정보', '#헬스']);
@@ -373,7 +373,7 @@ private function buildYoutubeText(VideoGeneration $video, array $scenario, array
foreach ($scenes as $scene) {
$narration = $scene['narration'] ?? '';
if ($narration && ($scene['scene_type'] ?? '') !== 'HOOK') {
- $descLines[] = '- ' . mb_substr($narration, 0, 60);
+ $descLines[] = '- '.mb_substr($narration, 0, 60);
}
}
diff --git a/app/Http/Middleware/AutoLoginViaRemember.php b/app/Http/Middleware/AutoLoginViaRemember.php
index f3ea54c1..d00884bd 100644
--- a/app/Http/Middleware/AutoLoginViaRemember.php
+++ b/app/Http/Middleware/AutoLoginViaRemember.php
@@ -30,16 +30,18 @@ public function handle(Request $request, Closure $next): Response
$user = Auth::user();
// HQ 테넌트 소속 확인
- if (!$user->belongsToHQ()) {
+ if (! $user->belongsToHQ()) {
Auth::logout();
Log::info('[AutoLoginViaRemember] Non-HQ user rejected', ['user_id' => $user->id]);
+
return $next($request);
}
// 활성 상태 확인
- if (!$user->is_active) {
+ if (! $user->is_active) {
Auth::logout();
Log::info('[AutoLoginViaRemember] Inactive user rejected', ['user_id' => $user->id]);
+
return $next($request);
}
@@ -79,4 +81,4 @@ private function refreshApiToken(int $userId, int $tenantId): void
]);
}
}
-}
\ No newline at end of file
+}
diff --git a/app/Jobs/VideoGenerationJob.php b/app/Jobs/VideoGenerationJob.php
index fd64089f..54ee5a95 100644
--- a/app/Jobs/VideoGenerationJob.php
+++ b/app/Jobs/VideoGenerationJob.php
@@ -3,12 +3,12 @@
namespace App\Jobs;
use App\Models\VideoGeneration;
+use App\Services\GoogleCloudStorageService;
use App\Services\Video\BgmService;
use App\Services\Video\GeminiScriptService;
use App\Services\Video\TtsService;
use App\Services\Video\VeoVideoService;
use App\Services\Video\VideoAssemblyService;
-use App\Services\GoogleCloudStorageService;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
@@ -114,7 +114,7 @@ public function handle(
$video->updateProgress(
VideoGeneration::STATUS_GENERATING_CLIPS,
20 + (int) (($sceneNum / count($scenes)) * 10),
- "영상 클립 생성 요청 중 ({$sceneNum}/" . count($scenes) . ')'
+ "영상 클립 생성 요청 중 ({$sceneNum}/".count($scenes).')'
);
$result = $veo->generateClip($prompt, $duration);
@@ -137,7 +137,7 @@ public function handle(
$video->updateProgress(
VideoGeneration::STATUS_GENERATING_CLIPS,
30 + (int) (($sceneNum / count($scenes)) * 40),
- "영상 클립 생성 대기 중 ({$sceneNum}/" . count($scenes) . ')'
+ "영상 클립 생성 대기 중 ({$sceneNum}/".count($scenes).')'
);
$result = $veo->waitAndSave(
@@ -189,7 +189,7 @@ public function handle(
// 성공한 클립이 절반 미만이면 전체 실패
if (count($clipPaths) < ceil(count($scenes) / 2)) {
- $video->markFailed('영상 클립 생성 실패 (성공: ' . count($clipPaths) . '/' . count($scenes) . ')');
+ $video->markFailed('영상 클립 생성 실패 (성공: '.count($clipPaths).'/'.count($scenes).')');
return;
}
@@ -310,7 +310,7 @@ public function handle(
// === 완료 ===
$stepMsg = empty($skippedScenes)
? '완료'
- : '완료 (장면 ' . implode(',', $skippedScenes) . ' 건너뜀)';
+ : '완료 (장면 '.implode(',', $skippedScenes).' 건너뜀)';
$video->update([
'status' => VideoGeneration::STATUS_COMPLETED,
@@ -344,7 +344,7 @@ public function handle(
public function failed(\Throwable $exception): void
{
$video = VideoGeneration::withoutGlobalScopes()->find($this->videoGenerationId);
- $video?->markFailed('Job 실패: ' . $exception->getMessage());
+ $video?->markFailed('Job 실패: '.$exception->getMessage());
}
/**
@@ -356,6 +356,6 @@ private function makeSafePrompt(string $prompt): string
$prompt = preg_replace('/\b(woman|man|girl|boy|person|people|her|his|she|he)\b/i', 'subject', $prompt);
// 안전 키워드 추가
- return 'Safe for all audiences. Professional stock footage style. ' . $prompt;
+ return 'Safe for all audiences. Professional stock footage style. '.$prompt;
}
}
diff --git a/app/Mail/EsignCompletedMail.php b/app/Mail/EsignCompletedMail.php
index 7cd992df..b650592b 100644
--- a/app/Mail/EsignCompletedMail.php
+++ b/app/Mail/EsignCompletedMail.php
@@ -6,8 +6,8 @@
use App\Models\ESign\EsignSigner;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
-use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Address;
+use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Collection;
@@ -32,7 +32,7 @@ public function envelope(): Envelope
public function content(): Content
{
- $downloadUrl = config('app.url') . '/esign/sign/' . $this->signer->access_token . '/api/document';
+ $downloadUrl = config('app.url').'/esign/sign/'.$this->signer->access_token.'/api/document';
return new Content(
html: 'emails.esign.completed',
diff --git a/app/Mail/EsignOtpMail.php b/app/Mail/EsignOtpMail.php
index eaf00768..f272a447 100644
--- a/app/Mail/EsignOtpMail.php
+++ b/app/Mail/EsignOtpMail.php
@@ -4,8 +4,8 @@
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
-use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Address;
+use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
diff --git a/app/Mail/EsignRequestMail.php b/app/Mail/EsignRequestMail.php
index e4554531..dc74db1c 100644
--- a/app/Mail/EsignRequestMail.php
+++ b/app/Mail/EsignRequestMail.php
@@ -6,8 +6,8 @@
use App\Models\ESign\EsignSigner;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
-use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Address;
+use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
@@ -33,7 +33,7 @@ public function envelope(): Envelope
public function content(): Content
{
- $signUrl = config('app.url') . '/esign/sign/' . $this->signer->access_token;
+ $signUrl = config('app.url').'/esign/sign/'.$this->signer->access_token;
return new Content(
html: 'emails.esign.request',
diff --git a/app/Models/Barobill/AccountCode.php b/app/Models/Barobill/AccountCode.php
index 7c295872..47cb6843 100644
--- a/app/Models/Barobill/AccountCode.php
+++ b/app/Models/Barobill/AccountCode.php
@@ -2,9 +2,9 @@
namespace App\Models\Barobill;
+use App\Models\Tenants\Tenant;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
-use App\Models\Tenants\Tenant;
/**
* 계정과목 모델
diff --git a/app/Models/Barobill/BankSyncStatus.php b/app/Models/Barobill/BankSyncStatus.php
index 9d32ac83..33b1dab0 100644
--- a/app/Models/Barobill/BankSyncStatus.php
+++ b/app/Models/Barobill/BankSyncStatus.php
@@ -2,9 +2,9 @@
namespace App\Models\Barobill;
+use App\Models\Tenants\Tenant;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
-use App\Models\Tenants\Tenant;
/**
* 바로빌 계좌 거래 동기화 상태 모델
diff --git a/app/Models/Barobill/BankTransactionSplit.php b/app/Models/Barobill/BankTransactionSplit.php
index 509d68a1..0b6ac1cb 100644
--- a/app/Models/Barobill/BankTransactionSplit.php
+++ b/app/Models/Barobill/BankTransactionSplit.php
@@ -2,9 +2,9 @@
namespace App\Models\Barobill;
+use App\Models\Tenants\Tenant;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
-use App\Models\Tenants\Tenant;
/**
* 계좌 입출금 거래 분개 모델
@@ -62,7 +62,7 @@ public static function getByDateRange(int $tenantId, string $startDate, string $
$grouped = [];
foreach ($splits as $split) {
$key = $split->original_unique_key;
- if (!isset($grouped[$key])) {
+ if (! isset($grouped[$key])) {
$grouped[$key] = [];
}
$grouped[$key][] = $split;
diff --git a/app/Models/Barobill/BarobillConfig.php b/app/Models/Barobill/BarobillConfig.php
index b63104fd..5e5cf723 100644
--- a/app/Models/Barobill/BarobillConfig.php
+++ b/app/Models/Barobill/BarobillConfig.php
@@ -102,6 +102,6 @@ public function getMaskedCertKeyAttribute(): string
return $this->cert_key;
}
- return substr($this->cert_key, 0, 8) . str_repeat('*', 8) . '...';
+ return substr($this->cert_key, 0, 8).str_repeat('*', 8).'...';
}
}
diff --git a/app/Models/Barobill/BarobillMember.php b/app/Models/Barobill/BarobillMember.php
index 01d79f2e..1875ee90 100644
--- a/app/Models/Barobill/BarobillMember.php
+++ b/app/Models/Barobill/BarobillMember.php
@@ -60,8 +60,9 @@ public function getFormattedBizNoAttribute(): string
{
$bizNo = preg_replace('/[^0-9]/', '', $this->biz_no);
if (strlen($bizNo) === 10) {
- return substr($bizNo, 0, 3) . '-' . substr($bizNo, 3, 2) . '-' . substr($bizNo, 5);
+ return substr($bizNo, 0, 3).'-'.substr($bizNo, 3, 2).'-'.substr($bizNo, 5);
}
+
return $this->biz_no;
}
diff --git a/app/Models/Barobill/BarobillPricingPolicy.php b/app/Models/Barobill/BarobillPricingPolicy.php
index 88164d33..602fdf46 100644
--- a/app/Models/Barobill/BarobillPricingPolicy.php
+++ b/app/Models/Barobill/BarobillPricingPolicy.php
@@ -50,7 +50,9 @@ class BarobillPricingPolicy extends Model
* 서비스 유형 상수
*/
public const TYPE_CARD = 'card';
+
public const TYPE_TAX_INVOICE = 'tax_invoice';
+
public const TYPE_BANK_ACCOUNT = 'bank_account';
/**
@@ -104,7 +106,7 @@ public static function getAllActive(): \Illuminate\Database\Eloquent\Collection
/**
* 추가 과금액 계산
*
- * @param int $usageCount 사용량
+ * @param int $usageCount 사용량
* @return array ['free_count' => int, 'billable_count' => int, 'billable_amount' => int]
*/
public function calculateBilling(int $usageCount): array
diff --git a/app/Models/Barobill/BarobillSetting.php b/app/Models/Barobill/BarobillSetting.php
index 445b4352..20c1f4cd 100644
--- a/app/Models/Barobill/BarobillSetting.php
+++ b/app/Models/Barobill/BarobillSetting.php
@@ -60,10 +60,19 @@ public function tenant(): BelongsTo
public function getActiveServicesAttribute(): array
{
$services = [];
- if ($this->use_tax_invoice) $services[] = 'tax_invoice';
- if ($this->use_bank_account) $services[] = 'bank_account';
- if ($this->use_card_usage) $services[] = 'card_usage';
- if ($this->use_hometax) $services[] = 'hometax';
+ if ($this->use_tax_invoice) {
+ $services[] = 'tax_invoice';
+ }
+ if ($this->use_bank_account) {
+ $services[] = 'bank_account';
+ }
+ if ($this->use_card_usage) {
+ $services[] = 'card_usage';
+ }
+ if ($this->use_hometax) {
+ $services[] = 'hometax';
+ }
+
return $services;
}
}
diff --git a/app/Models/Barobill/BarobillSubscription.php b/app/Models/Barobill/BarobillSubscription.php
index a44ad136..f4ca21e6 100644
--- a/app/Models/Barobill/BarobillSubscription.php
+++ b/app/Models/Barobill/BarobillSubscription.php
@@ -74,12 +74,13 @@ public function getServiceTypeLabelAttribute(): string
*/
public function getStatusLabelAttribute(): string
{
- if (!$this->is_active) {
+ if (! $this->is_active) {
return '비활성';
}
if ($this->ended_at && $this->ended_at->isPast()) {
return '종료';
}
+
return '구독중';
}
@@ -88,12 +89,13 @@ public function getStatusLabelAttribute(): string
*/
public function getStatusColorAttribute(): string
{
- if (!$this->is_active) {
+ if (! $this->is_active) {
return 'bg-gray-100 text-gray-800';
}
if ($this->ended_at && $this->ended_at->isPast()) {
return 'bg-red-100 text-red-800';
}
+
return 'bg-green-100 text-green-800';
}
@@ -103,10 +105,10 @@ public function getStatusColorAttribute(): string
public function scopeActive($query)
{
return $query->where('is_active', true)
- ->where(function ($q) {
- $q->whereNull('ended_at')
- ->orWhere('ended_at', '>=', now()->toDateString());
- });
+ ->where(function ($q) {
+ $q->whereNull('ended_at')
+ ->orWhere('ended_at', '>=', now()->toDateString());
+ });
}
/**
diff --git a/app/Models/Barobill/CardTransaction.php b/app/Models/Barobill/CardTransaction.php
index 2b07e94d..fc7534f8 100644
--- a/app/Models/Barobill/CardTransaction.php
+++ b/app/Models/Barobill/CardTransaction.php
@@ -2,9 +2,9 @@
namespace App\Models\Barobill;
+use App\Models\Tenants\Tenant;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
-use App\Models\Tenants\Tenant;
/**
* 바로빌 카드 사용내역 모델
@@ -103,6 +103,6 @@ public static function getByDateRange(int $tenantId, string $startDate, string $
$query->where('card_num', $cardNum);
}
- return $query->get()->keyBy(fn($item) => $item->unique_key);
+ return $query->get()->keyBy(fn ($item) => $item->unique_key);
}
}
diff --git a/app/Models/Barobill/CardTransactionSplit.php b/app/Models/Barobill/CardTransactionSplit.php
index 0e4654a2..e7e731cc 100644
--- a/app/Models/Barobill/CardTransactionSplit.php
+++ b/app/Models/Barobill/CardTransactionSplit.php
@@ -2,9 +2,9 @@
namespace App\Models\Barobill;
+use App\Models\Tenants\Tenant;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
-use App\Models\Tenants\Tenant;
/**
* 카드 거래 분개 모델
@@ -67,7 +67,7 @@ public static function getByDateRange(int $tenantId, string $startDate, string $
$grouped = [];
foreach ($splits as $split) {
$key = $split->original_unique_key;
- if (!isset($grouped[$key])) {
+ if (! isset($grouped[$key])) {
$grouped[$key] = [];
}
$grouped[$key][] = $split;
diff --git a/app/Models/Barobill/HometaxInvoice.php b/app/Models/Barobill/HometaxInvoice.php
index fa26c861..e6c59426 100644
--- a/app/Models/Barobill/HometaxInvoice.php
+++ b/app/Models/Barobill/HometaxInvoice.php
@@ -99,15 +99,19 @@ class HometaxInvoice extends Model
// 과세유형 상수
public const TAX_TYPE_TAXABLE = 1; // 과세
+
public const TAX_TYPE_ZERO_RATE = 2; // 영세
+
public const TAX_TYPE_EXEMPT = 3; // 면세
// 영수/청구 상수
public const PURPOSE_TYPE_RECEIPT = 1; // 영수
+
public const PURPOSE_TYPE_CLAIM = 2; // 청구
// 발급유형 상수
public const ISSUE_TYPE_NORMAL = 1; // 정발행
+
public const ISSUE_TYPE_REVERSE = 2; // 역발행
/**
@@ -147,7 +151,7 @@ public function scopePurchase($query)
*/
public function scopePeriod($query, string $startDate, string $endDate, string $dateType = 'write')
{
- $column = match($dateType) {
+ $column = match ($dateType) {
'issue' => 'issue_date',
'send' => 'send_date',
default => 'write_date',
@@ -169,12 +173,12 @@ public function scopeSearchCorp($query, string $keyword, string $invoiceType = '
if ($invoiceType === 'sales') {
return $query->where(function ($q) use ($keyword) {
$q->where('invoicee_corp_name', 'like', "%{$keyword}%")
- ->orWhere('invoicee_corp_num', 'like', "%{$keyword}%");
+ ->orWhere('invoicee_corp_num', 'like', "%{$keyword}%");
});
} else {
return $query->where(function ($q) use ($keyword) {
$q->where('invoicer_corp_name', 'like', "%{$keyword}%")
- ->orWhere('invoicer_corp_num', 'like', "%{$keyword}%");
+ ->orWhere('invoicer_corp_num', 'like', "%{$keyword}%");
});
}
}
@@ -184,7 +188,7 @@ public function scopeSearchCorp($query, string $keyword, string $invoiceType = '
*/
public function getTaxTypeNameAttribute(): string
{
- return match($this->tax_type) {
+ return match ($this->tax_type) {
self::TAX_TYPE_TAXABLE => '과세',
self::TAX_TYPE_ZERO_RATE => '영세',
self::TAX_TYPE_EXEMPT => '면세',
@@ -197,7 +201,7 @@ public function getTaxTypeNameAttribute(): string
*/
public function getPurposeTypeNameAttribute(): string
{
- return match($this->purpose_type) {
+ return match ($this->purpose_type) {
self::PURPOSE_TYPE_RECEIPT => '영수',
self::PURPOSE_TYPE_CLAIM => '청구',
default => '-',
@@ -209,7 +213,7 @@ public function getPurposeTypeNameAttribute(): string
*/
public function getIssueTypeNameAttribute(): string
{
- return match($this->issue_type) {
+ return match ($this->issue_type) {
self::ISSUE_TYPE_NORMAL => '정발급',
self::ISSUE_TYPE_REVERSE => '역발급',
default => '-',
@@ -247,17 +251,17 @@ public static function fromApiData(array $apiData, int $tenantId, string $invoic
{
// 작성일자 파싱
$writeDate = null;
- if (!empty($apiData['writeDate']) && strlen($apiData['writeDate']) >= 8) {
- $writeDate = substr($apiData['writeDate'], 0, 4) . '-' .
- substr($apiData['writeDate'], 4, 2) . '-' .
+ if (! empty($apiData['writeDate']) && strlen($apiData['writeDate']) >= 8) {
+ $writeDate = substr($apiData['writeDate'], 0, 4).'-'.
+ substr($apiData['writeDate'], 4, 2).'-'.
substr($apiData['writeDate'], 6, 2);
}
// 발급일자 파싱
$issueDate = null;
- if (!empty($apiData['issueDT']) && strlen($apiData['issueDT']) >= 8) {
- $issueDate = substr($apiData['issueDT'], 0, 4) . '-' .
- substr($apiData['issueDT'], 4, 2) . '-' .
+ if (! empty($apiData['issueDT']) && strlen($apiData['issueDT']) >= 8) {
+ $issueDate = substr($apiData['issueDT'], 0, 4).'-'.
+ substr($apiData['issueDT'], 4, 2).'-'.
substr($apiData['issueDT'], 6, 2);
}
@@ -273,11 +277,11 @@ public static function fromApiData(array $apiData, int $tenantId, string $invoic
'invoicee_corp_num' => $apiData['invoiceeCorpNum'] ?? '',
'invoicee_corp_name' => $apiData['invoiceeCorpName'] ?? '',
'invoicee_ceo_name' => $apiData['invoiceeCEOName'] ?? null,
- 'supply_amount' => (int)($apiData['supplyAmount'] ?? 0),
- 'tax_amount' => (int)($apiData['taxAmount'] ?? 0),
- 'total_amount' => (int)($apiData['totalAmount'] ?? 0),
- 'tax_type' => (int)($apiData['taxType'] ?? 1),
- 'purpose_type' => (int)($apiData['purposeType'] ?? 1),
+ 'supply_amount' => (int) ($apiData['supplyAmount'] ?? 0),
+ 'tax_amount' => (int) ($apiData['taxAmount'] ?? 0),
+ 'total_amount' => (int) ($apiData['totalAmount'] ?? 0),
+ 'tax_type' => (int) ($apiData['taxType'] ?? 1),
+ 'purpose_type' => (int) ($apiData['purposeType'] ?? 1),
'issue_type' => 1, // 기본값: 정발행
'item_name' => $apiData['itemName'] ?? null,
'remark' => $apiData['remark'] ?? null,
diff --git a/app/Models/Barobill/HometaxInvoiceJournal.php b/app/Models/Barobill/HometaxInvoiceJournal.php
index 478d1fdd..035f43d6 100644
--- a/app/Models/Barobill/HometaxInvoiceJournal.php
+++ b/app/Models/Barobill/HometaxInvoiceJournal.php
@@ -2,9 +2,9 @@
namespace App\Models\Barobill;
+use App\Models\Tenants\Tenant;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
-use App\Models\Tenants\Tenant;
/**
* 홈택스 세금계산서 분개 모델
@@ -72,15 +72,15 @@ public static function saveJournals(int $tenantId, int $invoiceId, array $invoic
'dc_type' => $line['dc_type'],
'account_code' => $line['account_code'],
'account_name' => $line['account_name'],
- 'debit_amount' => (int)($line['debit_amount'] ?? 0),
- 'credit_amount' => (int)($line['credit_amount'] ?? 0),
+ 'debit_amount' => (int) ($line['debit_amount'] ?? 0),
+ 'credit_amount' => (int) ($line['credit_amount'] ?? 0),
'description' => $line['description'] ?? '',
'sort_order' => $index,
'invoice_type' => $invoiceData['invoice_type'] ?? '',
'write_date' => $invoiceData['write_date'] ?? null,
- 'supply_amount' => (int)($invoiceData['supply_amount'] ?? 0),
- 'tax_amount' => (int)($invoiceData['tax_amount'] ?? 0),
- 'total_amount' => (int)($invoiceData['total_amount'] ?? 0),
+ 'supply_amount' => (int) ($invoiceData['supply_amount'] ?? 0),
+ 'tax_amount' => (int) ($invoiceData['tax_amount'] ?? 0),
+ 'total_amount' => (int) ($invoiceData['total_amount'] ?? 0),
'trading_partner_name' => $invoiceData['trading_partner_name'] ?? '',
]);
}
diff --git a/app/Models/Boards/BoardComment.php b/app/Models/Boards/BoardComment.php
index 9fa0ce96..74b19a00 100644
--- a/app/Models/Boards/BoardComment.php
+++ b/app/Models/Boards/BoardComment.php
@@ -68,4 +68,4 @@ public function replies(): HasMany
{
return $this->children();
}
-}
\ No newline at end of file
+}
diff --git a/app/Models/Category.php b/app/Models/Category.php
index 52edcead..be610d2d 100644
--- a/app/Models/Category.php
+++ b/app/Models/Category.php
@@ -79,4 +79,4 @@ public function scopeActive($query)
{
return $query->where('is_active', true);
}
-}
\ No newline at end of file
+}
diff --git a/app/Models/Coocon/CooconConfig.php b/app/Models/Coocon/CooconConfig.php
index e62c607e..43129bbc 100644
--- a/app/Models/Coocon/CooconConfig.php
+++ b/app/Models/Coocon/CooconConfig.php
@@ -102,6 +102,6 @@ public function getMaskedApiKeyAttribute(): string
return $this->api_key;
}
- return substr($this->api_key, 0, 8) . str_repeat('*', 8) . '...';
+ return substr($this->api_key, 0, 8).str_repeat('*', 8).'...';
}
}
diff --git a/app/Models/Credit/CreditInquiry.php b/app/Models/Credit/CreditInquiry.php
index 374d6011..b9757285 100644
--- a/app/Models/Credit/CreditInquiry.php
+++ b/app/Models/Credit/CreditInquiry.php
@@ -87,7 +87,7 @@ protected static function boot()
*/
public static function generateInquiryKey(): string
{
- return date('Ymd') . Str::upper(Str::random(24));
+ return date('Ymd').Str::upper(Str::random(24));
}
/**
@@ -126,8 +126,9 @@ public function getFormattedCompanyKeyAttribute(): string
{
$key = $this->company_key;
if (strlen($key) === 10) {
- return substr($key, 0, 3) . '-' . substr($key, 3, 2) . '-' . substr($key, 5);
+ return substr($key, 0, 3).'-'.substr($key, 3, 2).'-'.substr($key, 5);
}
+
return $key;
}
@@ -172,11 +173,11 @@ public function getNtsStatusLabelAttribute(): string
/**
* API 응답으로부터 모델 생성
*
- * @param string $companyKey 사업자번호
- * @param array $apiResult 쿠콘 API 결과
- * @param array|null $ntsResult 국세청 API 결과
- * @param int|null $userId 조회자 ID
- * @param int|null $tenantId 테넌트 ID
+ * @param string $companyKey 사업자번호
+ * @param array $apiResult 쿠콘 API 결과
+ * @param array|null $ntsResult 국세청 API 결과
+ * @param int|null $userId 조회자 ID
+ * @param int|null $tenantId 테넌트 ID
*/
public static function createFromApiResponse(
string $companyKey,
@@ -199,10 +200,10 @@ public static function createFromApiResponse(
$businessType = $companyInfoData['bizcnd'] ?? $companyInfoData['indutyNm'] ?? null;
$businessItem = $companyInfoData['bizitm'] ?? $companyInfoData['indutyDetailNm'] ?? null;
$establishmentDate = null;
- if (!empty($companyInfoData['estbDt']) || !empty($companyInfoData['estbDate'])) {
+ if (! empty($companyInfoData['estbDt']) || ! empty($companyInfoData['estbDate'])) {
$estbDt = $companyInfoData['estbDt'] ?? $companyInfoData['estbDate'];
if (strlen($estbDt) === 8) {
- $establishmentDate = substr($estbDt, 0, 4) . '-' . substr($estbDt, 4, 2) . '-' . substr($estbDt, 6, 2);
+ $establishmentDate = substr($estbDt, 0, 4).'-'.substr($estbDt, 4, 2).'-'.substr($estbDt, 6, 2);
}
}
@@ -216,8 +217,8 @@ public static function createFromApiResponse(
$ntsStatus = $ntsData['b_stt'] ?? null;
$ntsStatusCode = $ntsData['b_stt_cd'] ?? null;
$ntsTaxType = $ntsData['tax_type'] ?? null;
- if (!empty($ntsData['end_dt']) && strlen($ntsData['end_dt']) === 8) {
- $ntsClosureDate = substr($ntsData['end_dt'], 0, 4) . '-' . substr($ntsData['end_dt'], 4, 2) . '-' . substr($ntsData['end_dt'], 6, 2);
+ if (! empty($ntsData['end_dt']) && strlen($ntsData['end_dt']) === 8) {
+ $ntsClosureDate = substr($ntsData['end_dt'], 0, 4).'-'.substr($ntsData['end_dt'], 4, 2).'-'.substr($ntsData['end_dt'], 6, 2);
}
}
@@ -230,7 +231,7 @@ public static function createFromApiResponse(
if (isset($apiResult[$key]['success']) && $apiResult[$key]['success']) {
$successCount++;
} else {
- $errors[] = $key . ': ' . ($apiResult[$key]['error'] ?? 'Unknown error');
+ $errors[] = $key.': '.($apiResult[$key]['error'] ?? 'Unknown error');
}
}
diff --git a/app/Models/DocumentTemplate.php b/app/Models/DocumentTemplate.php
index a4e517ac..56645b60 100644
--- a/app/Models/DocumentTemplate.php
+++ b/app/Models/DocumentTemplate.php
@@ -10,7 +10,7 @@
class DocumentTemplate extends Model
{
- use HasFactory, BelongsToTenant, SoftDeletes;
+ use BelongsToTenant, HasFactory, SoftDeletes;
protected $fillable = [
'tenant_id',
diff --git a/app/Models/DocumentTemplateApprovalLine.php b/app/Models/DocumentTemplateApprovalLine.php
index 0984f0e8..f9eb9209 100644
--- a/app/Models/DocumentTemplateApprovalLine.php
+++ b/app/Models/DocumentTemplateApprovalLine.php
@@ -27,4 +27,4 @@ public function template(): BelongsTo
{
return $this->belongsTo(DocumentTemplate::class, 'template_id');
}
-}
\ No newline at end of file
+}
diff --git a/app/Models/DocumentTemplateBasicField.php b/app/Models/DocumentTemplateBasicField.php
index 4ea87e98..9a67184e 100644
--- a/app/Models/DocumentTemplateBasicField.php
+++ b/app/Models/DocumentTemplateBasicField.php
@@ -27,4 +27,4 @@ public function template(): BelongsTo
{
return $this->belongsTo(DocumentTemplate::class, 'template_id');
}
-}
\ No newline at end of file
+}
diff --git a/app/Models/DocumentTemplateColumn.php b/app/Models/DocumentTemplateColumn.php
index ab1a0c67..5cc2a327 100644
--- a/app/Models/DocumentTemplateColumn.php
+++ b/app/Models/DocumentTemplateColumn.php
@@ -29,4 +29,4 @@ public function template(): BelongsTo
{
return $this->belongsTo(DocumentTemplate::class, 'template_id');
}
-}
\ No newline at end of file
+}
diff --git a/app/Models/DocumentTemplateSection.php b/app/Models/DocumentTemplateSection.php
index b808c774..f2ae8db5 100644
--- a/app/Models/DocumentTemplateSection.php
+++ b/app/Models/DocumentTemplateSection.php
@@ -32,4 +32,4 @@ public function items(): HasMany
return $this->hasMany(DocumentTemplateSectionItem::class, 'section_id')
->orderBy('sort_order');
}
-}
\ No newline at end of file
+}
diff --git a/app/Models/ESign/EsignContract.php b/app/Models/ESign/EsignContract.php
index b524b7c5..e4611cc7 100644
--- a/app/Models/ESign/EsignContract.php
+++ b/app/Models/ESign/EsignContract.php
@@ -3,7 +3,6 @@
namespace App\Models\ESign;
use Illuminate\Database\Eloquent\Model;
-use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
diff --git a/app/Models/ESign/EsignFieldTemplate.php b/app/Models/ESign/EsignFieldTemplate.php
index 293c8e33..b2246479 100644
--- a/app/Models/ESign/EsignFieldTemplate.php
+++ b/app/Models/ESign/EsignFieldTemplate.php
@@ -3,8 +3,8 @@
namespace App\Models\ESign;
use Illuminate\Database\Eloquent\Model;
-use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
+use Illuminate\Database\Eloquent\Relations\HasMany;
class EsignFieldTemplate extends Model
{
diff --git a/app/Models/Finance/BankAccount.php b/app/Models/Finance/BankAccount.php
index e0932e2f..61c05824 100644
--- a/app/Models/Finance/BankAccount.php
+++ b/app/Models/Finance/BankAccount.php
@@ -86,14 +86,14 @@ public function getFormattedBalanceAttribute(): string
$amount = abs($this->balance);
if ($amount >= 100000000) {
- return number_format($amount / 100000000, 1) . '억원';
+ return number_format($amount / 100000000, 1).'억원';
} elseif ($amount >= 10000000) {
- return number_format($amount / 10000000, 0) . '천만원';
+ return number_format($amount / 10000000, 0).'천만원';
} elseif ($amount >= 10000) {
- return number_format($amount / 10000, 0) . '만원';
+ return number_format($amount / 10000, 0).'만원';
}
- return number_format($amount) . '원';
+ return number_format($amount).'원';
}
/**
@@ -106,7 +106,7 @@ public function getMaskedAccountNumberAttribute(): string
return $number;
}
- return substr($number, 0, 3) . '-***-' . substr($number, -4);
+ return substr($number, 0, 3).'-***-'.substr($number, -4);
}
// ============================================================
diff --git a/app/Models/Finance/BankTransaction.php b/app/Models/Finance/BankTransaction.php
index 625433e7..7d4915ad 100644
--- a/app/Models/Finance/BankTransaction.php
+++ b/app/Models/Finance/BankTransaction.php
@@ -18,7 +18,9 @@ class BankTransaction extends Model
// 거래 유형 상수
public const TYPE_DEPOSIT = 'deposit'; // 입금
+
public const TYPE_WITHDRAWAL = 'withdrawal'; // 출금
+
public const TYPE_TRANSFER = 'transfer'; // 이체
protected $fillable = [
@@ -106,7 +108,8 @@ public function getIsWithdrawalAttribute(): bool
public function getFormattedAmountAttribute(): string
{
$prefix = $this->is_deposit ? '+' : '-';
- return $prefix . number_format(abs($this->amount)) . '원';
+
+ return $prefix.number_format(abs($this->amount)).'원';
}
/**
@@ -114,7 +117,7 @@ public function getFormattedAmountAttribute(): string
*/
public function getFormattedBalanceAfterAttribute(): string
{
- return number_format($this->balance_after) . '원';
+ return number_format($this->balance_after).'원';
}
/**
diff --git a/app/Models/Finance/ConsultingFee.php b/app/Models/Finance/ConsultingFee.php
index 6a9c5203..93ece669 100644
--- a/app/Models/Finance/ConsultingFee.php
+++ b/app/Models/Finance/ConsultingFee.php
@@ -1,4 +1,5 @@
amount);
if ($amount >= 100000000) {
- return number_format($amount / 100000000, 1) . '억원';
+ return number_format($amount / 100000000, 1).'억원';
} elseif ($amount >= 10000000) {
- return number_format($amount / 10000000, 1) . '천만원';
+ return number_format($amount / 10000000, 1).'천만원';
} elseif ($amount >= 10000) {
- return number_format($amount / 10000, 0) . '만원';
+ return number_format($amount / 10000, 0).'만원';
}
- return number_format($amount) . '원';
+ return number_format($amount).'원';
}
/**
diff --git a/app/Models/Finance/Income.php b/app/Models/Finance/Income.php
index 367816c9..dc39051a 100644
--- a/app/Models/Finance/Income.php
+++ b/app/Models/Finance/Income.php
@@ -1,4 +1,5 @@
name;
}
-}
\ No newline at end of file
+}
diff --git a/app/Models/Items/Item.php b/app/Models/Items/Item.php
index 067d4e8d..f551a42f 100644
--- a/app/Models/Items/Item.php
+++ b/app/Models/Items/Item.php
@@ -29,12 +29,17 @@ class Item extends Model
// 유형 상수
const TYPE_FG = 'FG'; // 완제품
+
const TYPE_PT = 'PT'; // 부품
+
const TYPE_SM = 'SM'; // 부자재
+
const TYPE_RM = 'RM'; // 원자재
+
const TYPE_CS = 'CS'; // 소모품
const PRODUCT_TYPES = ['FG', 'PT'];
+
const MATERIAL_TYPES = ['SM', 'RM', 'CS'];
// ── 관계 ──
@@ -73,10 +78,13 @@ public function scopeActive($query)
public function scopeSearch($query, ?string $search)
{
- if (!$search) return $query;
+ if (! $search) {
+ return $query;
+ }
+
return $query->where(function ($q) use ($search) {
$q->where('code', 'like', "%{$search}%")
- ->orWhere('name', 'like', "%{$search}%");
+ ->orWhere('name', 'like', "%{$search}%");
});
}
diff --git a/app/Models/Juil/ConstructionSitePhotoRow.php b/app/Models/Juil/ConstructionSitePhotoRow.php
index d553dc9a..b07ddab6 100644
--- a/app/Models/Juil/ConstructionSitePhotoRow.php
+++ b/app/Models/Juil/ConstructionSitePhotoRow.php
@@ -37,7 +37,7 @@ public function constructionSitePhoto(): BelongsTo
public function hasPhoto(string $type): bool
{
- return !empty($this->{$type . '_photo_path'});
+ return ! empty($this->{$type.'_photo_path'});
}
public function getPhotoCount(): int
diff --git a/app/Models/Juil/MeetingMinute.php b/app/Models/Juil/MeetingMinute.php
index b2b405c1..9d524379 100644
--- a/app/Models/Juil/MeetingMinute.php
+++ b/app/Models/Juil/MeetingMinute.php
@@ -16,9 +16,13 @@ class MeetingMinute extends Model
protected $table = 'meeting_minutes';
const STATUS_DRAFT = 'DRAFT';
+
const STATUS_RECORDING = 'RECORDING';
+
const STATUS_PROCESSING = 'PROCESSING';
+
const STATUS_COMPLETED = 'COMPLETED';
+
const STATUS_FAILED = 'FAILED';
protected $fillable = [
diff --git a/app/Models/NumberingRule.php b/app/Models/NumberingRule.php
index 016049e8..9e91bbb9 100644
--- a/app/Models/NumberingRule.php
+++ b/app/Models/NumberingRule.php
@@ -30,9 +30,13 @@ class NumberingRule extends Model
// SoftDeletes 없음 (DB에 deleted_at 컬럼 없음) → Hard Delete
const DOC_QUOTE = 'quote';
+
const DOC_ORDER = 'order';
+
const DOC_SALE = 'sale';
+
const DOC_WORK_ORDER = 'work_order';
+
const DOC_MATERIAL_RECEIPT = 'material_receipt';
public static function documentTypes(): array
@@ -68,8 +72,8 @@ public function getPreviewAttribute(): string
'static' => $segment['value'] ?? '',
'separator' => $segment['value'] ?? '',
'date' => now()->format($segment['format'] ?? 'ymd'),
- 'param' => $segment['default'] ?? '{' . ($segment['key'] ?? '?') . '}',
- 'mapping' => $segment['default'] ?? '{' . ($segment['key'] ?? '?') . '}',
+ 'param' => $segment['default'] ?? '{'.($segment['key'] ?? '?').'}',
+ 'mapping' => $segment['default'] ?? '{'.($segment['key'] ?? '?').'}',
'sequence' => str_pad('1', $this->sequence_padding, '0', STR_PAD_LEFT),
default => '',
};
diff --git a/app/Models/Products/CommonCode.php b/app/Models/Products/CommonCode.php
index fccfb52f..6c2f2cb7 100644
--- a/app/Models/Products/CommonCode.php
+++ b/app/Models/Products/CommonCode.php
@@ -46,4 +46,4 @@ public static function getItemTypes(int $tenantId): array
->pluck('name', 'code')
->toArray();
}
-}
\ No newline at end of file
+}
diff --git a/app/Models/PushDeviceToken.php b/app/Models/PushDeviceToken.php
index a298d6c1..999c5d29 100644
--- a/app/Models/PushDeviceToken.php
+++ b/app/Models/PushDeviceToken.php
@@ -61,17 +61,17 @@ public function getParsedOsVersionAttribute(): ?string
// Android 버전 추출
if (preg_match('/Android\s+([\d.]+)/', $this->device_name, $matches)) {
- return 'Android ' . $matches[1];
+ return 'Android '.$matches[1];
}
// iOS 버전 추출
if (preg_match('/iPhone\s+OS\s+([\d_]+)/', $this->device_name, $matches)) {
- return 'iOS ' . str_replace('_', '.', $matches[1]);
+ return 'iOS '.str_replace('_', '.', $matches[1]);
}
// iPad 버전 추출
if (preg_match('/CPU\s+OS\s+([\d_]+)/', $this->device_name, $matches)) {
- return 'iOS ' . str_replace('_', '.', $matches[1]);
+ return 'iOS '.str_replace('_', '.', $matches[1]);
}
return null;
@@ -94,6 +94,7 @@ private function parseUserAgent(string $userAgent): string
if (($pos = strpos($model, ' Build')) !== false) {
$model = substr($model, 0, $pos);
}
+
return $model ?: 'Android Device';
}
diff --git a/app/Models/Sales/SalesCommission.php b/app/Models/Sales/SalesCommission.php
index 663384ff..f1979bc4 100644
--- a/app/Models/Sales/SalesCommission.php
+++ b/app/Models/Sales/SalesCommission.php
@@ -51,14 +51,18 @@ class SalesCommission extends Model
* 상태 상수
*/
const STATUS_PENDING = 'pending';
+
const STATUS_APPROVED = 'approved';
+
const STATUS_PAID = 'paid';
+
const STATUS_CANCELLED = 'cancelled';
/**
* 입금 구분 상수
*/
const PAYMENT_DEPOSIT = 'deposit';
+
const PAYMENT_BALANCE = 'balance';
/**
@@ -361,7 +365,7 @@ public function recordFirstPayment(?Carbon $paymentDate = null): bool
*/
public function recordFirstPartnerPaid(?Carbon $paidDate = null): bool
{
- if (!$this->first_payment_at) {
+ if (! $this->first_payment_at) {
return false; // 1차 납입이 먼저 완료되어야 함
}
@@ -385,7 +389,7 @@ public function recordSecondPayment(?Carbon $paymentDate = null): bool
*/
public function recordSecondPartnerPaid(?Carbon $paidDate = null): bool
{
- if (!$this->second_payment_at) {
+ if (! $this->second_payment_at) {
return false; // 2차 납입이 먼저 완료되어야 함
}
@@ -409,7 +413,7 @@ public function recordFirstSubscription(?Carbon $subscriptionDate = null): bool
*/
public function recordManagerPaid(?Carbon $paidDate = null): bool
{
- if (!$this->first_subscription_at) {
+ if (! $this->first_subscription_at) {
return false; // 첫 구독료 입금이 먼저 완료되어야 함
}
@@ -423,9 +427,10 @@ public function recordManagerPaid(?Carbon $paidDate = null): bool
*/
public function getFirstPartnerScheduledDateAttribute(): ?Carbon
{
- if (!$this->first_payment_at) {
+ if (! $this->first_payment_at) {
return null;
}
+
return Carbon::parse($this->first_payment_at)->addMonth()->day(10);
}
@@ -434,9 +439,10 @@ public function getFirstPartnerScheduledDateAttribute(): ?Carbon
*/
public function getSecondPartnerScheduledDateAttribute(): ?Carbon
{
- if (!$this->second_payment_at) {
+ if (! $this->second_payment_at) {
return null;
}
+
return Carbon::parse($this->second_payment_at)->addMonth()->day(10);
}
@@ -445,9 +451,10 @@ public function getSecondPartnerScheduledDateAttribute(): ?Carbon
*/
public function getManagerScheduledDateAttribute(): ?Carbon
{
- if (!$this->first_subscription_at) {
+ if (! $this->first_subscription_at) {
return null;
}
+
return Carbon::parse($this->first_subscription_at)->addMonth()->day(10);
}
@@ -480,7 +487,7 @@ public function isManagerPaid(): bool
*/
public function recordFirstReferrerPaid(?Carbon $paidDate = null): bool
{
- if (!$this->referrer_partner_id) {
+ if (! $this->referrer_partner_id) {
return false;
}
@@ -494,7 +501,7 @@ public function recordFirstReferrerPaid(?Carbon $paidDate = null): bool
*/
public function recordSecondReferrerPaid(?Carbon $paidDate = null): bool
{
- if (!$this->referrer_partner_id) {
+ if (! $this->referrer_partner_id) {
return false;
}
diff --git a/app/Models/Sales/SalesConsultation.php b/app/Models/Sales/SalesConsultation.php
index 7d92c798..27ad86dc 100644
--- a/app/Models/Sales/SalesConsultation.php
+++ b/app/Models/Sales/SalesConsultation.php
@@ -2,7 +2,6 @@
namespace App\Models\Sales;
-use App\Models\Sales\TenantProspect;
use App\Models\Tenants\Tenant;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
@@ -61,7 +60,9 @@ class SalesConsultation extends Model
* 상담 유형 상수
*/
const TYPE_TEXT = 'text';
+
const TYPE_AUDIO = 'audio';
+
const TYPE_FILE = 'file';
/**
@@ -106,15 +107,15 @@ public static function createText(int $tenantId, string $scenarioType, ?int $ste
/**
* 음성 상담 기록 생성
*
- * @param int $tenantId 테넌트 ID
- * @param string $scenarioType 시나리오 타입 (sales/manager)
- * @param int|null $stepId 단계 ID
- * @param string $filePath 로컬 파일 경로
- * @param string $fileName 파일명
- * @param int $fileSize 파일 크기
- * @param string|null $transcript 음성 텍스트 변환 결과
- * @param int|null $duration 녹음 시간 (초)
- * @param string|null $gcsUri GCS URI (본사 연구용 백업)
+ * @param int $tenantId 테넌트 ID
+ * @param string $scenarioType 시나리오 타입 (sales/manager)
+ * @param int|null $stepId 단계 ID
+ * @param string $filePath 로컬 파일 경로
+ * @param string $fileName 파일명
+ * @param int $fileSize 파일 크기
+ * @param string|null $transcript 음성 텍스트 변환 결과
+ * @param int|null $duration 녹음 시간 (초)
+ * @param string|null $gcsUri GCS URI (본사 연구용 백업)
*/
public static function createAudio(
int $tenantId,
@@ -185,7 +186,7 @@ public function deleteWithFile(): bool
*/
public function getFormattedDurationAttribute(): ?string
{
- if (!$this->duration) {
+ if (! $this->duration) {
return null;
}
@@ -200,16 +201,16 @@ public function getFormattedDurationAttribute(): ?string
*/
public function getFormattedFileSizeAttribute(): ?string
{
- if (!$this->file_size) {
+ if (! $this->file_size) {
return null;
}
if ($this->file_size < 1024) {
- return $this->file_size . ' B';
+ return $this->file_size.' B';
} elseif ($this->file_size < 1024 * 1024) {
- return round($this->file_size / 1024, 1) . ' KB';
+ return round($this->file_size / 1024, 1).' KB';
} else {
- return round($this->file_size / (1024 * 1024), 1) . ' MB';
+ return round($this->file_size / (1024 * 1024), 1).' MB';
}
}
diff --git a/app/Models/Sales/SalesManagerDocument.php b/app/Models/Sales/SalesManagerDocument.php
index 40f32da3..f6a04278 100644
--- a/app/Models/Sales/SalesManagerDocument.php
+++ b/app/Models/Sales/SalesManagerDocument.php
@@ -76,14 +76,14 @@ public function getFormattedSizeAttribute(): string
$bytes = $this->file_size;
if ($bytes >= 1073741824) {
- return number_format($bytes / 1073741824, 2) . ' GB';
+ return number_format($bytes / 1073741824, 2).' GB';
} elseif ($bytes >= 1048576) {
- return number_format($bytes / 1048576, 2) . ' MB';
+ return number_format($bytes / 1048576, 2).' MB';
} elseif ($bytes >= 1024) {
- return number_format($bytes / 1024, 2) . ' KB';
+ return number_format($bytes / 1024, 2).' KB';
}
- return $bytes . ' bytes';
+ return $bytes.' bytes';
}
/**
@@ -123,7 +123,7 @@ public function existsInStorage(): bool
*/
public function getUrl(): ?string
{
- if (!$this->existsInStorage()) {
+ if (! $this->existsInStorage()) {
return null;
}
@@ -135,7 +135,7 @@ public function getUrl(): ?string
*/
public function download()
{
- if (!$this->existsInStorage()) {
+ if (! $this->existsInStorage()) {
abort(404, '파일을 찾을 수 없습니다.');
}
diff --git a/app/Models/Sales/SalesPartner.php b/app/Models/Sales/SalesPartner.php
index 06334b42..c18e3118 100644
--- a/app/Models/Sales/SalesPartner.php
+++ b/app/Models/Sales/SalesPartner.php
@@ -2,7 +2,6 @@
namespace App\Models\Sales;
-use App\Models\Sales\SalesCommission;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
@@ -132,7 +131,7 @@ public static function generatePartnerCode(): string
$sequence = $lastPartner ? (int) substr($lastPartner->partner_code, -4) + 1 : 1;
- return $prefix . $year . str_pad($sequence, 4, '0', STR_PAD_LEFT);
+ return $prefix.$year.str_pad($sequence, 4, '0', STR_PAD_LEFT);
}
/**
diff --git a/app/Models/Sales/SalesProduct.php b/app/Models/Sales/SalesProduct.php
index 510cecd2..bee4bcaf 100644
--- a/app/Models/Sales/SalesProduct.php
+++ b/app/Models/Sales/SalesProduct.php
@@ -104,7 +104,7 @@ public function getCommissionAttribute(): float
*/
public function getFormattedDevelopmentFeeAttribute(): string
{
- return '₩' . number_format($this->development_fee);
+ return '₩'.number_format($this->development_fee);
}
/**
@@ -112,7 +112,7 @@ public function getFormattedDevelopmentFeeAttribute(): string
*/
public function getFormattedRegistrationFeeAttribute(): string
{
- return '₩' . number_format($this->registration_fee);
+ return '₩'.number_format($this->registration_fee);
}
/**
@@ -120,6 +120,6 @@ public function getFormattedRegistrationFeeAttribute(): string
*/
public function getFormattedSubscriptionFeeAttribute(): string
{
- return '₩' . number_format($this->subscription_fee);
+ return '₩'.number_format($this->subscription_fee);
}
}
diff --git a/app/Models/Sales/SalesProspect.php b/app/Models/Sales/SalesProspect.php
index d478cd79..83617884 100644
--- a/app/Models/Sales/SalesProspect.php
+++ b/app/Models/Sales/SalesProspect.php
@@ -119,8 +119,9 @@ public function getFormattedBusinessNoAttribute(): string
{
$bizNo = preg_replace('/[^0-9]/', '', $this->business_no);
if (strlen($bizNo) === 10) {
- return substr($bizNo, 0, 3) . '-' . substr($bizNo, 3, 2) . '-' . substr($bizNo, 5);
+ return substr($bizNo, 0, 3).'-'.substr($bizNo, 3, 2).'-'.substr($bizNo, 5);
}
+
return $this->business_no ?? '';
}
@@ -145,7 +146,7 @@ public function getTotalCommissionAttribute(): float
*/
public function hasBusinessCard(): bool
{
- return !empty($this->business_card_image);
+ return ! empty($this->business_card_image);
}
/**
@@ -153,11 +154,11 @@ public function hasBusinessCard(): bool
*/
public function getBusinessCardUrlAttribute(): ?string
{
- if (!$this->hasBusinessCard()) {
+ if (! $this->hasBusinessCard()) {
return null;
}
- return asset('storage/' . $this->business_card_image);
+ return asset('storage/'.$this->business_card_image);
}
/**
@@ -165,7 +166,7 @@ public function getBusinessCardUrlAttribute(): ?string
*/
public function hasIdCard(): bool
{
- return !empty($this->id_card_image);
+ return ! empty($this->id_card_image);
}
/**
@@ -173,11 +174,11 @@ public function hasIdCard(): bool
*/
public function getIdCardUrlAttribute(): ?string
{
- if (!$this->hasIdCard()) {
+ if (! $this->hasIdCard()) {
return null;
}
- return asset('storage/' . $this->id_card_image);
+ return asset('storage/'.$this->id_card_image);
}
/**
@@ -185,7 +186,7 @@ public function getIdCardUrlAttribute(): ?string
*/
public function hasBankbook(): bool
{
- return !empty($this->bankbook_image);
+ return ! empty($this->bankbook_image);
}
/**
@@ -193,10 +194,10 @@ public function hasBankbook(): bool
*/
public function getBankbookUrlAttribute(): ?string
{
- if (!$this->hasBankbook()) {
+ if (! $this->hasBankbook()) {
return null;
}
- return asset('storage/' . $this->bankbook_image);
+ return asset('storage/'.$this->bankbook_image);
}
}
diff --git a/app/Models/Sales/SalesProspectConsultation.php b/app/Models/Sales/SalesProspectConsultation.php
index 639cbde9..c8e05ea9 100644
--- a/app/Models/Sales/SalesProspectConsultation.php
+++ b/app/Models/Sales/SalesProspectConsultation.php
@@ -86,6 +86,6 @@ public function getAttachmentCountAttribute(): int
*/
public function getHasAudioAttribute(): bool
{
- return !empty($this->audio_file_path);
+ return ! empty($this->audio_file_path);
}
}
diff --git a/app/Models/Sales/SalesProspectProduct.php b/app/Models/Sales/SalesProspectProduct.php
index 2743c182..eeddb43e 100644
--- a/app/Models/Sales/SalesProspectProduct.php
+++ b/app/Models/Sales/SalesProspectProduct.php
@@ -78,6 +78,7 @@ public function getApprovalStatusAttribute(): string
if ($this->join_approved) {
return '가입승인';
}
+
return '대기중';
}
@@ -92,6 +93,7 @@ public function getApprovalColorAttribute(): string
if ($this->join_approved) {
return 'bg-blue-100 text-blue-800';
}
+
return 'bg-gray-100 text-gray-800';
}
}
diff --git a/app/Models/Sales/SalesScenarioChecklist.php b/app/Models/Sales/SalesScenarioChecklist.php
index 7b9a4a0d..6f61e3c7 100644
--- a/app/Models/Sales/SalesScenarioChecklist.php
+++ b/app/Models/Sales/SalesScenarioChecklist.php
@@ -93,7 +93,7 @@ public static function toggle(int $tenantId, string $scenarioType, int $stepId,
]);
// 새 레코드인 경우 필수 필드 설정
- if (!$checklist->exists) {
+ if (! $checklist->exists) {
$checklist->user_id = $currentUserId;
$checklist->checkpoint_index = 0; // 기본값
}
@@ -121,7 +121,7 @@ public static function toggleByProspect(int $prospectId, string $scenarioType, i
]);
// 새 레코드인 경우 필수 필드 설정
- if (!$checklist->exists) {
+ if (! $checklist->exists) {
$checklist->user_id = $currentUserId;
$checklist->checkpoint_index = 0;
}
@@ -305,8 +305,7 @@ public function scopeChecked($query)
/**
* 간단한 진행률 계산 (전체 체크포인트 수 기준)
*
- * @param int $tenantId
- * @param string $scenarioType 'sales' 또는 'manager'
+ * @param string $scenarioType 'sales' 또는 'manager'
* @return array ['completed' => 완료 수, 'total' => 전체 수, 'percentage' => 백분율]
*/
public static function getSimpleProgress(int $tenantId, string $scenarioType): array
diff --git a/app/Models/Sales/SalesTenantManagement.php b/app/Models/Sales/SalesTenantManagement.php
index b812cae7..66ec5fd8 100644
--- a/app/Models/Sales/SalesTenantManagement.php
+++ b/app/Models/Sales/SalesTenantManagement.php
@@ -99,11 +99,17 @@ class SalesTenantManagement extends Model
* 상태 상수
*/
const STATUS_PROSPECT = 'prospect';
+
const STATUS_APPROACH = 'approach';
+
const STATUS_NEGOTIATION = 'negotiation';
+
const STATUS_CONTRACTED = 'contracted';
+
const STATUS_ONBOARDING = 'onboarding';
+
const STATUS_ACTIVE = 'active';
+
const STATUS_CHURNED = 'churned';
/**
@@ -123,12 +129,19 @@ class SalesTenantManagement extends Model
* 본사 진행 상태 상수
*/
const HQ_STATUS_PENDING = 'pending'; // 대기
+
const HQ_STATUS_REVIEW = 'review'; // 검토
+
const HQ_STATUS_PLANNING = 'planning'; // 기획안작성
+
const HQ_STATUS_CODING = 'coding'; // 개발코드작성
+
const HQ_STATUS_DEV_TEST = 'dev_test'; // 개발테스트
+
const HQ_STATUS_DEV_DONE = 'dev_done'; // 개발완료
+
const HQ_STATUS_INT_TEST = 'int_test'; // 통합테스트
+
const HQ_STATUS_HANDOVER = 'handover'; // 인계
/**
@@ -163,7 +176,9 @@ class SalesTenantManagement extends Model
* 수당 지급 상태 상수
*/
const INCENTIVE_PENDING = 'pending'; // 대기
+
const INCENTIVE_ELIGIBLE = 'eligible'; // 지급대상
+
const INCENTIVE_PAID = 'paid'; // 지급완료
/**
diff --git a/app/Models/Sales/TenantProspect.php b/app/Models/Sales/TenantProspect.php
index bdb38fbc..4e52b103 100644
--- a/app/Models/Sales/TenantProspect.php
+++ b/app/Models/Sales/TenantProspect.php
@@ -19,11 +19,15 @@ class TenantProspect extends Model
protected $table = 'tenant_prospects';
public const STATUS_ACTIVE = 'active'; // 영업권 유효
+
public const STATUS_EXPIRED = 'expired'; // 영업권 만료
+
public const STATUS_CONVERTED = 'converted'; // 테넌트 전환 완료
+
public const STATUS_COMPLETED = 'completed'; // 영업 완료
public const VALIDITY_MONTHS = 2; // 영업권 유효기간 (개월)
+
public const COOLDOWN_MONTHS = 1; // 재등록 대기 기간 (개월)
protected $fillable = [
@@ -179,7 +183,7 @@ public function getStatusColorAttribute(): string
*/
public function getRemainingDaysAttribute(): int
{
- if (!$this->isActive()) {
+ if (! $this->isActive()) {
return 0;
}
@@ -191,7 +195,7 @@ public function getRemainingDaysAttribute(): int
*/
public function getBusinessCardUrlAttribute(): ?string
{
- if (!$this->business_card_path) {
+ if (! $this->business_card_path) {
return null;
}
@@ -219,7 +223,7 @@ public function hasIdCard(): bool
*/
public function getIdCardUrlAttribute(): ?string
{
- if (!$this->id_card_path) {
+ if (! $this->id_card_path) {
return null;
}
@@ -239,7 +243,7 @@ public function hasBankbook(): bool
*/
public function getBankbookUrlAttribute(): ?string
{
- if (!$this->bankbook_path) {
+ if (! $this->bankbook_path) {
return null;
}
diff --git a/app/Models/Stats/StatAlert.php b/app/Models/Stats/StatAlert.php
index ab3e6df7..c14eb1f7 100644
--- a/app/Models/Stats/StatAlert.php
+++ b/app/Models/Stats/StatAlert.php
@@ -74,8 +74,8 @@ public function getDomainLabelAttribute(): string
public function getAiAnalysisSummaryAttribute(): string
{
$lines = [];
- $lines[] = "=== SAM 시스템 알림 분석 요청 ===";
- $lines[] = "";
+ $lines[] = '=== SAM 시스템 알림 분석 요청 ===';
+ $lines[] = '';
$lines[] = "■ 심각도: {$this->severity} ({$this->severity_label})";
$lines[] = "■ 도메인: {$this->domain} ({$this->domain_label})";
$lines[] = "■ 알림 유형: {$this->alert_type}";
@@ -83,20 +83,20 @@ public function getAiAnalysisSummaryAttribute(): string
$lines[] = "■ 발생 시간: {$this->created_at?->format('Y-m-d H:i:s')}";
if ($this->message) {
- $lines[] = "";
- $lines[] = "■ 상세 메시지:";
+ $lines[] = '';
+ $lines[] = '■ 상세 메시지:';
$lines[] = $this->message;
}
if ($this->current_value || $this->threshold_value) {
- $lines[] = "";
+ $lines[] = '';
$lines[] = "■ 현재값: {$this->current_value}";
$lines[] = "■ 임계값: {$this->threshold_value}";
}
- $lines[] = "";
- $lines[] = "위 시스템 알림의 원인과 해결 방법을 분석해주세요.";
+ $lines[] = '';
+ $lines[] = '위 시스템 알림의 원인과 해결 방법을 분석해주세요.';
return implode("\n", $lines);
}
-}
\ No newline at end of file
+}
diff --git a/app/Models/System/Schedule.php b/app/Models/System/Schedule.php
index 72568aff..04b88f6d 100644
--- a/app/Models/System/Schedule.php
+++ b/app/Models/System/Schedule.php
@@ -48,9 +48,13 @@ class Schedule extends Model
];
public const TYPE_EVENT = 'event';
+
public const TYPE_MEETING = 'meeting';
+
public const TYPE_INTERVIEW = 'interview';
+
public const TYPE_NOTICE = 'notice';
+
public const TYPE_OTHER = 'other';
public const TYPES = [
diff --git a/app/Models/Tenants/TenantSetting.php b/app/Models/Tenants/TenantSetting.php
index b52b9775..1158d74a 100644
--- a/app/Models/Tenants/TenantSetting.php
+++ b/app/Models/Tenants/TenantSetting.php
@@ -33,4 +33,4 @@ class TenantSetting extends Model
protected $casts = [
'setting_value' => 'array',
];
-}
\ No newline at end of file
+}
diff --git a/app/Models/TutorialVideo.php b/app/Models/TutorialVideo.php
index 5fa879d3..8213cef1 100644
--- a/app/Models/TutorialVideo.php
+++ b/app/Models/TutorialVideo.php
@@ -42,12 +42,19 @@ public function user()
}
const STATUS_PENDING = 'pending';
+
const STATUS_ANALYZING = 'analyzing';
+
const STATUS_GENERATING_SLIDES = 'generating_slides';
+
const STATUS_GENERATING_TTS = 'generating_tts';
+
const STATUS_GENERATING_BGM = 'generating_bgm';
+
const STATUS_ASSEMBLING = 'assembling';
+
const STATUS_COMPLETED = 'completed';
+
const STATUS_FAILED = 'failed';
public function updateProgress(string $status, int $progress, string $step): void
diff --git a/app/Models/VehicleLog.php b/app/Models/VehicleLog.php
index 44d13968..dedba5c4 100644
--- a/app/Models/VehicleLog.php
+++ b/app/Models/VehicleLog.php
@@ -4,8 +4,8 @@
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
-use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
+use Illuminate\Database\Eloquent\SoftDeletes;
class VehicleLog extends Model
{
diff --git a/app/Models/VehicleMaintenance.php b/app/Models/VehicleMaintenance.php
index 48dc64bd..070a9408 100644
--- a/app/Models/VehicleMaintenance.php
+++ b/app/Models/VehicleMaintenance.php
@@ -4,8 +4,8 @@
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
-use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
+use Illuminate\Database\Eloquent\SoftDeletes;
class VehicleMaintenance extends Model
{
diff --git a/app/Services/AiVoiceRecordingService.php b/app/Services/AiVoiceRecordingService.php
index bd9339fd..2b064d75 100644
--- a/app/Services/AiVoiceRecordingService.php
+++ b/app/Services/AiVoiceRecordingService.php
@@ -109,7 +109,7 @@ public function processAudio(AiVoiceRecording $recording, string $audioBase64, i
Log::info('AiVoiceRecording STT 결과', ['recording_id' => $recording->id, 'transcript_length' => strlen($transcript ?? ''), 'transcript_preview' => mb_substr($transcript ?? '', 0, 100)]);
if (! $transcript) {
- throw new \Exception('음성 인식 실패: STT 결과가 비어있습니다 (transcript=' . var_export($transcript, true) . ')');
+ throw new \Exception('음성 인식 실패: STT 결과가 비어있습니다 (transcript='.var_export($transcript, true).')');
}
// STT 토큰 사용량 기록
@@ -154,7 +154,7 @@ public function processUploadedFile(AiVoiceRecording $recording, UploadedFile $f
// 임시 저장
$tempPath = $file->store('temp', 'local');
- $fullPath = storage_path('app/' . $tempPath);
+ $fullPath = storage_path('app/'.$tempPath);
// 파일 크기로 대략적인 재생 시간 추정 (12KB/초 기준)
$fileSize = $file->getSize();
@@ -240,6 +240,7 @@ private function analyzeWithGemini(string $transcript): ?string
if (! $config) {
Log::warning('Gemini API 설정이 없습니다.');
+
return null;
}
@@ -279,19 +280,21 @@ private function callVertexAiApi(AiConfig $config, string $prompt): ?string
if (! $projectId) {
Log::error('Vertex AI 프로젝트 ID가 설정되지 않았습니다.');
+
return null;
}
$accessToken = $this->getAccessToken($config);
if (! $accessToken) {
Log::error('Google Cloud 인증 실패');
+
return null;
}
$url = "https://{$region}-aiplatform.googleapis.com/v1/projects/{$projectId}/locations/{$region}/publishers/google/models/{$model}:generateContent";
return $this->callGeminiApi($url, $prompt, [
- 'Authorization' => 'Bearer ' . $accessToken,
+ 'Authorization' => 'Bearer '.$accessToken,
'Content-Type' => 'application/json',
], true);
}
@@ -329,6 +332,7 @@ private function callGeminiApi(string $url, string $prompt, array $headers, bool
'status' => $response->status(),
'body' => $response->body(),
]);
+
return null;
}
@@ -340,6 +344,7 @@ private function callGeminiApi(string $url, string $prompt, array $headers, bool
return $result['candidates'][0]['content']['parts'][0]['text'] ?? null;
} catch (\Exception $e) {
Log::error('Gemini API 예외', ['error' => $e->getMessage()]);
+
return null;
}
}
@@ -367,12 +372,14 @@ private function getAccessToken(AiConfig $config): ?string
if (! $serviceAccountPath) {
Log::error('Service account file not found', ['tried_paths' => $possiblePaths]);
+
return null;
}
$serviceAccount = json_decode(file_get_contents($serviceAccountPath), true);
if (! $serviceAccount) {
Log::error('Service account JSON parse failed');
+
return null;
}
@@ -389,11 +396,12 @@ private function getAccessToken(AiConfig $config): ?string
$privateKey = openssl_pkey_get_private($serviceAccount['private_key']);
if (! $privateKey) {
Log::error('Failed to load private key');
+
return null;
}
- openssl_sign($jwtHeader . '.' . $jwtClaim, $signature, $privateKey, OPENSSL_ALGO_SHA256);
- $jwt = $jwtHeader . '.' . $jwtClaim . '.' . $this->base64UrlEncode($signature);
+ openssl_sign($jwtHeader.'.'.$jwtClaim, $signature, $privateKey, OPENSSL_ALGO_SHA256);
+ $jwt = $jwtHeader.'.'.$jwtClaim.'.'.$this->base64UrlEncode($signature);
try {
$response = Http::asForm()->post('https://oauth2.googleapis.com/token', [
@@ -409,9 +417,11 @@ private function getAccessToken(AiConfig $config): ?string
'status' => $response->status(),
'body' => $response->body(),
]);
+
return null;
} catch (\Exception $e) {
Log::error('OAuth token request exception', ['error' => $e->getMessage()]);
+
return null;
}
}
diff --git a/app/Services/AuthService.php b/app/Services/AuthService.php
index 5503e9e5..9e95ac06 100644
--- a/app/Services/AuthService.php
+++ b/app/Services/AuthService.php
@@ -23,9 +23,9 @@ public function __construct(
* - 이메일 로그인: 본사(HQ) 테넌트 소속만 허용
* - 아이디 로그인: 본사(HQ) 테넌트 소속만 허용
*
- * @param array $credentials 인증 정보 ['email' => ..., 'password' => ...] 또는 ['user_id' => ..., 'password' => ...]
- * @param bool $remember 로그인 유지 여부
- * @param string $loginField 로그인 필드 ('email' 또는 'user_id')
+ * @param array $credentials 인증 정보 ['email' => ..., 'password' => ...] 또는 ['user_id' => ..., 'password' => ...]
+ * @param bool $remember 로그인 유지 여부
+ * @param string $loginField 로그인 필드 ('email' 또는 'user_id')
*/
public function login(array $credentials, bool $remember = false, string $loginField = 'email'): bool
{
@@ -37,12 +37,14 @@ public function login(array $credentials, bool $remember = false, string $loginF
if (! $user) {
$this->loginError = '아이디 또는 비밀번호가 올바르지 않습니다.';
+
return false;
}
// 아이디 로그인은 본사 소속만 허용
if (! $user->belongsToHQ()) {
$this->loginError = '아이디 로그인은 본사 소속 직원만 가능합니다.';
+
return false;
}
}
diff --git a/app/Services/BankAccountService.php b/app/Services/BankAccountService.php
index 8f681f43..b68ddf06 100644
--- a/app/Services/BankAccountService.php
+++ b/app/Services/BankAccountService.php
@@ -347,8 +347,8 @@ public function getSummary(): array
return [
'total_accounts' => $accounts->count(),
'total_balance' => $accounts->sum('balance'),
- 'formatted_total_balance' => number_format($accounts->sum('balance')) . '원',
- 'by_bank' => $accounts->groupBy('bank_name')->map(fn($group) => [
+ 'formatted_total_balance' => number_format($accounts->sum('balance')).'원',
+ 'by_bank' => $accounts->groupBy('bank_name')->map(fn ($group) => [
'count' => $group->count(),
'total' => $group->sum('balance'),
]),
diff --git a/app/Services/Barobill/BarobillBillingService.php b/app/Services/Barobill/BarobillBillingService.php
index f139503b..041201e9 100644
--- a/app/Services/Barobill/BarobillBillingService.php
+++ b/app/Services/Barobill/BarobillBillingService.php
@@ -3,11 +3,9 @@
namespace App\Services\Barobill;
use App\Models\Barobill\BarobillBillingRecord;
-use App\Models\Barobill\BarobillMember;
use App\Models\Barobill\BarobillMonthlySummary;
use App\Models\Barobill\BarobillSubscription;
use Carbon\Carbon;
-use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
/**
@@ -54,7 +52,7 @@ public function saveSubscription(int $memberId, string $serviceType, array $data
public function cancelSubscription(int $subscriptionId): bool
{
$subscription = BarobillSubscription::find($subscriptionId);
- if (!$subscription) {
+ if (! $subscription) {
return false;
}
@@ -74,7 +72,7 @@ public function cancelSubscription(int $subscriptionId): bool
public function processMonthlyBilling(?string $billingMonth = null): array
{
$billingMonth = $billingMonth ?? now()->format('Y-m');
- $billedAt = Carbon::parse($billingMonth . '-01');
+ $billedAt = Carbon::parse($billingMonth.'-01');
$results = [
'billing_month' => $billingMonth,
@@ -99,6 +97,7 @@ public function processMonthlyBilling(?string $billingMonth = null): array
if ($exists) {
$results['skipped']++;
+
continue;
}
@@ -112,7 +111,7 @@ public function processMonthlyBilling(?string $billingMonth = null): array
'unit_price' => $subscription->monthly_fee,
'total_amount' => $subscription->monthly_fee,
'billed_at' => $billedAt,
- 'description' => BarobillSubscription::SERVICE_TYPES[$subscription->service_type] . ' 월정액',
+ 'description' => BarobillSubscription::SERVICE_TYPES[$subscription->service_type].' 월정액',
]);
$results['processed']++;
@@ -156,7 +155,7 @@ public function recordUsage(int $memberId, string $serviceType, int $quantity, ?
'unit_price' => $unitPrice,
'total_amount' => $quantity * $unitPrice,
'billed_at' => now()->toDateString(),
- 'description' => BarobillBillingRecord::SERVICE_TYPES[$serviceType] . ' ' . $quantity . '건',
+ 'description' => BarobillBillingRecord::SERVICE_TYPES[$serviceType].' '.$quantity.'건',
]
);
@@ -247,6 +246,7 @@ public function getYearlyTrend(int $year, ?int $tenantId = null): array
$billingMonth = sprintf('%d-%02d', $year, $m);
$months[$billingMonth] = $this->getMonthlyTotal($billingMonth, $tenantId);
}
+
return $months;
}
}
diff --git a/app/Services/Barobill/BarobillUsageService.php b/app/Services/Barobill/BarobillUsageService.php
index 8bcc2534..e1b49aec 100644
--- a/app/Services/Barobill/BarobillUsageService.php
+++ b/app/Services/Barobill/BarobillUsageService.php
@@ -6,7 +6,6 @@
use App\Models\Barobill\BarobillPricingPolicy;
use App\Models\Barobill\HometaxInvoice;
use Illuminate\Support\Facades\Log;
-use Illuminate\Support\Collection;
/**
* 바로빌 사용량 집계 서비스
@@ -31,11 +30,10 @@ public function __construct(BarobillService $barobillService)
/**
* 전체 테넌트 사용량 목록 조회
*
- * @param string $startDate 시작일 (YYYYMMDD)
- * @param string $endDate 종료일 (YYYYMMDD)
- * @param int|null $tenantId 특정 테넌트만 조회 (null이면 전체)
- * @param bool $productionOnly 운영 모드만 조회 (기본값: true)
- * @return array
+ * @param string $startDate 시작일 (YYYYMMDD)
+ * @param string $endDate 종료일 (YYYYMMDD)
+ * @param int|null $tenantId 특정 테넌트만 조회 (null이면 전체)
+ * @param bool $productionOnly 운영 모드만 조회 (기본값: true)
*/
public function getUsageList(string $startDate, string $endDate, ?int $tenantId = null, bool $productionOnly = true): array
{
@@ -66,10 +64,8 @@ public function getUsageList(string $startDate, string $endDate, ?int $tenantId
/**
* 단일 회원사 사용량 조회
*
- * @param BarobillMember $member
- * @param string $startDate 시작일 (YYYYMMDD)
- * @param string $endDate 종료일 (YYYYMMDD)
- * @return array
+ * @param string $startDate 시작일 (YYYYMMDD)
+ * @param string $endDate 종료일 (YYYYMMDD)
*/
public function getMemberUsage(BarobillMember $member, string $startDate, string $endDate): array
{
@@ -110,8 +106,7 @@ public function getMemberUsage(BarobillMember $member, string $startDate, string
/**
* 통계 데이터 집계
*
- * @param array $usageList 사용량 목록
- * @return array
+ * @param array $usageList 사용량 목록
*/
public function aggregateStats(array $usageList): array
{
@@ -150,8 +145,8 @@ protected function getTaxInvoiceCount(BarobillMember $member, string $startDate,
{
try {
// YYYYMMDD -> YYYY-MM-DD 형식 변환
- $start = substr($startDate, 0, 4) . '-' . substr($startDate, 4, 2) . '-' . substr($startDate, 6, 2);
- $end = substr($endDate, 0, 4) . '-' . substr($endDate, 4, 2) . '-' . substr($endDate, 6, 2);
+ $start = substr($startDate, 0, 4).'-'.substr($startDate, 4, 2).'-'.substr($startDate, 6, 2);
+ $end = substr($endDate, 0, 4).'-'.substr($endDate, 4, 2).'-'.substr($endDate, 6, 2);
return HometaxInvoice::where('tenant_id', $member->tenant_id)
->where('invoice_type', 'sales') // 매출 (발행한 세금계산서)
@@ -197,10 +192,12 @@ protected function getBankAccountCount(BarobillMember $member, string $startDate
// GetBankAccountEx 응답: BankAccount 또는 BankAccountEx 배열
if (isset($result['data']->BankAccount)) {
$accounts = $result['data']->BankAccount;
+
return is_array($accounts) ? count($accounts) : 1;
}
if (isset($result['data']->BankAccountEx)) {
$accounts = $result['data']->BankAccountEx;
+
return is_array($accounts) ? count($accounts) : 1;
}
}
@@ -244,6 +241,7 @@ protected function getCardCount(BarobillMember $member, string $startDate, strin
// GetCardEx2 응답: CardEx 배열
if (isset($result['data']->CardEx)) {
$cards = $result['data']->CardEx;
+
return is_array($cards) ? count($cards) : 1;
}
}
@@ -268,8 +266,8 @@ protected function getHometaxCount(BarobillMember $member, string $startDate, st
{
try {
// YYYYMMDD -> YYYY-MM-DD 형식 변환
- $start = substr($startDate, 0, 4) . '-' . substr($startDate, 4, 2) . '-' . substr($startDate, 6, 2);
- $end = substr($endDate, 0, 4) . '-' . substr($endDate, 4, 2) . '-' . substr($endDate, 6, 2);
+ $start = substr($startDate, 0, 4).'-'.substr($startDate, 4, 2).'-'.substr($startDate, 6, 2);
+ $end = substr($endDate, 0, 4).'-'.substr($endDate, 4, 2).'-'.substr($endDate, 6, 2);
return HometaxInvoice::where('tenant_id', $member->tenant_id)
->whereBetween('write_date', [$start, $end])
@@ -348,7 +346,7 @@ public static function getPriceInfo(): array
// 없는 정책은 기본값으로 채움
foreach ($defaults as $type => $default) {
- if (!isset($priceInfo[$type])) {
+ if (! isset($priceInfo[$type])) {
$priceInfo[$type] = $default;
}
}
@@ -359,15 +357,15 @@ public static function getPriceInfo(): array
/**
* 사용량에 따른 과금액 계산
*
- * @param string $serviceType 서비스 유형
- * @param int $usageCount 사용량/등록 수
+ * @param string $serviceType 서비스 유형
+ * @param int $usageCount 사용량/등록 수
* @return array ['free_count' => int, 'billable_count' => int, 'billable_amount' => int]
*/
public static function calculateBillingByPolicy(string $serviceType, int $usageCount): array
{
$policy = BarobillPricingPolicy::getByServiceType($serviceType);
- if (!$policy) {
+ if (! $policy) {
// 기본 정책이 없으면 과금 없음
return [
'free_count' => $usageCount,
diff --git a/app/Services/Barobill/HometaxSyncService.php b/app/Services/Barobill/HometaxSyncService.php
index 0fd01f37..6cb02fe1 100644
--- a/app/Services/Barobill/HometaxSyncService.php
+++ b/app/Services/Barobill/HometaxSyncService.php
@@ -15,9 +15,9 @@ class HometaxSyncService
/**
* API 응답 데이터를 로컬 DB에 동기화
*
- * @param array $invoices API에서 받은 세금계산서 목록
- * @param int $tenantId 테넌트 ID
- * @param string $invoiceType 'sales' 또는 'purchase'
+ * @param array $invoices API에서 받은 세금계산서 목록
+ * @param int $tenantId 테넌트 ID
+ * @param string $invoiceType 'sales' 또는 'purchase'
* @return array 동기화 결과 ['inserted' => int, 'updated' => int, 'failed' => int]
*/
public function syncInvoices(array $invoices, int $tenantId, string $invoiceType): array
@@ -40,6 +40,7 @@ public function syncInvoices(array $invoices, int $tenantId, string $invoiceType
// 국세청승인번호가 없으면 스킵
if (empty($apiData['ntsConfirmNum'])) {
$result['failed']++;
+
continue;
}
@@ -103,13 +104,12 @@ public function syncInvoices(array $invoices, int $tenantId, string $invoiceType
/**
* 로컬 DB에서 세금계산서 목록 조회
*
- * @param int $tenantId 테넌트 ID
- * @param string $invoiceType 'sales' 또는 'purchase'
- * @param string $startDate 시작일 (Y-m-d)
- * @param string $endDate 종료일 (Y-m-d)
- * @param string $dateType 날짜 타입 ('write', 'issue', 'send')
- * @param string|null $searchCorp 거래처 검색어
- * @return array
+ * @param int $tenantId 테넌트 ID
+ * @param string $invoiceType 'sales' 또는 'purchase'
+ * @param string $startDate 시작일 (Y-m-d)
+ * @param string $endDate 종료일 (Y-m-d)
+ * @param string $dateType 날짜 타입 ('write', 'issue', 'send')
+ * @param string|null $searchCorp 거래처 검색어
*/
public function getLocalInvoices(
int $tenantId,
@@ -123,7 +123,7 @@ public function getLocalInvoices(
->where('invoice_type', $invoiceType)
->period($startDate, $endDate, $dateType);
- if (!empty($searchCorp)) {
+ if (! empty($searchCorp)) {
$query->searchCorp($searchCorp, $invoiceType);
}
@@ -215,11 +215,12 @@ public function toggleChecked(int $id, int $tenantId): bool
->where('tenant_id', $tenantId)
->first();
- if (!$invoice) {
+ if (! $invoice) {
return false;
}
- $invoice->is_checked = !$invoice->is_checked;
+ $invoice->is_checked = ! $invoice->is_checked;
+
return $invoice->save();
}
diff --git a/app/Services/BoardService.php b/app/Services/BoardService.php
index 8dd0d1ef..314b086f 100644
--- a/app/Services/BoardService.php
+++ b/app/Services/BoardService.php
@@ -424,7 +424,7 @@ public function getAllBoards(array $filters = [], int $perPage = 15): LengthAwar
// 본사: 시스템 게시판 + 본사 테넌트 게시판
$query->where(function ($q) use ($selectedTenantId) {
$q->where('is_system', true)
- ->orWhere('tenant_id', $selectedTenantId);
+ ->orWhere('tenant_id', $selectedTenantId);
});
} else {
// 일반 테넌트: 해당 테넌트 게시판만 (시스템 게시판 제외)
@@ -468,7 +468,7 @@ public function getAllBoards(array $filters = [], int $perPage = 15): LengthAwar
$sortBy = $filters['sort_by'] ?? 'id';
$sortDirection = $filters['sort_direction'] ?? 'desc';
$query->orderBy('is_system', 'desc') // 시스템 게시판 우선
- ->orderBy($sortBy, $sortDirection);
+ ->orderBy($sortBy, $sortDirection);
return $query->paginate($perPage);
}
diff --git a/app/Services/BusinessCardOcrService.php b/app/Services/BusinessCardOcrService.php
index 0fb16654..b73f3af3 100644
--- a/app/Services/BusinessCardOcrService.php
+++ b/app/Services/BusinessCardOcrService.php
@@ -38,13 +38,13 @@ private function callVertexAiApi(AiConfig $config, string $base64Image): array
$projectId = $config->getProjectId();
$region = $config->getRegion();
- if (!$projectId) {
+ if (! $projectId) {
throw new \RuntimeException('Vertex AI 프로젝트 ID가 설정되지 않았습니다.');
}
// 액세스 토큰 가져오기
$accessToken = $this->getAccessToken($config);
- if (!$accessToken) {
+ if (! $accessToken) {
throw new \RuntimeException('Google Cloud 인증 실패');
}
@@ -52,7 +52,7 @@ private function callVertexAiApi(AiConfig $config, string $base64Image): array
$url = "https://{$region}-aiplatform.googleapis.com/v1/projects/{$projectId}/locations/{$region}/publishers/google/models/{$model}:generateContent";
return $this->callGeminiApi($url, $base64Image, [
- 'Authorization' => 'Bearer ' . $accessToken,
+ 'Authorization' => 'Bearer '.$accessToken,
'Content-Type' => 'application/json',
], true); // Vertex AI
}
@@ -127,7 +127,7 @@ private function callGeminiApi(string $url, string $base64Image, array $headers,
'status' => $response->status(),
'body' => $response->body(),
]);
- throw new \RuntimeException('AI API 호출 실패: ' . $response->status());
+ throw new \RuntimeException('AI API 호출 실패: '.$response->status());
}
$result = $response->json();
@@ -178,14 +178,16 @@ private function getAccessToken(AiConfig $config): ?string
}
}
- if (!$serviceAccountPath) {
+ if (! $serviceAccountPath) {
Log::error('Service account file not found', ['tried_paths' => $possiblePaths]);
+
return null;
}
$serviceAccount = json_decode(file_get_contents($serviceAccountPath), true);
- if (!$serviceAccount) {
+ if (! $serviceAccount) {
Log::error('Service account JSON parse failed');
+
return null;
}
@@ -201,13 +203,14 @@ private function getAccessToken(AiConfig $config): ?string
]));
$privateKey = openssl_pkey_get_private($serviceAccount['private_key']);
- if (!$privateKey) {
+ if (! $privateKey) {
Log::error('Failed to load private key');
+
return null;
}
- openssl_sign($jwtHeader . '.' . $jwtClaim, $signature, $privateKey, OPENSSL_ALGO_SHA256);
- $jwt = $jwtHeader . '.' . $jwtClaim . '.' . $this->base64UrlEncode($signature);
+ openssl_sign($jwtHeader.'.'.$jwtClaim, $signature, $privateKey, OPENSSL_ALGO_SHA256);
+ $jwt = $jwtHeader.'.'.$jwtClaim.'.'.$this->base64UrlEncode($signature);
// OAuth 토큰 요청
try {
@@ -218,6 +221,7 @@ private function getAccessToken(AiConfig $config): ?string
if ($response->successful()) {
$data = $response->json();
+
return $data['access_token'] ?? null;
}
@@ -225,9 +229,11 @@ private function getAccessToken(AiConfig $config): ?string
'status' => $response->status(),
'body' => $response->body(),
]);
+
return null;
} catch (\Exception $e) {
Log::error('OAuth token request exception', ['error' => $e->getMessage()]);
+
return null;
}
}
@@ -245,7 +251,7 @@ private function base64UrlEncode(string $data): string
*/
private function buildPrompt(): string
{
- return <<orderBy('work_date', 'desc')
->orderBy('id', 'desc');
- if (!empty($params['search'])) {
+ if (! empty($params['search'])) {
$search = $params['search'];
$query->where(function ($q) use ($search) {
$q->where('site_name', 'like', "%{$search}%")
@@ -29,11 +29,11 @@ public function getList(array $params): LengthAwarePaginator
});
}
- if (!empty($params['date_from'])) {
+ if (! empty($params['date_from'])) {
$query->where('work_date', '>=', $params['date_from']);
}
- if (!empty($params['date_to'])) {
+ if (! empty($params['date_to'])) {
$query->where('work_date', '<=', $params['date_to']);
}
@@ -60,7 +60,7 @@ public function create(array $data): ConstructionSitePhoto
public function uploadPhoto(ConstructionSitePhotoRow $row, $file, string $type): bool
{
- if (!in_array($type, ['before', 'during', 'after'])) {
+ if (! in_array($type, ['before', 'during', 'after'])) {
return false;
}
@@ -70,7 +70,7 @@ public function uploadPhoto(ConstructionSitePhotoRow $row, $file, string $type):
$objectName = "construction-site-photos/{$photo->tenant_id}/{$photo->id}/{$row->id}_{$timestamp}_{$type}.{$extension}";
// 기존 사진이 있으면 GCS에서 삭제
- $oldPath = $row->{$type . '_photo_path'};
+ $oldPath = $row->{$type.'_photo_path'};
if ($oldPath) {
$this->googleCloudService->deleteFromStorage($oldPath);
}
@@ -79,7 +79,7 @@ public function uploadPhoto(ConstructionSitePhotoRow $row, $file, string $type):
$tempPath = $file->getRealPath();
$result = $this->googleCloudService->uploadToStorage($tempPath, $objectName);
- if (!$result) {
+ if (! $result) {
Log::error('ConstructionSitePhoto: GCS 업로드 실패', [
'photo_id' => $photo->id,
'row_id' => $row->id,
@@ -90,9 +90,9 @@ public function uploadPhoto(ConstructionSitePhotoRow $row, $file, string $type):
}
$row->update([
- $type . '_photo_path' => $objectName,
- $type . '_photo_gcs_uri' => $result['uri'],
- $type . '_photo_size' => $result['size'],
+ $type.'_photo_path' => $objectName,
+ $type.'_photo_gcs_uri' => $result['uri'],
+ $type.'_photo_size' => $result['size'],
]);
AiTokenHelper::saveGcsStorageUsage('공사현장사진대지-GCS저장', $result['size']);
@@ -116,7 +116,7 @@ public function delete(ConstructionSitePhoto $photo): bool
// rows 순회하여 모든 GCS 파일 삭제
foreach ($photo->rows as $row) {
foreach (['before', 'during', 'after'] as $type) {
- $path = $row->{$type . '_photo_path'};
+ $path = $row->{$type.'_photo_path'};
if ($path) {
$this->googleCloudService->deleteFromStorage($path);
}
@@ -128,19 +128,19 @@ public function delete(ConstructionSitePhoto $photo): bool
public function deletePhotoByType(ConstructionSitePhotoRow $row, string $type): bool
{
- if (!in_array($type, ['before', 'during', 'after'])) {
+ if (! in_array($type, ['before', 'during', 'after'])) {
return false;
}
- $path = $row->{$type . '_photo_path'};
+ $path = $row->{$type.'_photo_path'};
if ($path) {
$this->googleCloudService->deleteFromStorage($path);
}
$row->update([
- $type . '_photo_path' => null,
- $type . '_photo_gcs_uri' => null,
- $type . '_photo_size' => null,
+ $type.'_photo_path' => null,
+ $type.'_photo_gcs_uri' => null,
+ $type.'_photo_size' => null,
]);
return true;
@@ -157,7 +157,7 @@ public function deleteRow(ConstructionSitePhotoRow $row): bool
{
// 행의 GCS 파일 삭제
foreach (['before', 'during', 'after'] as $type) {
- $path = $row->{$type . '_photo_path'};
+ $path = $row->{$type.'_photo_path'};
if ($path) {
$this->googleCloudService->deleteFromStorage($path);
}
diff --git a/app/Services/Coocon/CooconService.php b/app/Services/Coocon/CooconService.php
index 476ddcd9..30988ac1 100644
--- a/app/Services/Coocon/CooconService.php
+++ b/app/Services/Coocon/CooconService.php
@@ -13,17 +13,24 @@
class CooconService
{
private ?CooconConfig $config = null;
+
private bool $isTestMode = true;
/**
* API ID 상수
*/
public const API_COMPANY_INFO = 'OA08'; // 기업 기본정보
+
public const API_CREDIT_SUMMARY = 'OA12'; // 신용요약정보
+
public const API_SHORT_TERM_OVERDUE = 'OA13'; // 단기연체정보 (한국신용정보원)
+
public const API_NEGATIVE_INFO_KCI = 'OA14'; // 신용도판단정보 (한국신용정보원)
+
public const API_NEGATIVE_INFO_CB = 'OA15'; // 신용도판단정보 (신용정보사)
+
public const API_SUSPENSION_INFO = 'OA16'; // 당좌거래정지정보 (금융결제원)
+
public const API_WORKOUT_INFO = 'OA17'; // 법정관리/워크아웃정보
/**
@@ -43,6 +50,7 @@ class CooconService
* 기본 URL
*/
private const BASE_URL_TEST = 'https://dev2.coocon.co.kr:8443/sol/gateway/oapi_relay.jsp';
+
private const BASE_URL_PRODUCTION = 'https://sgw.coocon.co.kr/sol/gateway/oapi_relay.jsp';
public function __construct(bool $isTestMode = true)
@@ -65,6 +73,7 @@ private function loadConfig(): void
public function reloadConfig(): self
{
$this->loadConfig();
+
return $this;
}
@@ -75,6 +84,7 @@ public function setTestMode(bool $isTestMode): self
{
$this->isTestMode = $isTestMode;
$this->loadConfig();
+
return $this;
}
@@ -111,7 +121,7 @@ private function getBaseUrl(): string
*/
private function callApi(string $apiId, array $params = []): array
{
- if (!$this->config) {
+ if (! $this->config) {
return [
'success' => false,
'error' => '쿠콘 API 설정이 없습니다. 설정을 먼저 등록해주세요.',
@@ -151,10 +161,10 @@ private function callApi(string $apiId, array $params = []): array
'rslt_msg' => $result['RSLT_MSG'] ?? 'N/A',
]);
- if (!$response->successful()) {
+ if (! $response->successful()) {
return [
'success' => false,
- 'error' => 'HTTP 오류: ' . $response->status(),
+ 'error' => 'HTTP 오류: '.$response->status(),
'code' => 'HTTP_ERROR',
'http_status' => $response->status(),
];
@@ -186,7 +196,7 @@ private function callApi(string $apiId, array $params = []): array
return [
'success' => false,
- 'error' => '쿠콘 API 호출 중 오류가 발생했습니다: ' . $e->getMessage(),
+ 'error' => '쿠콘 API 호출 중 오류가 발생했습니다: '.$e->getMessage(),
'code' => 'EXCEPTION',
];
}
@@ -197,14 +207,14 @@ private function callApi(string $apiId, array $params = []): array
*/
private function generateTransactionSequence(): string
{
- return date('YmdHis') . substr(microtime(), 2, 6);
+ return date('YmdHis').substr(microtime(), 2, 6);
}
/**
* 기업 기본정보 조회 (OA08)
*
- * @param string $companyKey 사업자번호, 법인번호, 업체코드 중 하나
- * @param string $idscdcg 식별자구분코드 (기본값: 09-사업자등록번호)
+ * @param string $companyKey 사업자번호, 법인번호, 업체코드 중 하나
+ * @param string $idscdcg 식별자구분코드 (기본값: 09-사업자등록번호)
*/
public function getCompanyInfo(string $companyKey, string $idscdcg = '09'): array
{
@@ -217,7 +227,7 @@ public function getCompanyInfo(string $companyKey, string $idscdcg = '09'): arra
/**
* 신용요약정보 조회 (OA12)
*
- * @param string $companyKey 사업자번호, 법인번호, 업체코드 중 하나
+ * @param string $companyKey 사업자번호, 법인번호, 업체코드 중 하나
*/
public function getCreditSummary(string $companyKey): array
{
@@ -229,8 +239,8 @@ public function getCreditSummary(string $companyKey): array
/**
* 단기연체정보 조회 (OA13) - 한국신용정보원
*
- * @param string $companyKey 사업자번호, 법인번호, 업체코드 중 하나
- * @param string|null $reqDate 기준일자 (YYYYMMDD), 미입력시 현재 날짜
+ * @param string $companyKey 사업자번호, 법인번호, 업체코드 중 하나
+ * @param string|null $reqDate 기준일자 (YYYYMMDD), 미입력시 현재 날짜
*/
public function getShortTermOverdueInfo(string $companyKey, ?string $reqDate = null): array
{
@@ -246,7 +256,7 @@ public function getShortTermOverdueInfo(string $companyKey, ?string $reqDate = n
/**
* 신용도판단정보 조회 (OA14) - 한국신용정보원 (공공정보 포함)
*
- * @param string $companyKey 사업자번호, 법인번호, 업체코드 중 하나
+ * @param string $companyKey 사업자번호, 법인번호, 업체코드 중 하나
*/
public function getNegativeInfoKCI(string $companyKey): array
{
@@ -258,7 +268,7 @@ public function getNegativeInfoKCI(string $companyKey): array
/**
* 신용도판단정보 조회 (OA15) - 신용정보사
*
- * @param string $companyKey 사업자번호, 법인번호, 업체코드 중 하나
+ * @param string $companyKey 사업자번호, 법인번호, 업체코드 중 하나
*/
public function getNegativeInfoCB(string $companyKey): array
{
@@ -270,7 +280,7 @@ public function getNegativeInfoCB(string $companyKey): array
/**
* 당좌거래정지정보 조회 (OA16) - 금융결제원
*
- * @param string $companyKey 사업자번호, 법인번호, 업체코드 중 하나
+ * @param string $companyKey 사업자번호, 법인번호, 업체코드 중 하나
*/
public function getSuspensionInfo(string $companyKey): array
{
@@ -282,9 +292,9 @@ public function getSuspensionInfo(string $companyKey): array
/**
* 법정관리/워크아웃정보 조회 (OA17)
*
- * @param string $companyKey 사업자번호, 법인번호, 업체코드 중 하나
- * @param int $pageNo 페이지 번호
- * @param int $pageSize 페이지 사이즈
+ * @param string $companyKey 사업자번호, 법인번호, 업체코드 중 하나
+ * @param int $pageNo 페이지 번호
+ * @param int $pageSize 페이지 사이즈
*/
public function getWorkoutInfo(string $companyKey, int $pageNo = 1, int $pageSize = 10): array
{
@@ -298,7 +308,7 @@ public function getWorkoutInfo(string $companyKey, int $pageNo = 1, int $pageSiz
/**
* 전체 신용정보 조회 (모든 API 호출)
*
- * @param string $companyKey 사업자번호, 법인번호, 업체코드 중 하나
+ * @param string $companyKey 사업자번호, 법인번호, 업체코드 중 하나
*/
public function getAllCreditInfo(string $companyKey): array
{
diff --git a/app/Services/ESign/DocxToPdfConverter.php b/app/Services/ESign/DocxToPdfConverter.php
index ad54cc05..7a45db65 100644
--- a/app/Services/ESign/DocxToPdfConverter.php
+++ b/app/Services/ESign/DocxToPdfConverter.php
@@ -16,7 +16,7 @@ class DocxToPdfConverter
*/
public function convertAndStore(UploadedFile $file, string $storagePath): array
{
- if (!$this->isWordFile($file)) {
+ if (! $this->isWordFile($file)) {
// PDF는 그대로 저장
$path = $file->store($storagePath, 'local');
@@ -32,11 +32,11 @@ public function convertAndStore(UploadedFile $file, string $storagePath): array
$originalName = $file->getClientOriginalName();
$pdfName = preg_replace('/\.(docx?|DOCX?)$/', '.pdf', $originalName);
- $tmpDir = sys_get_temp_dir() . '/esign_convert_' . Str::random(16);
+ $tmpDir = sys_get_temp_dir().'/esign_convert_'.Str::random(16);
mkdir($tmpDir, 0755, true);
try {
- $tmpWordPath = $tmpDir . '/' . 'source.' . $file->getClientOriginalExtension();
+ $tmpWordPath = $tmpDir.'/'.'source.'.$file->getClientOriginalExtension();
copy($file->getRealPath(), $tmpWordPath);
$command = sprintf(
@@ -50,12 +50,12 @@ public function convertAndStore(UploadedFile $file, string $storagePath): array
if ($exitCode !== 0) {
throw new RuntimeException(
- 'LibreOffice 변환 실패 (exit code: ' . $exitCode . '): ' . implode("\n", $output)
+ 'LibreOffice 변환 실패 (exit code: '.$exitCode.'): '.implode("\n", $output)
);
}
- $tmpPdfPath = $tmpDir . '/source.pdf';
- if (!file_exists($tmpPdfPath)) {
+ $tmpPdfPath = $tmpDir.'/source.pdf';
+ if (! file_exists($tmpPdfPath)) {
throw new RuntimeException('변환된 PDF 파일을 찾을 수 없습니다.');
}
@@ -63,7 +63,7 @@ public function convertAndStore(UploadedFile $file, string $storagePath): array
$size = filesize($tmpPdfPath);
// 최종 저장 경로
- $finalPath = $storagePath . '/' . Str::random(40) . '.pdf';
+ $finalPath = $storagePath.'/'.Str::random(40).'.pdf';
Storage::disk('local')->put($finalPath, file_get_contents($tmpPdfPath));
return [
@@ -74,7 +74,7 @@ public function convertAndStore(UploadedFile $file, string $storagePath): array
];
} finally {
// 임시 파일 정리
- array_map('unlink', glob($tmpDir . '/*'));
+ array_map('unlink', glob($tmpDir.'/*'));
@rmdir($tmpDir);
}
}
diff --git a/app/Services/ESign/PdfSignatureService.php b/app/Services/ESign/PdfSignatureService.php
index bedf35c5..ccd00d5f 100644
--- a/app/Services/ESign/PdfSignatureService.php
+++ b/app/Services/ESign/PdfSignatureService.php
@@ -42,7 +42,7 @@ public function mergeSignatures(EsignContract $contract): string
}
// FPDI(TCPDF 확장)로 원본 PDF 임포트
- $pdf = new Fpdi();
+ $pdf = new Fpdi;
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
@@ -91,7 +91,7 @@ public function mergeSignatures(EsignContract $contract): string
'signed_file_hash' => hash_file('sha256', $signedAbsPath),
]);
- Log::info("PDF 서명 합성 완료", [
+ Log::info('PDF 서명 합성 완료', [
'contract_id' => $contract->id,
'signed_file_path' => $signedRelPath,
]);
@@ -112,7 +112,7 @@ public function generatePreview(EsignContract $contract): string
throw new \RuntimeException("원본 PDF 파일이 존재하지 않습니다: {$contract->original_file_path}");
}
- $pdf = new Fpdi();
+ $pdf = new Fpdi;
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
@@ -199,10 +199,11 @@ private function overlayImage(Fpdi $pdf, EsignSignField $field, float $x, float
$imagePath = Storage::disk('local')->path($signer->signature_image_path);
if (! file_exists($imagePath)) {
- Log::warning("서명 이미지 파일 없음", [
+ Log::warning('서명 이미지 파일 없음', [
'signer_id' => $signer->id,
'path' => $signer->signature_image_path,
]);
+
return;
}
diff --git a/app/Services/FcmApiService.php b/app/Services/FcmApiService.php
index f3ca3a5e..7d97ae83 100644
--- a/app/Services/FcmApiService.php
+++ b/app/Services/FcmApiService.php
@@ -111,4 +111,4 @@ public function previewCount(array $filters): array
];
}
}
-}
\ No newline at end of file
+}
diff --git a/app/Services/FlowTester/ConditionEvaluator.php b/app/Services/FlowTester/ConditionEvaluator.php
index a4f3ba3d..acc0589c 100644
--- a/app/Services/FlowTester/ConditionEvaluator.php
+++ b/app/Services/FlowTester/ConditionEvaluator.php
@@ -505,4 +505,4 @@ public function getStepResults(): array
{
return $this->stepResults;
}
-}
\ No newline at end of file
+}
diff --git a/app/Services/FlowTester/FlowExecutor.php b/app/Services/FlowTester/FlowExecutor.php
index 4b70177f..f50434f6 100644
--- a/app/Services/FlowTester/FlowExecutor.php
+++ b/app/Services/FlowTester/FlowExecutor.php
@@ -239,6 +239,7 @@ private function checkDependencies(array $step): array
// 의존 스텝이 아직 실행되지 않은 경우 (순서 문제)
if ($depResult === null && ! isset($this->stepSuccessMap[$depId])) {
$failedDeps[] = "{$depId} (not executed yet)";
+
continue;
}
diff --git a/app/Services/FormulaApiService.php b/app/Services/FormulaApiService.php
index 74386266..df6ca8b5 100644
--- a/app/Services/FormulaApiService.php
+++ b/app/Services/FormulaApiService.php
@@ -16,9 +16,9 @@ class FormulaApiService
* - SSL 우회: withoutVerifying() (내부 자체 서명 인증서)
* - 인증: X-API-KEY + Bearer token (ApiTokenService 토큰 교환)
*
- * @param string $finishedGoodsCode 완제품 코드 (예: FG-KQTS01)
- * @param array $variables 입력 변수 ['W0' => 3000, 'H0' => 3000, 'QTY' => 1]
- * @param int $tenantId 테넌트 ID
+ * @param string $finishedGoodsCode 완제품 코드 (예: FG-KQTS01)
+ * @param array $variables 입력 변수 ['W0' => 3000, 'H0' => 3000, 'QTY' => 1]
+ * @param int $tenantId 테넌트 ID
* @return array 성공 시 API 응답, 실패 시 ['success' => false, 'error' => '...']
*/
public function calculateBom(string $finishedGoodsCode, array $variables, int $tenantId): array
@@ -54,6 +54,7 @@ public function calculateBom(string $finishedGoodsCode, array $variables, int $t
if ($response->successful()) {
$json = $response->json();
+
// ApiResponse::handle()는 {success, message, data} 구조로 래핑
return $json['data'] ?? $json;
}
@@ -66,7 +67,7 @@ public function calculateBom(string $finishedGoodsCode, array $variables, int $t
return [
'success' => false,
- 'error' => 'API 응답 오류: HTTP ' . $response->status(),
+ 'error' => 'API 응답 오류: HTTP '.$response->status(),
];
} catch (\Exception $e) {
Log::error('FormulaApiService: 예외 발생', [
@@ -76,7 +77,7 @@ public function calculateBom(string $finishedGoodsCode, array $variables, int $t
return [
'success' => false,
- 'error' => '수식 계산 서버 연결 실패: ' . $e->getMessage(),
+ 'error' => '수식 계산 서버 연결 실패: '.$e->getMessage(),
];
}
}
diff --git a/app/Services/FundScheduleService.php b/app/Services/FundScheduleService.php
index a5c55abc..15290918 100644
--- a/app/Services/FundScheduleService.php
+++ b/app/Services/FundScheduleService.php
@@ -315,13 +315,13 @@ public function getMonthlySummary(int $year, int $month): array
'count' => $incomeSchedules->count(),
'total' => $incomeSchedules->sum('amount'),
'pending' => $incomeSchedules->where('status', FundSchedule::STATUS_PENDING)->sum('amount'),
- 'completed' => $incomeSchedules->where('status', FundSchedule::STATUS_COMPLETED)->sum(fn($s) => $s->completed_amount ?: $s->amount),
+ 'completed' => $incomeSchedules->where('status', FundSchedule::STATUS_COMPLETED)->sum(fn ($s) => $s->completed_amount ?: $s->amount),
],
'expense' => [
'count' => $expenseSchedules->count(),
'total' => $expenseSchedules->sum('amount'),
'pending' => $expenseSchedules->where('status', FundSchedule::STATUS_PENDING)->sum('amount'),
- 'completed' => $expenseSchedules->where('status', FundSchedule::STATUS_COMPLETED)->sum(fn($s) => $s->completed_amount ?: $s->amount),
+ 'completed' => $expenseSchedules->where('status', FundSchedule::STATUS_COMPLETED)->sum(fn ($s) => $s->completed_amount ?: $s->amount),
],
'net' => $incomeSchedules->sum('amount') - $expenseSchedules->sum('amount'),
];
diff --git a/app/Services/GoogleCloudService.php b/app/Services/GoogleCloudService.php
index f9406d75..549029bf 100644
--- a/app/Services/GoogleCloudService.php
+++ b/app/Services/GoogleCloudService.php
@@ -97,6 +97,7 @@ public function getAccessToken(): ?string
/**
* GCS에 파일 업로드
+ *
* @return array|null ['uri' => 'gs://...', 'size' => bytes] or null
*/
public function uploadToStorage(string $localPath, string $objectName): ?array
@@ -153,6 +154,7 @@ public function uploadToStorage(string $localPath, string $objectName): ?array
/**
* Base64 오디오를 GCS에 업로드
+ *
* @return array|null ['uri' => 'gs://...', 'size' => bytes] or null
*/
public function uploadBase64Audio(string $base64Audio, string $objectName): ?array
@@ -415,7 +417,7 @@ private function parseDiarizationResult(array $operationResult): ?array
// word-level 결과 없으면 일반 transcript로 폴백
$transcript = '';
foreach ($results as $res) {
- $transcript .= ($res['alternatives'][0]['transcript'] ?? '') . ' ';
+ $transcript .= ($res['alternatives'][0]['transcript'] ?? '').' ';
}
$transcript = $this->cleanSttText(trim($transcript));
@@ -428,7 +430,7 @@ private function parseDiarizationResult(array $operationResult): ?array
'end_time_ms' => null,
'is_manual_speaker' => false,
]],
- 'full_transcript' => '[화자 1] ' . $transcript,
+ 'full_transcript' => '[화자 1] '.$transcript,
'speaker_count' => 1,
];
}
@@ -457,7 +459,7 @@ private function parseDiarizationResult(array $operationResult): ?array
if ($speakerTag !== $currentSpeaker && $currentSpeaker !== null && ! empty($currentTokens)) {
$segments[] = [
- 'speaker_name' => '화자 ' . $currentSpeaker,
+ 'speaker_name' => '화자 '.$currentSpeaker,
'speaker_label' => (string) $currentSpeaker,
'text' => $this->joinSentencePieceTokens($currentTokens),
'start_time_ms' => $segmentStartMs,
@@ -476,7 +478,7 @@ private function parseDiarizationResult(array $operationResult): ?array
if (! empty($currentTokens)) {
$lastWord = end($words);
$segments[] = [
- 'speaker_name' => '화자 ' . $currentSpeaker,
+ 'speaker_name' => '화자 '.$currentSpeaker,
'speaker_label' => (string) $currentSpeaker,
'text' => $this->joinSentencePieceTokens($currentTokens),
'start_time_ms' => $segmentStartMs,
@@ -526,7 +528,7 @@ private function joinSentencePieceTokens(array $tokens): string
if ($i === 0) {
$result = $token['text'];
} elseif ($token['new_word']) {
- $result .= ' ' . $token['text'];
+ $result .= ' '.$token['text'];
} else {
$result .= $token['text'];
}
@@ -739,7 +741,7 @@ private function parseV2Result(array $operationResult, string $gcsUri): ?array
// word-level 결과 없으면 일반 transcript 사용
$transcript = '';
foreach ($results as $res) {
- $transcript .= ($res['alternatives'][0]['transcript'] ?? '') . ' ';
+ $transcript .= ($res['alternatives'][0]['transcript'] ?? '').' ';
}
$transcript = trim($transcript);
@@ -752,7 +754,7 @@ private function parseV2Result(array $operationResult, string $gcsUri): ?array
'end_time_ms' => null,
'is_manual_speaker' => false,
]],
- 'full_transcript' => '[화자 1] ' . $transcript,
+ 'full_transcript' => '[화자 1] '.$transcript,
'speaker_count' => 1,
];
}
@@ -789,7 +791,7 @@ private function parseV2Result(array $operationResult, string $gcsUri): ?array
if ($speakerTag !== $currentSpeaker && $currentSpeaker !== null && ! empty($currentTokens)) {
$segments[] = [
- 'speaker_name' => '화자 ' . $currentSpeaker,
+ 'speaker_name' => '화자 '.$currentSpeaker,
'speaker_label' => (string) $currentSpeaker,
'text' => $this->joinSentencePieceTokens($currentTokens),
'start_time_ms' => $segmentStartMs,
@@ -806,7 +808,7 @@ private function parseV2Result(array $operationResult, string $gcsUri): ?array
// 일반 단어 방식 처리 (Chirp 2)
if ($speakerTag !== $currentSpeaker && $currentSpeaker !== null && ! empty($currentWords)) {
$segments[] = [
- 'speaker_name' => '화자 ' . $currentSpeaker,
+ 'speaker_name' => '화자 '.$currentSpeaker,
'speaker_label' => (string) $currentSpeaker,
'text' => implode(' ', $currentWords),
'start_time_ms' => $segmentStartMs,
@@ -826,7 +828,7 @@ private function parseV2Result(array $operationResult, string $gcsUri): ?array
if ($hasSentencePiece && ! empty($currentTokens)) {
$lastWord = end($words);
$segments[] = [
- 'speaker_name' => '화자 ' . $currentSpeaker,
+ 'speaker_name' => '화자 '.$currentSpeaker,
'speaker_label' => (string) $currentSpeaker,
'text' => $this->joinSentencePieceTokens($currentTokens),
'start_time_ms' => $segmentStartMs,
@@ -836,7 +838,7 @@ private function parseV2Result(array $operationResult, string $gcsUri): ?array
} elseif (! $hasSentencePiece && ! empty($currentWords)) {
$lastWord = end($words);
$segments[] = [
- 'speaker_name' => '화자 ' . $currentSpeaker,
+ 'speaker_name' => '화자 '.$currentSpeaker,
'speaker_label' => (string) $currentSpeaker,
'text' => implode(' ', $currentWords),
'start_time_ms' => $segmentStartMs,
diff --git a/app/Services/ItemManagementService.php b/app/Services/ItemManagementService.php
index cc7bc861..1ed13b75 100644
--- a/app/Services/ItemManagementService.php
+++ b/app/Services/ItemManagementService.php
@@ -57,7 +57,7 @@ public function getItemDetail(int $itemId): array
// BOM 1depth: 직접 연결된 자식 품목만
$bomChildren = [];
$bomData = $item->bom ?? [];
- if (!empty($bomData)) {
+ if (! empty($bomData)) {
$childIds = array_column($bomData, 'child_item_id');
$children = Item::withoutGlobalScopes()
->where('tenant_id', $tenantId)
@@ -99,7 +99,7 @@ private function buildBomNode(Item $item, int $depth, int $maxDepth, array $visi
$children = [];
$bomData = $item->bom ?? [];
- if (!empty($bomData)) {
+ if (! empty($bomData)) {
$childIds = array_column($bomData, 'child_item_id');
$childItems = Item::withoutGlobalScopes()
->where('tenant_id', session('selected_tenant_id'))
diff --git a/app/Services/MeetingMinuteService.php b/app/Services/MeetingMinuteService.php
index e7ae1ee3..74206bf6 100644
--- a/app/Services/MeetingMinuteService.php
+++ b/app/Services/MeetingMinuteService.php
@@ -391,7 +391,7 @@ private function splitSpeakersWithGemini(string $fullText, int $expectedSpeakers
continue;
}
$segments[] = [
- 'speaker_name' => '화자 ' . $speakerNum,
+ 'speaker_name' => '화자 '.$speakerNum,
'speaker_label' => (string) $speakerNum,
'text' => $text,
'start_time_ms' => 0,
@@ -505,7 +505,7 @@ private function callVertexAiApi(AiConfig $config, string $prompt): ?string
$url = "https://{$region}-aiplatform.googleapis.com/v1/projects/{$projectId}/locations/{$region}/publishers/google/models/{$model}:generateContent";
return $this->callGeminiApi($url, $prompt, [
- 'Authorization' => 'Bearer ' . $accessToken,
+ 'Authorization' => 'Bearer '.$accessToken,
'Content-Type' => 'application/json',
], true);
}
@@ -554,8 +554,8 @@ private function getAccessToken(AiConfig $config): ?string
return null;
}
- openssl_sign($jwtHeader . '.' . $jwtClaim, $signature, $privateKey, OPENSSL_ALGO_SHA256);
- $jwt = $jwtHeader . '.' . $jwtClaim . '.' . $this->base64UrlEncode($signature);
+ openssl_sign($jwtHeader.'.'.$jwtClaim, $signature, $privateKey, OPENSSL_ALGO_SHA256);
+ $jwt = $jwtHeader.'.'.$jwtClaim.'.'.$this->base64UrlEncode($signature);
try {
$response = Http::asForm()->post('https://oauth2.googleapis.com/token', [
diff --git a/app/Services/Nts/NtsBusinessService.php b/app/Services/Nts/NtsBusinessService.php
index c64e3416..1f618d70 100644
--- a/app/Services/Nts/NtsBusinessService.php
+++ b/app/Services/Nts/NtsBusinessService.php
@@ -29,8 +29,7 @@ public function __construct()
/**
* 사업자등록 상태 조회
*
- * @param string $businessNumber 사업자등록번호 (10자리, 하이픈 없이)
- * @return array
+ * @param string $businessNumber 사업자등록번호 (10자리, 하이픈 없이)
*/
public function getBusinessStatus(string $businessNumber): array
{
@@ -45,7 +44,7 @@ public function getBusinessStatus(string $businessNumber): array
];
}
- $url = self::API_URL . '?serviceKey=' . $this->serviceKey;
+ $url = self::API_URL.'?serviceKey='.$this->serviceKey;
Log::info('국세청 사업자등록 상태 조회', [
'biz_no' => $bizNo,
@@ -69,10 +68,10 @@ public function getBusinessStatus(string $businessNumber): array
'status_code' => $response->status(),
]);
- if (!$response->successful()) {
+ if (! $response->successful()) {
return [
'success' => false,
- 'error' => 'HTTP 오류: ' . $response->status(),
+ 'error' => 'HTTP 오류: '.$response->status(),
'code' => 'HTTP_ERROR',
'http_status' => $response->status(),
];
@@ -119,7 +118,7 @@ public function getBusinessStatus(string $businessNumber): array
return [
'success' => false,
- 'error' => '국세청 API 호출 중 오류가 발생했습니다: ' . $e->getMessage(),
+ 'error' => '국세청 API 호출 중 오류가 발생했습니다: '.$e->getMessage(),
'code' => 'EXCEPTION',
];
}
@@ -128,8 +127,7 @@ public function getBusinessStatus(string $businessNumber): array
/**
* 여러 사업자번호 일괄 상태 조회
*
- * @param array $businessNumbers 사업자등록번호 배열
- * @return array
+ * @param array $businessNumbers 사업자등록번호 배열
*/
public function getBusinessStatusBulk(array $businessNumbers): array
{
@@ -138,7 +136,7 @@ public function getBusinessStatusBulk(array $businessNumbers): array
}, $businessNumbers);
// 유효하지 않은 번호 필터링
- $validBizNos = array_filter($bizNos, fn($num) => strlen($num) === 10);
+ $validBizNos = array_filter($bizNos, fn ($num) => strlen($num) === 10);
if (empty($validBizNos)) {
return [
@@ -148,7 +146,7 @@ public function getBusinessStatusBulk(array $businessNumbers): array
];
}
- $url = self::API_URL . '?serviceKey=' . $this->serviceKey;
+ $url = self::API_URL.'?serviceKey='.$this->serviceKey;
try {
$response = Http::timeout(30)
@@ -162,10 +160,10 @@ public function getBusinessStatusBulk(array $businessNumbers): array
$result = $response->json();
- if (!$response->successful()) {
+ if (! $response->successful()) {
return [
'success' => false,
- 'error' => 'HTTP 오류: ' . $response->status(),
+ 'error' => 'HTTP 오류: '.$response->status(),
'code' => 'HTTP_ERROR',
];
}
@@ -179,7 +177,7 @@ public function getBusinessStatusBulk(array $businessNumbers): array
} catch (\Exception $e) {
return [
'success' => false,
- 'error' => '국세청 API 호출 중 오류가 발생했습니다: ' . $e->getMessage(),
+ 'error' => '국세청 API 호출 중 오류가 발생했습니다: '.$e->getMessage(),
'code' => 'EXCEPTION',
];
}
diff --git a/app/Services/NumberingRuleService.php b/app/Services/NumberingRuleService.php
index 7ffed286..7642683f 100644
--- a/app/Services/NumberingRuleService.php
+++ b/app/Services/NumberingRuleService.php
@@ -106,8 +106,8 @@ public function generatePreview(array $pattern, int $sequencePadding = 2): strin
'static' => $segment['value'] ?? '',
'separator' => $segment['value'] ?? '',
'date' => now()->format($segment['format'] ?? 'ymd'),
- 'param' => $segment['default'] ?? '{' . ($segment['key'] ?? '?') . '}',
- 'mapping' => $segment['default'] ?? '{' . ($segment['key'] ?? '?') . '}',
+ 'param' => $segment['default'] ?? '{'.($segment['key'] ?? '?').'}',
+ 'mapping' => $segment['default'] ?? '{'.($segment['key'] ?? '?').'}',
'sequence' => str_pad('1', $sequencePadding, '0', STR_PAD_LEFT),
default => '',
};
diff --git a/app/Services/PartitionManagementService.php b/app/Services/PartitionManagementService.php
index f4bec8fb..33ac4c43 100644
--- a/app/Services/PartitionManagementService.php
+++ b/app/Services/PartitionManagementService.php
@@ -113,7 +113,7 @@ public function addFuturePartitions(int $months): array
for ($i = 0; $i <= $months; $i++) {
$target = $now->copy()->addMonths($i)->startOfMonth()->addMonth();
$ts = $target->timestamp;
- $name = 'p' . $target->copy()->subMonth()->format('Ym');
+ $name = 'p'.$target->copy()->subMonth()->format('Ym');
if (in_array($ts, $existingBounds)) {
continue;
diff --git a/app/Services/Sales/InterviewScenarioService.php b/app/Services/Sales/InterviewScenarioService.php
index 6a35afb2..f75247dc 100644
--- a/app/Services/Sales/InterviewScenarioService.php
+++ b/app/Services/Sales/InterviewScenarioService.php
@@ -223,11 +223,11 @@ public function getSessions(array $filters = [])
->orderByDesc('interview_date')
->orderByDesc('id');
- if (!empty($filters['status'])) {
+ if (! empty($filters['status'])) {
$query->where('status', $filters['status']);
}
- if (!empty($filters['category_id'])) {
+ if (! empty($filters['category_id'])) {
$query->where('interview_category_id', $filters['category_id']);
}
@@ -249,7 +249,7 @@ public function startSession(array $data): InterviewSession
->orderBy('sort_order')
->get();
- $totalQuestions = $templates->sum(fn($t) => $t->questions->count());
+ $totalQuestions = $templates->sum(fn ($t) => $t->questions->count());
// 세션 생성
$session = InterviewSession::create([
@@ -302,7 +302,7 @@ public function toggleAnswer(array $data): InterviewAnswer
->firstOrFail();
$answer->update([
- 'is_checked' => !$answer->is_checked,
+ 'is_checked' => ! $answer->is_checked,
'answer_text' => $data['answer_text'] ?? $answer->answer_text,
'memo' => $data['memo'] ?? $answer->memo,
]);
diff --git a/app/Services/Sales/SalesDevelopmentApprovalService.php b/app/Services/Sales/SalesDevelopmentApprovalService.php
index 62ee5150..d4124798 100644
--- a/app/Services/Sales/SalesDevelopmentApprovalService.php
+++ b/app/Services/Sales/SalesDevelopmentApprovalService.php
@@ -3,9 +3,7 @@
namespace App\Services\Sales;
use App\Models\Sales\SalesTenantManagement;
-use App\Models\Tenants\Tenant;
use Illuminate\Pagination\LengthAwarePaginator;
-use Illuminate\Support\Facades\DB;
/**
* 개발 승인 관리 서비스
@@ -168,8 +166,8 @@ public function reject(int $id, string $reason): SalesTenantManagement
// notes 필드에 반려 사유 추가
$currentNotes = $management->notes ?? '';
- $rejectionNote = '[반려 ' . now()->format('Y-m-d H:i') . '] ' . $reason;
- $newNotes = $currentNotes ? $currentNotes . "\n" . $rejectionNote : $rejectionNote;
+ $rejectionNote = '[반려 '.now()->format('Y-m-d H:i').'] '.$reason;
+ $newNotes = $currentNotes ? $currentNotes."\n".$rejectionNote : $rejectionNote;
$management->update([
'notes' => $newNotes,
@@ -186,7 +184,7 @@ public function updateHqStatus(int $id, string $status): SalesTenantManagement
$management = SalesTenantManagement::findOrFail($id);
// 유효한 상태인지 확인
- if (!array_key_exists($status, SalesTenantManagement::$hqStatusLabels)) {
+ if (! array_key_exists($status, SalesTenantManagement::$hqStatusLabels)) {
throw new \InvalidArgumentException('유효하지 않은 상태입니다.');
}
diff --git a/app/Services/Sales/SalesManagerService.php b/app/Services/Sales/SalesManagerService.php
index 4b44d543..d9854c4a 100644
--- a/app/Services/Sales/SalesManagerService.php
+++ b/app/Services/Sales/SalesManagerService.php
@@ -51,7 +51,7 @@ public function createSalesPartner(array $data, array $documents = []): User
]);
// 3. 역할 할당
- if (!empty($data['role_ids'])) {
+ if (! empty($data['role_ids'])) {
$this->syncRoles($user, $tenantId, $data['role_ids']);
}
@@ -59,7 +59,7 @@ public function createSalesPartner(array $data, array $documents = []): User
$this->assignSalesDepartment($user, $tenantId);
// 4-1. 사업자 정보 저장 (선택)
- if (!empty($data['company_name']) || !empty($data['biz_no']) || !empty($data['address'])) {
+ if (! empty($data['company_name']) || ! empty($data['biz_no']) || ! empty($data['address'])) {
$partnerType = $data['partner_type'] ?? 'individual';
$spData = [
'partner_code' => SalesPartner::generatePartnerCode(),
@@ -84,7 +84,7 @@ public function createSalesPartner(array $data, array $documents = []): User
}
// 5. 첨부 서류 저장
- if (!empty($documents)) {
+ if (! empty($documents)) {
$this->uploadDocuments($user, $tenantId, $documents);
}
@@ -108,7 +108,7 @@ public function updateSalesPartner(User $user, array $data, array $documents = [
];
// 비밀번호 변경 시에만 업데이트
- if (!empty($data['password'])) {
+ if (! empty($data['password'])) {
$updateData['password'] = Hash::make($data['password']);
}
@@ -120,13 +120,13 @@ public function updateSalesPartner(User $user, array $data, array $documents = [
}
// 2-1. 사업자 정보 업데이트
- $hasBizInfo = !empty($data['company_name']) || !empty($data['biz_no']) || !empty($data['address']);
+ $hasBizInfo = ! empty($data['company_name']) || ! empty($data['biz_no']) || ! empty($data['address']);
$existingSp = SalesPartner::where('user_id', $user->id)->first();
- $hasPartnerType = !empty($data['partner_type']);
+ $hasPartnerType = ! empty($data['partner_type']);
if ($hasBizInfo || $existingSp || $hasPartnerType) {
$sp = $existingSp ?? new SalesPartner(['user_id' => $user->id]);
- if (!$sp->exists) {
+ if (! $sp->exists) {
$sp->partner_code = SalesPartner::generatePartnerCode();
$sp->partner_type = $data['partner_type'] ?? 'individual';
$sp->status = 'active';
@@ -151,7 +151,7 @@ public function updateSalesPartner(User $user, array $data, array $documents = [
}
// 3. 새 첨부 서류 저장
- if (!empty($documents)) {
+ if (! empty($documents)) {
$this->uploadDocuments($user, $tenantId, $documents);
}
@@ -194,9 +194,9 @@ public function reject(User $user, int $approverId, string $reason): User
/**
* 역할 위임
*
- * @param User $fromUser 역할을 넘기는 파트너
- * @param User $toUser 역할을 받는 파트너
- * @param string $roleName 위임할 역할 (manager, recruiter 등)
+ * @param User $fromUser 역할을 넘기는 파트너
+ * @param User $toUser 역할을 받는 파트너
+ * @param string $roleName 위임할 역할 (manager, recruiter 등)
*/
public function delegateRole(User $fromUser, User $toUser, string $roleName): bool
{
@@ -208,7 +208,7 @@ public function delegateRole(User $fromUser, User $toUser, string $roleName): bo
->where('name', $roleName)
->first();
- if (!$role) {
+ if (! $role) {
throw new \InvalidArgumentException("역할을 찾을 수 없습니다: {$roleName}");
}
@@ -218,7 +218,7 @@ public function delegateRole(User $fromUser, User $toUser, string $roleName): bo
->where('role_id', $role->id)
->exists();
- if (!$hasRole) {
+ if (! $hasRole) {
throw new \InvalidArgumentException("{$fromUser->name}님이 {$roleName} 역할을 보유하고 있지 않습니다.");
}
@@ -252,7 +252,7 @@ public function assignRole(User $user, string $roleName): bool
->where('name', $roleName)
->first();
- if (!$role) {
+ if (! $role) {
return false;
}
@@ -278,7 +278,7 @@ public function removeRole(User $user, string $roleName): bool
->where('name', $roleName)
->first();
- if (!$role) {
+ if (! $role) {
return false;
}
@@ -338,7 +338,7 @@ public function syncRoles(User $user, int $tenantId, array $roleIds): void
// 제거할 역할 soft delete (새 역할 목록에 없는 것들)
$roleIdsToRemove = array_diff($salesRoleIds, $roleIds);
- if (!empty($roleIdsToRemove)) {
+ if (! empty($roleIdsToRemove)) {
UserRole::where('user_id', $user->id)
->where('tenant_id', $tenantId)
->whereIn('role_id', $roleIdsToRemove)
@@ -379,7 +379,7 @@ public function uploadDocuments(User $user, int $tenantId, array $documents): ar
$uploaded = [];
foreach ($documents as $doc) {
- if (!isset($doc['file']) || !$doc['file'] instanceof UploadedFile) {
+ if (! isset($doc['file']) || ! $doc['file'] instanceof UploadedFile) {
continue;
}
@@ -388,7 +388,7 @@ public function uploadDocuments(User $user, int $tenantId, array $documents): ar
$description = $doc['description'] ?? null;
// 파일 저장
- $storedName = Str::uuid() . '.' . $file->getClientOriginalExtension();
+ $storedName = Str::uuid().'.'.$file->getClientOriginalExtension();
$filePath = "sales-partners/{$user->id}/{$storedName}";
Storage::disk('tenant')->put($filePath, file_get_contents($file));
@@ -448,7 +448,7 @@ public function getSalesPartners(array $filters = [])
->with(['parent', 'userRoles.role', 'salesDocuments', 'salesPartner']);
// 검색
- if (!empty($filters['search'])) {
+ if (! empty($filters['search'])) {
$search = $filters['search'];
$query->where(function ($q) use ($search) {
$q->where('name', 'like', "%{$search}%")
@@ -459,7 +459,7 @@ public function getSalesPartners(array $filters = [])
}
// 역할 필터
- if (!empty($filters['role'])) {
+ if (! empty($filters['role'])) {
$roleName = $filters['role'];
$query->whereHas('userRoles', function ($q) use ($tenantId, $roleName) {
$q->where('tenant_id', $tenantId)
@@ -470,7 +470,7 @@ public function getSalesPartners(array $filters = [])
}
// 승인 상태 필터
- if (!empty($filters['approval_status'])) {
+ if (! empty($filters['approval_status'])) {
$query->where('approval_status', $filters['approval_status']);
}
@@ -480,7 +480,7 @@ public function getSalesPartners(array $filters = [])
}
// 유치자(추천인) 필터 - 현재 로그인한 사용자가 유치한 파트너만
- if (!empty($filters['parent_id'])) {
+ if (! empty($filters['parent_id'])) {
$query->where('parent_id', $filters['parent_id']);
}
@@ -562,10 +562,10 @@ public function getStats(?int $parentId = null): array
'pending' => (clone $baseQuery)->where('approval_status', 'pending')->count(),
'approved' => (clone $baseQuery)->where('approval_status', 'approved')->count(),
'sales' => (clone $baseQuery)
- ->whereHas('userRoles.role', fn($q) => $q->where('name', 'sales'))
+ ->whereHas('userRoles.role', fn ($q) => $q->where('name', 'sales'))
->count(),
'manager' => (clone $baseQuery)
- ->whereHas('userRoles.role', fn($q) => $q->where('name', 'manager'))
+ ->whereHas('userRoles.role', fn ($q) => $q->where('name', 'manager'))
->count(),
];
}
@@ -626,6 +626,7 @@ public function getAllDescendants(User $user, int $maxDepth = 10): array
{
$descendants = [];
$this->collectDescendants($user, $descendants, 1, $maxDepth);
+
return $descendants;
}
diff --git a/app/Services/Sales/TenantProspectService.php b/app/Services/Sales/TenantProspectService.php
index a4a0c021..59abc8ec 100644
--- a/app/Services/Sales/TenantProspectService.php
+++ b/app/Services/Sales/TenantProspectService.php
@@ -104,7 +104,7 @@ public function convertToTenant(TenantProspect $prospect, int $convertedBy): Ten
{
return DB::transaction(function () use ($prospect, $convertedBy) {
// 고유 테넌트 코드 생성 (T + 타임스탬프 + 랜덤)
- $tenantCode = 'T' . now()->format('ymd') . strtoupper(substr(uniqid(), -4));
+ $tenantCode = 'T'.now()->format('ymd').strtoupper(substr(uniqid(), -4));
// 테넌트 생성
$tenant = Tenant::create([
@@ -208,7 +208,7 @@ public function getProspects(array $filters = [])
$query = TenantProspect::with(['registeredBy', 'tenant']);
// 검색
- if (!empty($filters['search'])) {
+ if (! empty($filters['search'])) {
$search = $filters['search'];
$query->where(function ($q) use ($search) {
$q->where('company_name', 'like', "%{$search}%")
@@ -219,7 +219,7 @@ public function getProspects(array $filters = [])
}
// 상태 필터
- if (!empty($filters['status'])) {
+ if (! empty($filters['status'])) {
if ($filters['status'] === 'active') {
$query->active();
} elseif ($filters['status'] === 'expired') {
@@ -230,7 +230,7 @@ public function getProspects(array $filters = [])
}
// 특정 영업파트너
- if (!empty($filters['registered_by'])) {
+ if (! empty($filters['registered_by'])) {
$query->byPartner($filters['registered_by']);
}
@@ -261,7 +261,7 @@ public function getStats(?int $partnerId = null): array
*/
private function uploadAttachment(UploadedFile $file, int $userId): string
{
- $storedName = Str::uuid() . '.' . $file->getClientOriginalExtension();
+ $storedName = Str::uuid().'.'.$file->getClientOriginalExtension();
$filePath = "prospects/{$userId}/{$storedName}";
Storage::disk('tenant')->put($filePath, file_get_contents($file));
@@ -295,7 +295,7 @@ private function saveBase64Image(string $base64Data, int $userId): ?string
return null;
}
- $storedName = Str::uuid() . '.' . $extension;
+ $storedName = Str::uuid().'.'.$extension;
$filePath = "prospects/{$userId}/{$storedName}";
Storage::disk('tenant')->put($filePath, $imageData);
@@ -316,9 +316,9 @@ public function deleteBusinessCard(TenantProspect $prospect): bool
*/
public function deleteAttachment(TenantProspect $prospect, string $type): bool
{
- $pathField = $type . '_path';
+ $pathField = $type.'_path';
- if (!$prospect->$pathField) {
+ if (! $prospect->$pathField) {
return false;
}
@@ -327,6 +327,7 @@ public function deleteAttachment(TenantProspect $prospect, string $type): bool
}
$prospect->update([$pathField => null]);
+
return true;
}
}
diff --git a/app/Services/SalesCommissionService.php b/app/Services/SalesCommissionService.php
index 861a3fef..b1f8a16f 100644
--- a/app/Services/SalesCommissionService.php
+++ b/app/Services/SalesCommissionService.php
@@ -4,7 +4,6 @@
use App\Models\Sales\SalesCommission;
use App\Models\Sales\SalesCommissionDetail;
-use App\Models\Sales\SalesContractProduct;
use App\Models\Sales\SalesPartner;
use App\Models\Sales\SalesTenantManagement;
use Carbon\Carbon;
@@ -18,8 +17,11 @@ class SalesCommissionService
* 기본 수당률
*/
const DEFAULT_PARTNER_RATE = 20.00;
+
const DEFAULT_GROUP_RATE = 30.00; // 단체 파트너 수당률
+
const DEFAULT_INDIVIDUAL_REFERRER_RATE = 5.00; // 개인 유치수당률
+
const DEFAULT_GROUP_REFERRER_RATE = 3.00; // 단체 유치수당률
// =========================================================================
@@ -42,44 +44,44 @@ public function getCommissions(array $filters = [], int $perPage = 20): LengthAw
]);
// 상태 필터
- if (!empty($filters['status'])) {
+ if (! empty($filters['status'])) {
$query->where('status', $filters['status']);
}
// 입금구분 필터
- if (!empty($filters['payment_type'])) {
+ if (! empty($filters['payment_type'])) {
$query->where('payment_type', $filters['payment_type']);
}
// 영업파트너 필터
- if (!empty($filters['partner_id'])) {
+ if (! empty($filters['partner_id'])) {
$query->where('partner_id', $filters['partner_id']);
}
// 매니저 필터
- if (!empty($filters['manager_user_id'])) {
+ if (! empty($filters['manager_user_id'])) {
$query->where('manager_user_id', $filters['manager_user_id']);
}
// 지급예정 기간 범위 필터
- if (!empty($filters['scheduled_start_year']) && !empty($filters['scheduled_start_month'])
- && !empty($filters['scheduled_end_year']) && !empty($filters['scheduled_end_month'])) {
+ if (! empty($filters['scheduled_start_year']) && ! empty($filters['scheduled_start_month'])
+ && ! empty($filters['scheduled_end_year']) && ! empty($filters['scheduled_end_month'])) {
$startDate = \Carbon\Carbon::create($filters['scheduled_start_year'], $filters['scheduled_start_month'], 1)->startOfMonth();
$endDate = \Carbon\Carbon::create($filters['scheduled_end_year'], $filters['scheduled_end_month'], 1)->endOfMonth();
$query->whereBetween('scheduled_payment_date', [$startDate, $endDate]);
}
// 지급예정 년/월 필터 (단일)
- elseif (!empty($filters['scheduled_year']) && !empty($filters['scheduled_month'])) {
+ elseif (! empty($filters['scheduled_year']) && ! empty($filters['scheduled_month'])) {
$query->forScheduledMonth((int) $filters['scheduled_year'], (int) $filters['scheduled_month']);
}
// 입금일 기간 필터
- if (!empty($filters['payment_start_date']) && !empty($filters['payment_end_date'])) {
+ if (! empty($filters['payment_start_date']) && ! empty($filters['payment_end_date'])) {
$query->paymentDateBetween($filters['payment_start_date'], $filters['payment_end_date']);
}
// 수당유형 필터
- if (!empty($filters['commission_type'])) {
+ if (! empty($filters['commission_type'])) {
$commissionType = $filters['commission_type'];
if ($commissionType === 'partner') {
$query->where('partner_commission', '>', 0);
@@ -92,7 +94,7 @@ public function getCommissions(array $filters = [], int $perPage = 20): LengthAw
}
// 고객사 검색 (management → tenant 또는 tenantProspect)
- if (!empty($filters['search'])) {
+ if (! empty($filters['search'])) {
$search = $filters['search'];
$query->whereHas('management', function ($q) use ($search) {
$q->where(function ($sub) use ($search) {
@@ -144,10 +146,10 @@ public function createCommission(int $managementId, string $paymentType, float $
// 영업파트너 resolve (fallback: tenantProspect → registeredBy → salesPartner)
$partner = $management->salesPartner;
- if (!$partner) {
+ if (! $partner) {
$partner = $management->tenantProspect?->registeredBy?->salesPartner;
}
- if (!$partner) {
+ if (! $partner) {
throw new \Exception('영업파트너가 지정되지 않았습니다.');
}
@@ -271,7 +273,7 @@ public function approve(int $commissionId, int $approverId): SalesCommission
$this->recalculateCommission($commission);
}
- if (!$commission->approve($approverId)) {
+ if (! $commission->approve($approverId)) {
throw new \Exception('승인할 수 없는 상태입니다.');
}
@@ -311,7 +313,7 @@ public function markAsPaid(int $commissionId, ?string $bankReference = null): Sa
{
$commission = SalesCommission::findOrFail($commissionId);
- if (!$commission->markAsPaid($bankReference)) {
+ if (! $commission->markAsPaid($bankReference)) {
throw new \Exception('지급완료 처리할 수 없는 상태입니다.');
}
@@ -357,7 +359,7 @@ public function unapprove(int $commissionId): SalesCommission
{
$commission = SalesCommission::findOrFail($commissionId);
- if (!$commission->unapprove()) {
+ if (! $commission->unapprove()) {
throw new \Exception('승인취소할 수 없는 상태입니다.');
}
@@ -371,7 +373,7 @@ public function cancel(int $commissionId): SalesCommission
{
$commission = SalesCommission::findOrFail($commissionId);
- if (!$commission->cancel()) {
+ if (! $commission->cancel()) {
throw new \Exception('취소할 수 없는 상태입니다.');
}
@@ -401,7 +403,7 @@ public function getPartnerCommissionSummary(int $partnerId): array
// 이번 달 지급예정 (승인 완료된 건)
'scheduled_this_month' => $commissions
->where('status', SalesCommission::STATUS_APPROVED)
- ->filter(fn($c) => $c->scheduled_payment_date->format('Y-m') === $thisMonth)
+ ->filter(fn ($c) => $c->scheduled_payment_date->format('Y-m') === $thisMonth)
->sum('partner_commission'),
// 누적 수령 수당
@@ -416,7 +418,7 @@ public function getPartnerCommissionSummary(int $partnerId): array
// 이번 달 신규 계약 건수
'contracts_this_month' => $commissions
- ->filter(fn($c) => $c->payment_date >= $thisMonthStart && $c->payment_date <= $thisMonthEnd)
+ ->filter(fn ($c) => $c->payment_date >= $thisMonthStart && $c->payment_date <= $thisMonthEnd)
->count(),
// 1차 수당 상세
@@ -485,7 +487,7 @@ public function getManagerCommissionSummary(int $managerUserId): array
// 이번 달 지급예정 (승인 완료된 건)
'scheduled_this_month' => $commissions
->where('status', SalesCommission::STATUS_APPROVED)
- ->filter(fn($c) => $c->scheduled_payment_date->format('Y-m') === $thisMonth)
+ ->filter(fn ($c) => $c->scheduled_payment_date->format('Y-m') === $thisMonth)
->sum('manager_commission'),
// 누적 수령 수당
@@ -616,16 +618,16 @@ private function recalculateCommission(SalesCommission $commission): void
'tenantProspect.registeredBy.salesPartner',
])->find($commission->management_id);
- if (!$management) {
+ if (! $management) {
return;
}
// 파트너 resolve (fallback: tenantProspect → registeredBy → salesPartner)
$partner = $management->salesPartner;
- if (!$partner) {
+ if (! $partner) {
$partner = $management->tenantProspect?->registeredBy?->salesPartner;
}
- if (!$partner) {
+ if (! $partner) {
return;
}
diff --git a/app/Services/SidebarMenuService.php b/app/Services/SidebarMenuService.php
index 58f202d6..8c7362f0 100644
--- a/app/Services/SidebarMenuService.php
+++ b/app/Services/SidebarMenuService.php
@@ -180,8 +180,8 @@ public function isMenuActive(Menu $menu): bool
// prefix 매칭: 더 구체적인 메뉴가 있으면 덜 구체적인 prefix 매칭 비활성화
// (예: /esign/templates/5/fields 접속 시, /esign/templates 메뉴만 활성화, /esign 메뉴는 비활성)
if (str_starts_with($currentPath, $menu->url.'/')) {
- return !self::hasExactMenuMatch($currentPath)
- && !self::hasMoreSpecificPrefixMenu($currentPath, $menu->url);
+ return ! self::hasExactMenuMatch($currentPath)
+ && ! self::hasMoreSpecificPrefixMenu($currentPath, $menu->url);
}
return false;
@@ -275,7 +275,7 @@ private static function hasExactMenuMatch(string $currentPath): bool
private static function hasMoreSpecificPrefixMenu(string $currentPath, string $menuUrl): bool
{
- $cacheKey = $currentPath . '|' . $menuUrl;
+ $cacheKey = $currentPath.'|'.$menuUrl;
if (isset(self::$prefixMenuCache[$cacheKey])) {
return self::$prefixMenuCache[$cacheKey];
}
@@ -293,6 +293,7 @@ private static function hasMoreSpecificPrefixMenu(string $currentPath, string $m
->exists();
self::$prefixMenuCache[$cacheKey] = $result;
+
return $result;
}
diff --git a/app/Services/TradingPartnerOcrService.php b/app/Services/TradingPartnerOcrService.php
index ba25f4ed..2d424265 100644
--- a/app/Services/TradingPartnerOcrService.php
+++ b/app/Services/TradingPartnerOcrService.php
@@ -37,19 +37,19 @@ private function callVertexAiApi(AiConfig $config, string $base64Image): array
$projectId = $config->getProjectId();
$region = $config->getRegion();
- if (!$projectId) {
+ if (! $projectId) {
throw new \RuntimeException('Vertex AI 프로젝트 ID가 설정되지 않았습니다.');
}
$accessToken = $this->getAccessToken($config);
- if (!$accessToken) {
+ if (! $accessToken) {
throw new \RuntimeException('Google Cloud 인증 실패');
}
$url = "https://{$region}-aiplatform.googleapis.com/v1/projects/{$projectId}/locations/{$region}/publishers/google/models/{$model}:generateContent";
return $this->callGeminiApi($url, $base64Image, [
- 'Authorization' => 'Bearer ' . $accessToken,
+ 'Authorization' => 'Bearer '.$accessToken,
'Content-Type' => 'application/json',
], true);
}
@@ -122,7 +122,7 @@ private function callGeminiApi(string $url, string $base64Image, array $headers,
'status' => $response->status(),
'body' => $response->body(),
]);
- throw new \RuntimeException('AI API 호출 실패: ' . $response->status());
+ throw new \RuntimeException('AI API 호출 실패: '.$response->status());
}
$result = $response->json();
@@ -169,14 +169,16 @@ private function getAccessToken(AiConfig $config): ?string
}
}
- if (!$serviceAccountPath) {
+ if (! $serviceAccountPath) {
Log::error('Service account file not found', ['tried_paths' => $possiblePaths]);
+
return null;
}
$serviceAccount = json_decode(file_get_contents($serviceAccountPath), true);
- if (!$serviceAccount) {
+ if (! $serviceAccount) {
Log::error('Service account JSON parse failed');
+
return null;
}
@@ -191,13 +193,14 @@ private function getAccessToken(AiConfig $config): ?string
]));
$privateKey = openssl_pkey_get_private($serviceAccount['private_key']);
- if (!$privateKey) {
+ if (! $privateKey) {
Log::error('Failed to load private key');
+
return null;
}
- openssl_sign($jwtHeader . '.' . $jwtClaim, $signature, $privateKey, OPENSSL_ALGO_SHA256);
- $jwt = $jwtHeader . '.' . $jwtClaim . '.' . $this->base64UrlEncode($signature);
+ openssl_sign($jwtHeader.'.'.$jwtClaim, $signature, $privateKey, OPENSSL_ALGO_SHA256);
+ $jwt = $jwtHeader.'.'.$jwtClaim.'.'.$this->base64UrlEncode($signature);
try {
$response = Http::asForm()->post('https://oauth2.googleapis.com/token', [
@@ -207,6 +210,7 @@ private function getAccessToken(AiConfig $config): ?string
if ($response->successful()) {
$data = $response->json();
+
return $data['access_token'] ?? null;
}
@@ -214,9 +218,11 @@ private function getAccessToken(AiConfig $config): ?string
'status' => $response->status(),
'body' => $response->body(),
]);
+
return null;
} catch (\Exception $e) {
Log::error('OAuth token request exception', ['error' => $e->getMessage()]);
+
return null;
}
}
@@ -234,7 +240,7 @@ private function base64UrlEncode(string $data): string
*/
private function buildPrompt(): string
{
- return <<cnt;
+ ', [$dbName, $table])->cnt;
$tableTriggers = $triggers->where('EVENT_OBJECT_TABLE', $table);
@@ -205,8 +205,8 @@ private function createTriggersForTable(string $dbName, string $table): void
return;
}
- $newJson = 'JSON_OBJECT(' . collect($cols)->map(fn ($c) => "'{$c}', NEW.`{$c}`")->implode(', ') . ')';
- $oldJson = 'JSON_OBJECT(' . collect($cols)->map(fn ($c) => "'{$c}', OLD.`{$c}`")->implode(', ') . ')';
+ $newJson = 'JSON_OBJECT('.collect($cols)->map(fn ($c) => "'{$c}', NEW.`{$c}`")->implode(', ').')';
+ $oldJson = 'JSON_OBJECT('.collect($cols)->map(fn ($c) => "'{$c}', OLD.`{$c}`")->implode(', ').')';
$changedCols = collect($cols)->map(fn ($c) => "IF(NOT (NEW.`{$c}` <=> OLD.`{$c}`), '{$c}', NULL)")->implode(', ');
$changeCheck = collect($cols)->map(fn ($c) => "NOT (NEW.`{$c}` <=> OLD.`{$c}`)")->implode(' OR ');
diff --git a/app/Services/Video/BgmService.php b/app/Services/Video/BgmService.php
index c9f6de5d..9c3c49c6 100644
--- a/app/Services/Video/BgmService.php
+++ b/app/Services/Video/BgmService.php
@@ -264,14 +264,14 @@ public function generateAmbient(string $mood, int $durationSec, string $savePath
foreach ($chords as $i => $freq) {
$vol = 0.06 - ($i * 0.01); // 각 음의 볼륨을 점차 줄여 자연스럽게
$modFreq = 0.08 + ($i * 0.03); // 각 음의 떨림 속도를 다르게
- $expr .= ($expr ? ' + ' : '') . "{$vol}*sin({$freq}*2*PI*t)*((0.5+0.5*sin({$modFreq}*2*PI*t)))";
+ $expr .= ($expr ? ' + ' : '')."{$vol}*sin({$freq}*2*PI*t)*((0.5+0.5*sin({$modFreq}*2*PI*t)))";
}
// 페이드인(3초) + 페이드아웃(3초) 추가
$cmd = sprintf(
'ffmpeg -y -f lavfi -i "aevalsrc=%s:s=44100:d=%d" '
- . '-af "lowpass=f=1500,highpass=f=80,afade=t=in:d=3,afade=t=out:st=%d:d=3" '
- . '-c:a libmp3lame -q:a 4 %s 2>&1',
+ .'-af "lowpass=f=1500,highpass=f=80,afade=t=in:d=3,afade=t=out:st=%d:d=3" '
+ .'-c:a libmp3lame -q:a 4 %s 2>&1',
escapeshellarg($expr),
$durationSec + 2, // 페이드아웃 여유분
max(0, $durationSec - 2),
diff --git a/app/Services/Video/GeminiScriptService.php b/app/Services/Video/GeminiScriptService.php
index b7975e67..ab79d639 100644
--- a/app/Services/Video/GeminiScriptService.php
+++ b/app/Services/Video/GeminiScriptService.php
@@ -31,7 +31,7 @@ public function filterHealthTrending(array $trendingKeywords): array
$keywordList = collect($trendingKeywords)->map(function ($item, $i) {
$news = ! empty($item['news_title']) ? " (뉴스: {$item['news_title']})" : '';
- return ($i + 1) . ". {$item['keyword']}{$news}";
+ return ($i + 1).". {$item['keyword']}{$news}";
})->implode("\n");
$prompt = <<take(10)->map(function ($item, $i) {
$news = ! empty($item['news_title']) ? " (뉴스: {$item['news_title']})" : '';
- return ($i + 1) . ". {$item['keyword']}{$news}";
+ return ($i + 1).". {$item['keyword']}{$news}";
})->implode("\n");
$prompt = << '...'], ['inlineData' => ['mimeType' => '...', 'data' => '...']]]
+ * @param array $parts [['text' => '...'], ['inlineData' => ['mimeType' => '...', 'data' => '...']]]
*/
public function callGeminiWithParts(array $parts, float $temperature = 0.9, int $maxTokens = 4096): ?string
{
diff --git a/app/Services/Video/SlideAnnotationService.php b/app/Services/Video/SlideAnnotationService.php
index 56ed8ecf..c2562d50 100644
--- a/app/Services/Video/SlideAnnotationService.php
+++ b/app/Services/Video/SlideAnnotationService.php
@@ -7,8 +7,11 @@
class SlideAnnotationService
{
private const TARGET_WIDTH = 1920;
+
private const TARGET_HEIGHT = 1080;
+
private const CAPTION_HEIGHT = 180;
+
private const MARKER_RADIUS = 35;
private string $fontPath;
@@ -25,11 +28,11 @@ public function __construct()
/**
* 스크린샷 위에 시각적 어노테이션 추가
*
- * @param string $imagePath 원본 스크린샷 경로
- * @param array $uiElements UI 요소 배열 [{type, label, x, y, description}]
- * @param int $stepNumber 현재 스텝 번호
- * @param string $caption 하단 캡션 텍스트
- * @param string $outputPath 출력 파일 경로
+ * @param string $imagePath 원본 스크린샷 경로
+ * @param array $uiElements UI 요소 배열 [{type, label, x, y, description}]
+ * @param int $stepNumber 현재 스텝 번호
+ * @param string $caption 하단 캡션 텍스트
+ * @param string $outputPath 출력 파일 경로
* @return string|null 성공 시 출력 경로
*/
public function annotateSlide(
@@ -41,6 +44,7 @@ public function annotateSlide(
): ?string {
if (! file_exists($imagePath)) {
Log::error("SlideAnnotation: 원본 이미지 없음 - {$imagePath}");
+
return null;
}
@@ -94,11 +98,12 @@ public function annotateSlide(
imagepng($canvas, $outputPath, 6);
imagedestroy($canvas);
- Log::info("SlideAnnotation: 슬라이드 생성 완료", ['output' => $outputPath]);
+ Log::info('SlideAnnotation: 슬라이드 생성 완료', ['output' => $outputPath]);
return $outputPath;
} catch (\Exception $e) {
- Log::error("SlideAnnotation: 예외 발생", ['error' => $e->getMessage()]);
+ Log::error('SlideAnnotation: 예외 발생', ['error' => $e->getMessage()]);
+
return null;
}
}
@@ -240,6 +245,7 @@ public function annotateSlideWithSpotlight(
): ?string {
if (! file_exists($imagePath)) {
Log::error("SlideAnnotation: 원본 이미지 없음 - {$imagePath}");
+
return null;
}
@@ -353,11 +359,12 @@ public function annotateSlideWithSpotlight(
imagepng($canvas, $outputPath, 6);
imagedestroy($canvas);
- Log::info("SlideAnnotation: 스포트라이트 슬라이드 생성 완료", ['output' => $outputPath]);
+ Log::info('SlideAnnotation: 스포트라이트 슬라이드 생성 완료', ['output' => $outputPath]);
return $outputPath;
} catch (\Exception $e) {
- Log::error("SlideAnnotation: 스포트라이트 예외 발생", ['error' => $e->getMessage()]);
+ Log::error('SlideAnnotation: 스포트라이트 예외 발생', ['error' => $e->getMessage()]);
+
return null;
}
}
@@ -418,7 +425,8 @@ public function createIntroSlide(string $title, string $outputPath): ?string
return $outputPath;
} catch (\Exception $e) {
- Log::error("SlideAnnotation: 인트로 슬라이드 생성 실패", ['error' => $e->getMessage()]);
+ Log::error('SlideAnnotation: 인트로 슬라이드 생성 실패', ['error' => $e->getMessage()]);
+
return null;
}
}
@@ -474,7 +482,8 @@ public function createOutroSlide(string $title, string $outputPath): ?string
return $outputPath;
} catch (\Exception $e) {
- Log::error("SlideAnnotation: 아웃트로 슬라이드 생성 실패", ['error' => $e->getMessage()]);
+ Log::error('SlideAnnotation: 아웃트로 슬라이드 생성 실패', ['error' => $e->getMessage()]);
+
return null;
}
}
@@ -540,6 +549,7 @@ private function loadImage(string $path): ?\GdImage
$info = getimagesize($path);
if (! $info) {
Log::error("SlideAnnotation: 이미지 정보를 읽을 수 없음 - {$path}");
+
return null;
}
@@ -566,7 +576,7 @@ private function wrapText(string $text, int $maxChars): string
$currentLine = '';
foreach ($words as $word) {
- if (mb_strlen($currentLine . $word) > $maxChars && $currentLine !== '') {
+ if (mb_strlen($currentLine.$word) > $maxChars && $currentLine !== '') {
$lines[] = trim($currentLine);
$currentLine = $word;
} else {
diff --git a/app/Services/Video/TutorialAssemblyService.php b/app/Services/Video/TutorialAssemblyService.php
index 6ced1dc2..0c63b48f 100644
--- a/app/Services/Video/TutorialAssemblyService.php
+++ b/app/Services/Video/TutorialAssemblyService.php
@@ -16,12 +16,12 @@ public function __construct(VideoAssemblyService $videoAssembly)
/**
* 어노테이션 이미지들 → MP4 영상 합성
*
- * @param array $slidePaths 슬라이드 이미지 경로 배열
- * @param array $durations 각 슬라이드 표시 시간(초) 배열
- * @param string|null $narrationPath 나레이션 오디오 경로
- * @param string|null $bgmPath BGM 오디오 경로
- * @param string $subtitlePath ASS 자막 파일 경로
- * @param string $outputPath 최종 MP4 출력 경로
+ * @param array $slidePaths 슬라이드 이미지 경로 배열
+ * @param array $durations 각 슬라이드 표시 시간(초) 배열
+ * @param string|null $narrationPath 나레이션 오디오 경로
+ * @param string|null $bgmPath BGM 오디오 경로
+ * @param string $subtitlePath ASS 자막 파일 경로
+ * @param string $outputPath 최종 MP4 출력 경로
* @return string|null 성공 시 출력 경로
*/
public function assembleFromImages(
@@ -34,6 +34,7 @@ public function assembleFromImages(
): ?string {
if (empty($slidePaths)) {
Log::error('TutorialAssembly: 슬라이드가 없습니다');
+
return null;
}
@@ -48,6 +49,7 @@ public function assembleFromImages(
if (! $silentVideo) {
Log::error('TutorialAssembly: 이미지→영상 변환 실패');
+
return null;
}
@@ -93,6 +95,7 @@ private function imagesToVideo(array $slidePaths, array $durations, string $outp
Log::error('TutorialAssembly: 단일 이미지 변환 실패', [
'output' => implode("\n", array_slice($output, -10)),
]);
+
return null;
}
@@ -122,6 +125,7 @@ private function imagesToVideo(array $slidePaths, array $durations, string $outp
Log::error("TutorialAssembly: 클립 {$i} 변환 실패", [
'output' => implode("\n", array_slice($output, -10)),
]);
+
// 실패 시 crossfade 없이 fallback
return $this->imagesToVideoSimple($slidePaths, $durations, $outputPath);
}
@@ -169,6 +173,7 @@ private function xfadeConcat(array $clipPaths, array $durations, float $fadeDura
Log::warning('TutorialAssembly: xfade 실패, concat fallback', [
'output' => implode("\n", array_slice($output, -10)),
]);
+
return $this->simpleConcatClips($clipPaths, $outputPath);
}
@@ -178,7 +183,7 @@ private function xfadeConcat(array $clipPaths, array $durations, float $fadeDura
// 3개 이상: 체인 xfade
$inputs = '';
foreach ($clipPaths as $path) {
- $inputs .= '-i ' . escapeshellarg($path) . ' ';
+ $inputs .= '-i '.escapeshellarg($path).' ';
}
$filter = '';
@@ -188,8 +193,8 @@ private function xfadeConcat(array $clipPaths, array $durations, float $fadeDura
$cumulativeOffset += ($durations[$i] ?? 8) - $fadeDuration;
$inputA = ($i === 0) ? '[0:v]' : "[v{$i}]";
- $inputB = '[' . ($i + 1) . ':v]';
- $outputLabel = ($i === $count - 2) ? '[v]' : "[v" . ($i + 1) . "]";
+ $inputB = '['.($i + 1).':v]';
+ $outputLabel = ($i === $count - 2) ? '[v]' : '[v'.($i + 1).']';
$filter .= "{$inputA}{$inputB}xfade=transition=fade:duration={$fadeDuration}:offset={$cumulativeOffset}{$outputLabel}";
@@ -211,6 +216,7 @@ private function xfadeConcat(array $clipPaths, array $durations, float $fadeDura
Log::warning('TutorialAssembly: 체인 xfade 실패, concat fallback', [
'output' => implode("\n", array_slice($output, -10)),
]);
+
return $this->simpleConcatClips($clipPaths, $outputPath);
}
@@ -227,7 +233,7 @@ private function simpleConcatClips(array $clipPaths, string $outputPath): ?strin
$listContent = '';
foreach ($clipPaths as $path) {
- $listContent .= "file " . escapeshellarg($path) . "\n";
+ $listContent .= 'file '.escapeshellarg($path)."\n";
}
file_put_contents($listFile, $listContent);
@@ -245,6 +251,7 @@ private function simpleConcatClips(array $clipPaths, string $outputPath): ?strin
Log::error('TutorialAssembly: concat fallback도 실패', [
'output' => implode("\n", array_slice($output, -10)),
]);
+
return null;
}
diff --git a/app/Services/Video/VeoVideoService.php b/app/Services/Video/VeoVideoService.php
index 56fac0a9..4c59527f 100644
--- a/app/Services/Video/VeoVideoService.php
+++ b/app/Services/Video/VeoVideoService.php
@@ -40,7 +40,7 @@ public function generateClip(string $prompt, int $duration = 8): ?array
// 한국인 여성 등장인물 프롬프트 프리픽스 추가
$characterPrefix = 'Featuring a young Korean woman in her 20s with natural black hair. ';
- $fullPrompt = $characterPrefix . $prompt;
+ $fullPrompt = $characterPrefix.$prompt;
$response = Http::withToken($token)
->timeout(60)
@@ -118,7 +118,7 @@ public function checkOperation(string $operationName): array
'body' => substr($response->body(), 0, 500),
]);
- return ['done' => false, 'video' => null, 'error' => 'HTTP ' . $response->status()];
+ return ['done' => false, 'video' => null, 'error' => 'HTTP '.$response->status()];
}
$data = $response->json();
@@ -195,7 +195,7 @@ public function waitAndSave(string $operationName, string $savePath, int $maxAtt
'operationName' => $operationName,
]);
- return ['path' => null, 'error' => '연속 폴링 실패: ' . $result['error']];
+ return ['path' => null, 'error' => '연속 폴링 실패: '.$result['error']];
}
continue;
@@ -227,7 +227,7 @@ public function waitAndSave(string $operationName, string $savePath, int $maxAtt
if (($i + 1) % 3 === 0) {
Log::info('VeoVideoService: 영상 생성 대기 중', [
'attempt' => $i + 1,
- 'elapsed' => ($i + 1) * 10 . '초',
+ 'elapsed' => ($i + 1) * 10 .'초',
]);
}
}
@@ -237,6 +237,6 @@ public function waitAndSave(string $operationName, string $savePath, int $maxAtt
'attempts' => $maxAttempts,
]);
- return ['path' => null, 'error' => '타임아웃 (' . ($maxAttempts * 10) . '초)'];
+ return ['path' => null, 'error' => '타임아웃 ('.($maxAttempts * 10).'초)'];
}
}
diff --git a/app/Services/Video/VideoAssemblyService.php b/app/Services/Video/VideoAssemblyService.php
index 244e7c34..267b0219 100644
--- a/app/Services/Video/VideoAssemblyService.php
+++ b/app/Services/Video/VideoAssemblyService.php
@@ -35,7 +35,7 @@ public function concatClips(array $clipPaths, string $outputPath): ?string
$listContent = '';
foreach ($clipPaths as $path) {
- $listContent .= "file " . escapeshellarg($path) . "\n";
+ $listContent .= 'file '.escapeshellarg($path)."\n";
}
file_put_contents($listFile, $listContent);
@@ -67,7 +67,7 @@ public function concatClips(array $clipPaths, string $outputPath): ?string
$scaledListFile = "{$dir}/scaled_list.txt";
$scaledListContent = '';
foreach ($scaledPaths as $path) {
- $scaledListContent .= "file " . escapeshellarg($path) . "\n";
+ $scaledListContent .= 'file '.escapeshellarg($path)."\n";
}
file_put_contents($scaledListFile, $scaledListContent);
@@ -151,7 +151,7 @@ public function concatNarrations(array $audioPaths, array $scenes, string $outpu
$listFile = "{$dir}/narration_list.txt";
$listContent = '';
foreach ($paddedPaths as $path) {
- $listContent .= "file " . escapeshellarg($path) . "\n";
+ $listContent .= 'file '.escapeshellarg($path)."\n";
}
file_put_contents($listFile, $listContent);
@@ -209,7 +209,7 @@ public function getAudioDuration(string $path): float
* @param array $narrationDurations [scene_number => 실제 오디오 초] (ffprobe 측정값)
*/
/**
- * @param string $layout 'portrait' (9:16 Shorts) 또는 'landscape' (16:9 튜토리얼)
+ * @param string $layout 'portrait' (9:16 Shorts) 또는 'landscape' (16:9 튜토리얼)
*/
public function generateAssSubtitle(array $scenes, string $outputPath, array $narrationDurations = [], string $layout = 'portrait'): string
{
@@ -306,7 +306,7 @@ public function generateAssSubtitle(array $scenes, string $outputPath, array $na
$endTime = $this->formatAssTime($currentTime + $offset + $sentDuration);
$text = $this->wrapText($sentence, $maxCharsPerLine);
- $text = str_replace("\n", "\\N", $text);
+ $text = str_replace("\n", '\\N', $text);
$ass .= "Dialogue: 0,{$startTime},{$endTime},Default,,0,0,0,,{$text}\n";
@@ -379,7 +379,7 @@ private function splitIntoSentences(string $text): array
if (mb_strlen($part) < 5 && ! empty($merged)) {
// 짧은 조각 → 이전 항목 뒤에 붙임
- $merged[count($merged) - 1] .= ' ' . $part;
+ $merged[count($merged) - 1] .= ' '.$part;
} else {
$merged[] = $part;
}
@@ -403,21 +403,21 @@ public function assemble(
mkdir($dir, 0755, true);
}
- $inputs = ['-i ' . escapeshellarg($videoPath)];
+ $inputs = ['-i '.escapeshellarg($videoPath)];
$filterParts = [];
$mapParts = ['-map 0:v'];
$audioIndex = 1;
// 나레이션 추가
if ($narrationPath && file_exists($narrationPath)) {
- $inputs[] = '-i ' . escapeshellarg($narrationPath);
+ $inputs[] = '-i '.escapeshellarg($narrationPath);
$filterParts[] = "[{$audioIndex}:a]volume=2.0[nar]";
$audioIndex++;
}
// BGM 추가
if ($bgmPath && file_exists($bgmPath)) {
- $inputs[] = '-i ' . escapeshellarg($bgmPath);
+ $inputs[] = '-i '.escapeshellarg($bgmPath);
$filterParts[] = "[{$audioIndex}:a]volume=1.2[bgm]";
$audioIndex++;
}
@@ -425,35 +425,35 @@ public function assemble(
// 오디오 믹싱 필터
if (count($filterParts) === 2) {
// 나레이션 + BGM
- $filterComplex = implode(';', $filterParts) . ';[nar][bgm]amix=inputs=2:duration=first[a]';
+ $filterComplex = implode(';', $filterParts).';[nar][bgm]amix=inputs=2:duration=first[a]';
$mapParts[] = '-map "[a]"';
} elseif (count($filterParts) === 1) {
// 나레이션 또는 BGM 중 하나만
$streamName = $narrationPath ? 'nar' : 'bgm';
$filterComplex = $filterParts[0];
- $mapParts[] = '-map "[' . $streamName . ']"';
+ $mapParts[] = '-map "['.$streamName.']"';
} else {
$filterComplex = null;
}
// FFmpeg 명령 조립
- $cmd = 'ffmpeg -y ' . implode(' ', $inputs);
+ $cmd = 'ffmpeg -y '.implode(' ', $inputs);
if ($filterComplex) {
- $cmd .= ' -filter_complex "' . $filterComplex . '"';
+ $cmd .= ' -filter_complex "'.$filterComplex.'"';
}
- $cmd .= ' ' . implode(' ', $mapParts);
+ $cmd .= ' '.implode(' ', $mapParts);
// 자막 비디오 필터 (슬라이드 캡션바에 텍스트 포함 시 생략 가능)
if ($subtitlePath && file_exists($subtitlePath)) {
- $vf = sprintf("ass=%s", escapeshellarg($subtitlePath));
- $cmd .= ' -vf ' . escapeshellarg($vf);
+ $vf = sprintf('ass=%s', escapeshellarg($subtitlePath));
+ $cmd .= ' -vf '.escapeshellarg($vf);
}
$cmd .= ' -c:v libx264 -preset fast -crf 23 -r 30';
$cmd .= ' -c:a aac -b:a 192k';
$cmd .= ' -shortest';
- $cmd .= ' ' . escapeshellarg($outputPath);
+ $cmd .= ' '.escapeshellarg($outputPath);
$cmd .= ' 2>&1';
Log::info('VideoAssemblyService: 최종 합성 시작', ['cmd' => $cmd]);
@@ -504,11 +504,11 @@ private function wrapText(string $text, int $maxCharsPerLine): string
$currentLine = '';
foreach ($words as $word) {
- if (mb_strlen($currentLine . ' ' . $word) > $maxCharsPerLine && $currentLine !== '') {
+ if (mb_strlen($currentLine.' '.$word) > $maxCharsPerLine && $currentLine !== '') {
$lines[] = trim($currentLine);
$currentLine = $word;
} else {
- $currentLine .= ($currentLine ? ' ' : '') . $word;
+ $currentLine .= ($currentLine ? ' ' : '').$word;
}
}
diff --git a/config/categories.php b/config/categories.php
index 457fbb10..11b282c6 100644
--- a/config/categories.php
+++ b/config/categories.php
@@ -24,4 +24,4 @@
'process_type' => '공정 유형',
'procurement_type' => '조달 유형',
],
-];
\ No newline at end of file
+];
diff --git a/config/database.php b/config/database.php
index 6da81efc..034e1694 100644
--- a/config/database.php
+++ b/config/database.php
@@ -83,7 +83,6 @@
]) : [],
],
-
'mariadb' => [
'driver' => 'mariadb',
'url' => env('DB_URL'),
diff --git a/config/fcm.php b/config/fcm.php
index 2886ab2c..c5ea8840 100644
--- a/config/fcm.php
+++ b/config/fcm.php
@@ -38,13 +38,13 @@
|
*/
'channels' => [
- 'default' => 'push_default',
- 'vendor_register' => 'push_vendor_register',
+ 'default' => 'push_default',
+ 'vendor_register' => 'push_vendor_register',
'approval_request' => 'push_approval_request',
- 'income' => 'push_income',
- 'sales_order' => 'push_sales_order',
- 'purchase_order' => 'push_purchase_order',
- 'contract' => 'push_contract',
+ 'income' => 'push_income',
+ 'sales_order' => 'push_sales_order',
+ 'purchase_order' => 'push_purchase_order',
+ 'contract' => 'push_contract',
],
/*
diff --git a/database/seeders/AccountCodeSeeder.php b/database/seeders/AccountCodeSeeder.php
index 74e92b69..64090b08 100644
--- a/database/seeders/AccountCodeSeeder.php
+++ b/database/seeders/AccountCodeSeeder.php
@@ -2,8 +2,8 @@
namespace Database\Seeders;
-use Illuminate\Database\Seeder;
use App\Models\Barobill\AccountCode;
+use Illuminate\Database\Seeder;
/**
* 더존 표준 계정과목 시더
@@ -34,7 +34,7 @@ public function run(): void
]);
}
- $this->command->info("계정과목 " . count($accountCodes) . "개 생성 완료");
+ $this->command->info('계정과목 '.count($accountCodes).'개 생성 완료');
}
/**
diff --git a/database/seeders/AdminProspectMenuSeeder.php b/database/seeders/AdminProspectMenuSeeder.php
index d0243a69..4bd0b994 100644
--- a/database/seeders/AdminProspectMenuSeeder.php
+++ b/database/seeders/AdminProspectMenuSeeder.php
@@ -21,8 +21,9 @@ public function run(): void
->whereNull('parent_id')
->value('id');
- if (!$salesParentId) {
+ if (! $salesParentId) {
$this->command->error('영업관리 메뉴를 찾을 수 없습니다.');
+
return;
}
@@ -42,6 +43,7 @@ public function run(): void
if ($existingMenu) {
$this->command->info('영업파트너 고객관리 메뉴가 이미 존재합니다.');
+
return;
}
@@ -56,7 +58,7 @@ public function run(): void
'is_active' => true,
]);
- $this->command->info('영업파트너 고객관리 메뉴 생성 완료 (sort_order: ' . $sortOrder . ')');
+ $this->command->info('영업파트너 고객관리 메뉴 생성 완료 (sort_order: '.$sortOrder.')');
// 결과 출력
$this->command->info('');
diff --git a/database/seeders/AiTokenUsageMenuSeeder.php b/database/seeders/AiTokenUsageMenuSeeder.php
index 905c9d4c..3c851df4 100644
--- a/database/seeders/AiTokenUsageMenuSeeder.php
+++ b/database/seeders/AiTokenUsageMenuSeeder.php
@@ -46,11 +46,11 @@ public function run(): void
'parent_id' => $aiGroup->id,
'sort_order' => 1,
]);
- $this->command->info("AI 설정 메뉴를 AI 관리 그룹으로 이동 완료");
+ $this->command->info('AI 설정 메뉴를 AI 관리 그룹으로 이동 완료');
} elseif (! $aiConfig) {
- $this->command->warn("AI 설정 메뉴가 존재하지 않습니다. (건너뜀)");
+ $this->command->warn('AI 설정 메뉴가 존재하지 않습니다. (건너뜀)');
} else {
- $this->command->info("AI 설정 메뉴가 이미 AI 관리 그룹에 있습니다.");
+ $this->command->info('AI 설정 메뉴가 이미 AI 관리 그룹에 있습니다.');
}
// 3. AI 토큰 사용량 메뉴 생성 또는 이동
@@ -65,7 +65,7 @@ public function run(): void
'parent_id' => $aiGroup->id,
'sort_order' => 2,
]);
- $this->command->info("AI 토큰 사용량 메뉴를 AI 관리 그룹으로 이동 완료");
+ $this->command->info('AI 토큰 사용량 메뉴를 AI 관리 그룹으로 이동 완료');
} elseif (! $aiToken) {
Menu::withoutGlobalScopes()->create([
'tenant_id' => $tenantId,
@@ -76,9 +76,9 @@ public function run(): void
'sort_order' => 2,
'is_active' => true,
]);
- $this->command->info("AI 토큰 사용량 메뉴 생성 완료");
+ $this->command->info('AI 토큰 사용량 메뉴 생성 완료');
} else {
- $this->command->info("AI 토큰 사용량 메뉴가 이미 AI 관리 그룹에 있습니다.");
+ $this->command->info('AI 토큰 사용량 메뉴가 이미 AI 관리 그룹에 있습니다.');
}
// 4. AI 음성녹음 메뉴 생성 또는 이동
@@ -93,7 +93,7 @@ public function run(): void
'parent_id' => $aiGroup->id,
'sort_order' => 3,
]);
- $this->command->info("AI 음성녹음 메뉴를 AI 관리 그룹으로 이동 완료");
+ $this->command->info('AI 음성녹음 메뉴를 AI 관리 그룹으로 이동 완료');
} elseif (! $aiVoice) {
Menu::withoutGlobalScopes()->create([
'tenant_id' => $tenantId,
@@ -104,9 +104,9 @@ public function run(): void
'sort_order' => 3,
'is_active' => true,
]);
- $this->command->info("AI 음성녹음 메뉴 생성 완료");
+ $this->command->info('AI 음성녹음 메뉴 생성 완료');
} else {
- $this->command->info("AI 음성녹음 메뉴가 이미 AI 관리 그룹에 있습니다.");
+ $this->command->info('AI 음성녹음 메뉴가 이미 AI 관리 그룹에 있습니다.');
}
// 결과 출력
diff --git a/database/seeders/BarobillPricingPolicySeeder.php b/database/seeders/BarobillPricingPolicySeeder.php
index ff90105d..13110a56 100644
--- a/database/seeders/BarobillPricingPolicySeeder.php
+++ b/database/seeders/BarobillPricingPolicySeeder.php
@@ -2,8 +2,8 @@
namespace Database\Seeders;
-use Illuminate\Database\Seeder;
use App\Models\Barobill\BarobillPricingPolicy;
+use Illuminate\Database\Seeder;
class BarobillPricingPolicySeeder extends Seeder
{
diff --git a/database/seeders/DesignPriceSeeder.php b/database/seeders/DesignPriceSeeder.php
index ab54a32d..742ea4cc 100644
--- a/database/seeders/DesignPriceSeeder.php
+++ b/database/seeders/DesignPriceSeeder.php
@@ -63,6 +63,7 @@ protected function seedPricesFromItems(): void
if ($salesPrice <= 0) {
$skipped++;
+
continue;
}
@@ -79,7 +80,7 @@ protected function seedPricesFromItems(): void
'sales_price' => $salesPrice,
'updated_by' => 1,
]);
- $this->command->line(" 업데이트: {$item->code} => " . number_format($salesPrice));
+ $this->command->line(" 업데이트: {$item->code} => ".number_format($salesPrice));
} else {
// 새 단가 생성
Price::create([
@@ -102,10 +103,10 @@ protected function seedPricesFromItems(): void
'created_by' => 1,
]);
$created++;
- $this->command->line(" 생성: {$item->code} => " . number_format($salesPrice));
+ $this->command->line(" 생성: {$item->code} => ".number_format($salesPrice));
}
}
$this->command->info(" 생성: {$created}개, 스킵(단가없음): {$skipped}개");
}
-}
\ No newline at end of file
+}
diff --git a/database/seeders/DevelopmentApprovalMenuSeeder.php b/database/seeders/DevelopmentApprovalMenuSeeder.php
index 5343cc63..5cabe368 100644
--- a/database/seeders/DevelopmentApprovalMenuSeeder.php
+++ b/database/seeders/DevelopmentApprovalMenuSeeder.php
@@ -21,8 +21,9 @@ public function run(): void
->whereNull('parent_id')
->value('id');
- if (!$salesParentId) {
+ if (! $salesParentId) {
$this->command->error('영업관리 메뉴를 찾을 수 없습니다.');
+
return;
}
@@ -34,6 +35,7 @@ public function run(): void
if ($existingMenu) {
$this->command->info('개발 승인 메뉴가 이미 존재합니다.');
+
return;
}
diff --git a/database/seeders/FixServerMenuSeeder.php b/database/seeders/FixServerMenuSeeder.php
index 4560a0d5..8c1173af 100644
--- a/database/seeders/FixServerMenuSeeder.php
+++ b/database/seeders/FixServerMenuSeeder.php
@@ -18,8 +18,9 @@ public function run(): void
->whereNull('parent_id')
->first();
- if (!$targetGroup) {
+ if (! $targetGroup) {
$this->command->error('고객/거래처/채권관리 그룹을 찾을 수 없습니다.');
+
return;
}
@@ -41,10 +42,12 @@ public function run(): void
->where('name', $name)
->where('is_active', true)
->first();
- if ($menu) break;
+ if ($menu) {
+ break;
+ }
}
- if (!$menu) {
+ if (! $menu) {
// 이미 이동된 경우 확인
$existing = Menu::withoutGlobalScopes()
->where('tenant_id', $tenantId)
@@ -55,8 +58,9 @@ public function run(): void
if ($existing) {
$this->command->info(" 이미 이동됨: {$newName} (id: {$existing->id})");
} else {
- $this->command->warn(" 메뉴 없음: " . implode(' / ', $searchNames));
+ $this->command->warn(' 메뉴 없음: '.implode(' / ', $searchNames));
}
+
continue;
}
diff --git a/database/seeders/FundScheduleSeeder.php b/database/seeders/FundScheduleSeeder.php
index d0e98e34..15ae9035 100644
--- a/database/seeders/FundScheduleSeeder.php
+++ b/database/seeders/FundScheduleSeeder.php
@@ -155,6 +155,6 @@ public function run(): void
// 데이터 삽입
DB::table('fund_schedules')->insert($schedules);
- $this->command->info('FundScheduleSeeder 완료: 자금계획일정 ' . count($schedules) . '개 생성');
+ $this->command->info('FundScheduleSeeder 완료: 자금계획일정 '.count($schedules).'개 생성');
}
}
diff --git a/database/seeders/HolidayMenuSeeder.php b/database/seeders/HolidayMenuSeeder.php
index 0b26fac8..5c12def9 100644
--- a/database/seeders/HolidayMenuSeeder.php
+++ b/database/seeders/HolidayMenuSeeder.php
@@ -16,8 +16,9 @@ public function run(): void
->where('name', '시스템 관리')
->first();
- if (!$parentMenu) {
+ if (! $parentMenu) {
$this->command->error('시스템 관리 메뉴를 찾을 수 없습니다.');
+
return;
}
@@ -29,6 +30,7 @@ public function run(): void
if ($existingMenu) {
$this->command->info('달력 휴일 관리 메뉴가 이미 존재합니다.');
+
return;
}
diff --git a/database/seeders/InterviewMenuSeeder.php b/database/seeders/InterviewMenuSeeder.php
index c468144e..8c561960 100644
--- a/database/seeders/InterviewMenuSeeder.php
+++ b/database/seeders/InterviewMenuSeeder.php
@@ -18,6 +18,7 @@ public function run(): void
if ($salesMenus->isEmpty()) {
$this->command->error('영업관리 메뉴를 찾을 수 없습니다.');
+
return;
}
@@ -34,6 +35,7 @@ public function run(): void
if ($exists) {
$this->command->info("[{$label}] 인터뷰 시나리오 메뉴가 이미 존재합니다.");
+
continue;
}
diff --git a/database/seeders/JournalEntryMenuSeeder.php b/database/seeders/JournalEntryMenuSeeder.php
index d6a4cb44..f90f399b 100644
--- a/database/seeders/JournalEntryMenuSeeder.php
+++ b/database/seeders/JournalEntryMenuSeeder.php
@@ -17,8 +17,9 @@ public function run(): void
->where('name', '일일자금일보')
->first();
- if (!$dailyFundMenu) {
+ if (! $dailyFundMenu) {
$this->command->error('일일자금일보 메뉴를 찾을 수 없습니다.');
+
return;
}
@@ -33,6 +34,7 @@ public function run(): void
if ($existingMenu) {
$this->command->info('일반전표입력 메뉴가 이미 존재합니다.');
+
return;
}
diff --git a/database/seeders/JuilPlanningMenuSeeder.php b/database/seeders/JuilPlanningMenuSeeder.php
index 6cdad4b5..ca4f76a9 100644
--- a/database/seeders/JuilPlanningMenuSeeder.php
+++ b/database/seeders/JuilPlanningMenuSeeder.php
@@ -20,6 +20,7 @@ public function run(): void
if ($existingParent) {
$this->command->info('주일기업 기획 메뉴가 이미 존재합니다.');
+
return;
}
diff --git a/database/seeders/PartnerMenuRenameSeeder.php b/database/seeders/PartnerMenuRenameSeeder.php
index ee6aef1d..77c155ca 100644
--- a/database/seeders/PartnerMenuRenameSeeder.php
+++ b/database/seeders/PartnerMenuRenameSeeder.php
@@ -19,7 +19,7 @@ public function run(): void
$menu = Menu::where('tenant_id', $tenantId)
->where(function ($q) {
$q->where('name', '협력사관리')
- ->orWhere('name', '협력사 관리');
+ ->orWhere('name', '협력사 관리');
})
->first();
diff --git a/database/seeders/PayableMenuRenameSeeder.php b/database/seeders/PayableMenuRenameSeeder.php
index 78c7db6e..edb4d026 100644
--- a/database/seeders/PayableMenuRenameSeeder.php
+++ b/database/seeders/PayableMenuRenameSeeder.php
@@ -14,7 +14,7 @@ public function run(): void
$menu = Menu::where('tenant_id', $tenantId)
->where(function ($q) {
$q->where('name', '채무관리')
- ->orWhere('name', '채무 관리');
+ ->orWhere('name', '채무 관리');
})
->first();
diff --git a/database/seeders/ProductInspectionTemplateSeeder.php b/database/seeders/ProductInspectionTemplateSeeder.php
index 3f93a930..dd9bf299 100644
--- a/database/seeders/ProductInspectionTemplateSeeder.php
+++ b/database/seeders/ProductInspectionTemplateSeeder.php
@@ -375,4 +375,4 @@ private function cleanupExisting(string $name): void
DocumentTemplateApprovalLine::where('template_id', $existing->id)->delete();
$existing->forceDelete();
}
-}
\ No newline at end of file
+}
diff --git a/database/seeders/QuoteFormulaCategorySeeder.php b/database/seeders/QuoteFormulaCategorySeeder.php
index 66133230..cb21c1b7 100644
--- a/database/seeders/QuoteFormulaCategorySeeder.php
+++ b/database/seeders/QuoteFormulaCategorySeeder.php
@@ -73,6 +73,6 @@ public function run(): void
);
}
- $this->command->info('QuoteFormulaCategorySeeder: ' . count($categories) . '개 카테고리 생성 완료');
+ $this->command->info('QuoteFormulaCategorySeeder: '.count($categories).'개 카테고리 생성 완료');
}
-}
\ No newline at end of file
+}
diff --git a/database/seeders/QuoteFormulaItemSeeder.php b/database/seeders/QuoteFormulaItemSeeder.php
index 849e715c..ab90e514 100644
--- a/database/seeders/QuoteFormulaItemSeeder.php
+++ b/database/seeders/QuoteFormulaItemSeeder.php
@@ -168,8 +168,8 @@ public function run(): void
]));
}
- $this->command->info('QuoteFormulaItemSeeder: ' . count($formulaItems) . '개 품목 매핑 생성 완료');
- $this->command->info(' - FG-SCR-001: ' . (isset($products['FG-SCR-001']) ? '14개 품목' : '미생성'));
- $this->command->info(' - FG-STL-001: ' . (isset($products['FG-STL-001']) ? '10개 품목' : '미생성'));
+ $this->command->info('QuoteFormulaItemSeeder: '.count($formulaItems).'개 품목 매핑 생성 완료');
+ $this->command->info(' - FG-SCR-001: '.(isset($products['FG-SCR-001']) ? '14개 품목' : '미생성'));
+ $this->command->info(' - FG-STL-001: '.(isset($products['FG-STL-001']) ? '10개 품목' : '미생성'));
}
-}
\ No newline at end of file
+}
diff --git a/database/seeders/QuoteFormulaRangeSeeder.php b/database/seeders/QuoteFormulaRangeSeeder.php
index 23d32e8c..f140ea1e 100644
--- a/database/seeders/QuoteFormulaRangeSeeder.php
+++ b/database/seeders/QuoteFormulaRangeSeeder.php
@@ -128,9 +128,9 @@ public function run(): void
]));
}
- $this->command->info('QuoteFormulaRangeSeeder: ' . count($ranges) . '개 범위 조건 생성 완료');
- $this->command->info(' - 모터 선택: ' . (isset($rangeFormulas['MOTOR']) ? '4개' : '0개'));
- $this->command->info(' - 가이드레일 선택: ' . (isset($rangeFormulas['GUIDE']) ? '4개' : '0개'));
- $this->command->info(' - 케이스 선택: ' . (isset($rangeFormulas['CASE']) ? '4개' : '0개'));
+ $this->command->info('QuoteFormulaRangeSeeder: '.count($ranges).'개 범위 조건 생성 완료');
+ $this->command->info(' - 모터 선택: '.(isset($rangeFormulas['MOTOR']) ? '4개' : '0개'));
+ $this->command->info(' - 가이드레일 선택: '.(isset($rangeFormulas['GUIDE']) ? '4개' : '0개'));
+ $this->command->info(' - 케이스 선택: '.(isset($rangeFormulas['CASE']) ? '4개' : '0개'));
}
-}
\ No newline at end of file
+}
diff --git a/database/seeders/QuoteFormulaSeeder.php b/database/seeders/QuoteFormulaSeeder.php
index dacbf577..dc9220c5 100644
--- a/database/seeders/QuoteFormulaSeeder.php
+++ b/database/seeders/QuoteFormulaSeeder.php
@@ -274,9 +274,9 @@ public function run(): void
]));
}
- $this->command->info('QuoteFormulaSeeder: ' . count($formulas) . '개 수식 생성 완료');
- $this->command->info(' - 입력변수: ' . count($inputVars) . '개');
- $this->command->info(' - 계산변수: ' . count($calcVars) . '개');
- $this->command->info(' - 범위선택: ' . count($rangeVars) . '개');
+ $this->command->info('QuoteFormulaSeeder: '.count($formulas).'개 수식 생성 완료');
+ $this->command->info(' - 입력변수: '.count($inputVars).'개');
+ $this->command->info(' - 계산변수: '.count($calcVars).'개');
+ $this->command->info(' - 범위선택: '.count($rangeVars).'개');
}
-}
\ No newline at end of file
+}
diff --git a/database/seeders/ReceivableMenuRenameSeeder.php b/database/seeders/ReceivableMenuRenameSeeder.php
index 35c452c3..0f9fbb14 100644
--- a/database/seeders/ReceivableMenuRenameSeeder.php
+++ b/database/seeders/ReceivableMenuRenameSeeder.php
@@ -14,7 +14,7 @@ public function run(): void
$menu = Menu::where('tenant_id', $tenantId)
->where(function ($q) {
$q->where('name', '채권관리')
- ->orWhere('name', '채권 관리');
+ ->orWhere('name', '채권 관리');
})
->first();
diff --git a/database/seeders/RefundMenuRenameSeeder.php b/database/seeders/RefundMenuRenameSeeder.php
index 334f9a0c..6ad71d68 100644
--- a/database/seeders/RefundMenuRenameSeeder.php
+++ b/database/seeders/RefundMenuRenameSeeder.php
@@ -14,7 +14,7 @@ public function run(): void
$menu = Menu::where('tenant_id', $tenantId)
->where(function ($q) {
$q->where('name', '환불관리')
- ->orWhere('name', '환불 관리');
+ ->orWhere('name', '환불 관리');
})
->first();
diff --git a/database/seeders/RemoveRnDLabsMenuSeeder.php b/database/seeders/RemoveRnDLabsMenuSeeder.php
index ef9edc4d..7cd98416 100644
--- a/database/seeders/RemoveRnDLabsMenuSeeder.php
+++ b/database/seeders/RemoveRnDLabsMenuSeeder.php
@@ -15,8 +15,9 @@ public function run(): void
->where('name', 'R&D Labs')
->first();
- if (!$menu) {
+ if (! $menu) {
$this->command->warn('R&D Labs 메뉴를 찾을 수 없습니다.');
+
return;
}
diff --git a/database/seeders/ReorganizeFinanceMenuSeeder.php b/database/seeders/ReorganizeFinanceMenuSeeder.php
index 86b5e9b3..dd253239 100644
--- a/database/seeders/ReorganizeFinanceMenuSeeder.php
+++ b/database/seeders/ReorganizeFinanceMenuSeeder.php
@@ -15,13 +15,13 @@ public function run(): void
// 1. 새 대분류 그룹 생성
// ==============================
$newGroups = [
- '재무/자금관리' => ['icon' => 'currency-dollar', 'sort' => 6],
- '회계/세무관리' => ['icon' => 'calculator', 'sort' => 7],
- '카드/차량관리' => ['icon' => 'credit-card', 'sort' => 8],
- '정산관리' => ['icon' => 'cash', 'sort' => 9],
- '고객/거래처/채권관리' => ['icon' => 'users', 'sort' => 10],
- '영업/매출관리' => ['icon' => 'briefcase', 'sort' => 11],
- '시스템/설정/내부관리' => ['icon' => 'settings', 'sort' => 12],
+ '재무/자금관리' => ['icon' => 'currency-dollar', 'sort' => 6],
+ '회계/세무관리' => ['icon' => 'calculator', 'sort' => 7],
+ '카드/차량관리' => ['icon' => 'credit-card', 'sort' => 8],
+ '정산관리' => ['icon' => 'cash', 'sort' => 9],
+ '고객/거래처/채권관리' => ['icon' => 'users', 'sort' => 10],
+ '영업/매출관리' => ['icon' => 'briefcase', 'sort' => 11],
+ '시스템/설정/내부관리' => ['icon' => 'settings', 'sort' => 12],
];
$parentIds = [];
@@ -56,37 +56,37 @@ public function run(): void
// [현재 이름 => [새 부모 그룹, 새 sort_order, 새 이름(null이면 변경 없음), 새 URL(null이면 변경 없음)]]
$menuMoves = [
// --- 재무/자금관리 ---
- '재무 대시보드' => ['재무/자금관리', 1, null, null],
- '일일자금일보' => ['재무/자금관리', 2, null, null],
- '자금계획일정' => ['재무/자금관리', 3, null, null],
- '보유계좌관리' => ['재무/자금관리', 4, null, null],
- '계좌입출금내역' => ['재무/자금관리', 5, null, null],
+ '재무 대시보드' => ['재무/자금관리', 1, null, null],
+ '일일자금일보' => ['재무/자금관리', 2, null, null],
+ '자금계획일정' => ['재무/자금관리', 3, null, null],
+ '보유계좌관리' => ['재무/자금관리', 4, null, null],
+ '계좌입출금내역' => ['재무/자금관리', 5, null, null],
// --- 회계/세무관리 ---
- '일반전표입력' => ['회계/세무관리', 1, null, null],
- '전자세금계산서' => ['회계/세무관리', 2, null, null],
+ '일반전표입력' => ['회계/세무관리', 1, null, null],
+ '전자세금계산서' => ['회계/세무관리', 2, null, null],
'홈택스 매출/매입' => ['회계/세무관리', 3, '홈택스매출/매입', null],
- '부가세관리' => ['회계/세무관리', 4, null, null],
+ '부가세관리' => ['회계/세무관리', 4, null, null],
// --- 카드/차량관리 ---
- '법인카드관리' => ['카드/차량관리', 1, null, null],
- '카드사용내역' => ['카드/차량관리', 2, null, null],
- '법인차량관리' => ['카드/차량관리', 3, '차량목록', '/finance/corporate-vehicles'],
+ '법인카드관리' => ['카드/차량관리', 1, null, null],
+ '카드사용내역' => ['카드/차량관리', 2, null, null],
+ '법인차량관리' => ['카드/차량관리', 3, '차량목록', '/finance/corporate-vehicles'],
// 차량일지는 아래에서 별도 생성
- '차량정비이력' => ['카드/차량관리', 5, '정비이력', null],
+ '차량정비이력' => ['카드/차량관리', 5, '정비이력', null],
// --- 정산관리 ---
- '영업수수료 정산' => ['정산관리', 1, '영업수수료정산', null],
- '컨설팅비용 정산' => ['정산관리', 2, '컨설팅비용정산', null],
- '고객사 정산' => ['정산관리', 3, '고객사정산', null],
- '구독료 정산' => ['정산관리', 4, '구독료정산', null],
+ '영업수수료 정산' => ['정산관리', 1, '영업수수료정산', null],
+ '컨설팅비용 정산' => ['정산관리', 2, '컨설팅비용정산', null],
+ '고객사 정산' => ['정산관리', 3, '고객사정산', null],
+ '구독료 정산' => ['정산관리', 4, '구독료정산', null],
// --- 고객/거래처/채권관리 ---
- '거래처 관리' => ['고객/거래처/채권관리', 1, '거래처관리', null],
- '고객사관리' => ['고객/거래처/채권관리', 2, null, null],
- '채권관리' => ['고객/거래처/채권관리', 3, '미수금관리', null],
- '채무관리' => ['고객/거래처/채권관리', 4, '미지급금관리', null],
- '환불관리' => ['고객/거래처/채권관리', 5, '환불/해지관리', null],
+ '거래처 관리' => ['고객/거래처/채권관리', 1, '거래처관리', null],
+ '고객사관리' => ['고객/거래처/채권관리', 2, null, null],
+ '채권관리' => ['고객/거래처/채권관리', 3, '미수금관리', null],
+ '채무관리' => ['고객/거래처/채권관리', 4, '미지급금관리', null],
+ '환불관리' => ['고객/거래처/채권관리', 5, '환불/해지관리', null],
// --- 영업/매출관리 --- (영업관리의 자식 중)
// 대시보드는 이름이 겹칠 수 있으므로 ID로 처리
@@ -106,8 +106,9 @@ public function run(): void
->where('is_active', true)
->first();
- if (!$menu) {
+ if (! $menu) {
$this->command->warn("메뉴 없음: {$currentName}");
+
continue;
}
@@ -142,7 +143,7 @@ public function run(): void
'parent_id' => $parentIds['카드/차량관리'],
'sort_order' => 4,
]);
- $this->command->info(" 이동: 차량일지 → 카드/차량관리 (sort: 4)");
+ $this->command->info(' 이동: 차량일지 → 카드/차량관리 (sort: 4)');
} else {
Menu::create([
'tenant_id' => $tenantId,
@@ -153,7 +154,7 @@ public function run(): void
'sort_order' => 4,
'is_active' => true,
]);
- $this->command->info(" 신규: 차량일지 → 카드/차량관리 (sort: 4)");
+ $this->command->info(' 신규: 차량일지 → 카드/차량관리 (sort: 4)');
}
// ==============================
@@ -212,7 +213,7 @@ public function run(): void
'parent_id' => $parentIds['영업/매출관리'],
'sort_order' => $nextSort++,
]);
- $this->command->info(" 이동(잔여): {$child->name} → 영업/매출관리 (sort: " . ($nextSort - 1) . ")");
+ $this->command->info(" 이동(잔여): {$child->name} → 영업/매출관리 (sort: ".($nextSort - 1).')');
}
}
@@ -256,7 +257,7 @@ public function run(): void
'url' => '/barobill/ecard',
'sort_order' => 1,
]);
- $this->command->info(" 변환: 바로빌본사 → 시스템/설정/내부관리/바로빌본사 (sort: 1)");
+ $this->command->info(' 변환: 바로빌본사 → 시스템/설정/내부관리/바로빌본사 (sort: 1)');
}
// 바로빌(15504)의 자식들 이동
@@ -269,7 +270,7 @@ public function run(): void
if ($barobillTenant) {
$tenantMoves = [
'사용량조회' => 4,
- '과금관리' => 5,
+ '과금관리' => 5,
];
$barobillChildren = Menu::withoutGlobalScopes()
@@ -311,7 +312,7 @@ public function run(): void
'parent_id' => $sysGroupId,
'sort_order' => $nextSort++,
]);
- $this->command->info(" 이동: {$child->name} → 시스템/설정/내부관리 (sort: " . ($nextSort - 1) . ")");
+ $this->command->info(" 이동: {$child->name} → 시스템/설정/내부관리 (sort: ".($nextSort - 1).')');
}
$sysOld->update(['is_active' => false]);
diff --git a/database/seeders/SalesMenuFixSeeder.php b/database/seeders/SalesMenuFixSeeder.php
index 001e0ede..040deaf9 100644
--- a/database/seeders/SalesMenuFixSeeder.php
+++ b/database/seeders/SalesMenuFixSeeder.php
@@ -43,8 +43,9 @@ public function run(): void
->whereNull('parent_id')
->value('id');
- if (!$salesParentId) {
+ if (! $salesParentId) {
$this->command->error('영업관리 메뉴를 찾을 수 없습니다.');
+
return;
}
diff --git a/database/seeders/SampleItemsSeeder.php b/database/seeders/SampleItemsSeeder.php
index f132826f..e6d5e711 100644
--- a/database/seeders/SampleItemsSeeder.php
+++ b/database/seeders/SampleItemsSeeder.php
@@ -482,4 +482,4 @@ private function buildBomJson(int $tenantId, array $bomItems): string
return json_encode($result);
}
-}
\ No newline at end of file
+}
diff --git a/database/seeders/VehicleLogMenuSeeder.php b/database/seeders/VehicleLogMenuSeeder.php
index be81b80d..633e4cda 100644
--- a/database/seeders/VehicleLogMenuSeeder.php
+++ b/database/seeders/VehicleLogMenuSeeder.php
@@ -20,8 +20,9 @@ public function run(): void
->where('name', '법인차량관리')
->first();
- if (!$vehicleMenu) {
+ if (! $vehicleMenu) {
$this->command->error('법인차량관리 메뉴를 찾을 수 없습니다.');
+
return;
}
@@ -33,6 +34,7 @@ public function run(): void
if ($existingMenu) {
$this->command->info('차량일지 메뉴가 이미 존재합니다.');
+
return;
}
diff --git a/database/seeders/VehicleMaintenanceMenuMoveSeeder.php b/database/seeders/VehicleMaintenanceMenuMoveSeeder.php
index 3db4222f..94777aff 100644
--- a/database/seeders/VehicleMaintenanceMenuMoveSeeder.php
+++ b/database/seeders/VehicleMaintenanceMenuMoveSeeder.php
@@ -19,8 +19,9 @@ public function run(): void
->where('name', '법인차량관리')
->first();
- if (!$parentMenu) {
+ if (! $parentMenu) {
$this->command->error('법인차량관리 메뉴를 찾을 수 없습니다.');
+
return;
}
@@ -28,23 +29,25 @@ public function run(): void
$maintenanceMenu = Menu::where('tenant_id', $tenantId)
->where(function ($q) {
$q->where('name', '차량정비이력')
- ->orWhere('name', '차량정비');
+ ->orWhere('name', '차량정비');
})
->first();
- if (!$maintenanceMenu) {
+ if (! $maintenanceMenu) {
$this->command->error('차량정비이력 메뉴를 찾을 수 없습니다.');
Menu::where('tenant_id', $tenantId)
->whereNull('parent_id')
->orderBy('sort_order')
->get(['id', 'name', 'url'])
->each(fn ($m) => $this->command->line(" - [{$m->id}] {$m->name} ({$m->url})"));
+
return;
}
// 이미 법인차량관리 하위에 있는지 확인
if ($maintenanceMenu->parent_id == $parentMenu->id) {
$this->command->info('차량정비이력은 이미 법인차량관리 하위에 있습니다.');
+
return;
}
diff --git a/resources/views/finance/account-transactions.blade.php b/resources/views/finance/account-transactions.blade.php
index feabc615..f1310e21 100644
--- a/resources/views/finance/account-transactions.blade.php
+++ b/resources/views/finance/account-transactions.blade.php
@@ -16,6 +16,19 @@
@push('scripts')
@include('partials.react-cdn')
+
@verbatim