style: Pint 코드 스타일 자동 수정 및 마이그레이션 실행

- Pint 스타일 이슈 25개 수정 (783 파일 통과)
- 마이그레이션 4개 실행 (payrolls, payroll_settings, push 테이블)
- routes/api.php import 정렬
This commit is contained in:
2025-12-18 11:40:49 +09:00
parent 76d86cfa9f
commit c7eee97610
26 changed files with 134 additions and 42 deletions

View File

@@ -1,6 +1,6 @@
# 논리적 데이터베이스 관계 문서
> **자동 생성**: 2025-12-17 23:09:53
> **자동 생성**: 2025-12-18 11:37:56
> **소스**: Eloquent 모델 관계 분석
## 📊 모델별 관계 현황
@@ -306,6 +306,14 @@ ### price_revisions
- **price()**: belongsTo → `prices`
### push_device_tokens
**모델**: `App\Models\PushDeviceToken`
### push_notification_settings
**모델**: `App\Models\PushNotificationSetting`
### lots
**모델**: `App\Models\Qualitys\Lot`
@@ -339,6 +347,36 @@ ### quote_revisions
- **quote()**: belongsTo → `quotes`
- **reviser()**: belongsTo → `users`
### approvals
**모델**: `App\Models\Tenants\Approval`
- **form()**: belongsTo → `approval_forms`
- **drafter()**: belongsTo → `users`
- **creator()**: belongsTo → `users`
- **updater()**: belongsTo → `users`
- **steps()**: hasMany → `approval_steps`
- **approverSteps()**: hasMany → `approval_steps`
- **referenceSteps()**: hasMany → `approval_steps`
### approval_forms
**모델**: `App\Models\Tenants\ApprovalForm`
- **creator()**: belongsTo → `users`
- **updater()**: belongsTo → `users`
- **approvals()**: hasMany → `approvals`
### approval_lines
**모델**: `App\Models\Tenants\ApprovalLine`
- **creator()**: belongsTo → `users`
- **updater()**: belongsTo → `users`
### approval_steps
**모델**: `App\Models\Tenants\ApprovalStep`
- **approval()**: belongsTo → `approvals`
- **approver()**: belongsTo → `users`
### attendances
**모델**: `App\Models\Tenants\Attendance`
@@ -392,6 +430,20 @@ ### payments
- **subscription()**: belongsTo → `subscriptions`
### payrolls
**모델**: `App\Models\Tenants\Payroll`
- **user()**: belongsTo → `users`
- **confirmer()**: belongsTo → `users`
- **withdrawal()**: belongsTo → `withdrawals`
- **creator()**: belongsTo → `users`
- **updater()**: belongsTo → `users`
### payroll_settings
**모델**: `App\Models\Tenants\PayrollSetting`
- **tenant()**: belongsTo → `tenants`
### department_users
**모델**: `App\Models\Tenants\Pivots\DepartmentUser`

View File

@@ -48,4 +48,4 @@ public function render()
'duplicate_code' => $this->duplicateCode,
], 400);
}
}
}

View File

@@ -88,4 +88,4 @@ public function getNotificationTypes()
];
});
}
}
}

View File

@@ -69,6 +69,7 @@ protected function shouldSkip(Request $request): bool
return true;
}
}
return false;
}
@@ -124,6 +125,7 @@ protected function maskSensitiveHeaders(array $headers): array
$headers[$header] = ['***MASKED***'];
}
}
return $headers;
}
@@ -136,6 +138,7 @@ protected function maskSensitiveFields(array $data): array
$data[$key] = $this->maskSensitiveFields($value);
}
}
return $data;
}
@@ -148,7 +151,7 @@ protected function truncateResponse(?string $content): ?string
// 10KB 이상이면 잘라내기
$maxLength = 10 * 1024;
if (strlen($content) > $maxLength) {
return substr($content, 0, $maxLength) . '...[TRUNCATED]';
return substr($content, 0, $maxLength).'...[TRUNCATED]';
}
return $content;
@@ -157,7 +160,7 @@ protected function truncateResponse(?string $content): ?string
protected function writeToLogFile(array $logData): void
{
$logMessage = sprintf(
"[%s] %s %s | Status: %d | Duration: %dms | IP: %s | User: %s",
'[%s] %s %s | Status: %d | Duration: %dms | IP: %s | User: %s',
now()->format('Y-m-d H:i:s'),
$logData['method'],
$logData['url'],
@@ -188,13 +191,14 @@ protected function getOrCreateGroupId(?int $tenantId, ?int $userId): string
if ($existingGroupId) {
// TTL 갱신 (연속 요청 시 그룹 유지)
cache()->put($cacheKey, $existingGroupId, $groupTtl);
return $existingGroupId;
}
// 새 그룹 ID 생성
$newGroupId = now()->format('Ymd_His_') . substr(md5(uniqid((string) mt_rand(), true)), 0, 8);
$newGroupId = now()->format('Ymd_His_').substr(md5(uniqid((string) mt_rand(), true)), 0, 8);
cache()->put($cacheKey, $newGroupId, $groupTtl);
return $newGroupId;
}
}
}

View File

@@ -40,4 +40,4 @@ public function messages(): array
'platform.in' => __('error.push.platform_invalid'),
];
}
}
}

View File

@@ -63,4 +63,4 @@ public static function pruneOldLogs(): int
{
return static::where('created_at', '<', now()->subDay())->delete();
}
}
}

View File

@@ -111,4 +111,4 @@ public function requiresInspection(): bool
{
return $this->is_inspection === 'Y';
}
}
}

View File

@@ -76,4 +76,4 @@ public function scopeForUser($query, int $userId)
{
return $query->where('user_id', $userId);
}
}
}

View File

@@ -128,4 +128,4 @@ public function scopeOfType($query, string $type)
{
return $query->where('notification_type', $type);
}
}
}

View File

@@ -274,4 +274,4 @@ protected function getDefaultSound(string $type): string
default => PushNotificationSetting::SOUND_DEFAULT,
};
}
}
}

View File

@@ -16,6 +16,7 @@
* schema="PushDeviceToken",
* type="object",
* description="푸시 디바이스 토큰",
*
* @OA\Property(property="id", type="integer", example=1),
* @OA\Property(property="tenant_id", type="integer", example=1),
* @OA\Property(property="user_id", type="integer", example=5),
@@ -33,6 +34,7 @@
* schema="PushNotificationSetting",
* type="object",
* description="푸시 알림 설정",
*
* @OA\Property(property="id", type="integer", example=1),
* @OA\Property(property="tenant_id", type="integer", example=1),
* @OA\Property(property="user_id", type="integer", example=5),
@@ -49,6 +51,7 @@
* schema="RegisterTokenRequest",
* type="object",
* required={"token", "platform"},
*
* @OA\Property(property="token", type="string", minLength=10, example="dGhpcyBpcyBhIHNhbXBsZSBGQ00gdG9rZW4...", description="FCM 토큰"),
* @OA\Property(property="platform", type="string", enum={"ios", "android", "web"}, example="android", description="디바이스 플랫폼"),
* @OA\Property(property="device_name", type="string", nullable=true, maxLength=255, example="Samsung Galaxy S24", description="디바이스명"),
@@ -59,6 +62,7 @@
* schema="UnregisterTokenRequest",
* type="object",
* required={"token"},
*
* @OA\Property(property="token", type="string", example="dGhpcyBpcyBhIHNhbXBsZSBGQ00gdG9rZW4...", description="해제할 FCM 토큰")
* )
*
@@ -66,13 +70,16 @@
* schema="UpdatePushSettingsRequest",
* type="object",
* required={"settings"},
*
* @OA\Property(
* property="settings",
* type="array",
* description="알림 설정 배열",
*
* @OA\Items(
* type="object",
* required={"notification_type", "is_enabled"},
*
* @OA\Property(property="notification_type", type="string", enum={"deposit", "withdrawal", "order", "approval", "attendance", "notice", "system"}, example="deposit"),
* @OA\Property(property="is_enabled", type="boolean", example=true),
* @OA\Property(property="sound", type="string", nullable=true, enum={"default.wav", "deposit.wav", "withdrawal.wav", "order.wav", "approval.wav", "urgent.wav"}, example="deposit.wav"),
@@ -85,16 +92,20 @@
* @OA\Schema(
* schema="NotificationTypesResponse",
* type="object",
*
* @OA\Property(
* property="types",
* type="array",
* description="지원하는 알림 유형 목록",
*
* @OA\Items(type="string", example="deposit")
* ),
*
* @OA\Property(
* property="sounds",
* type="array",
* description="지원하는 알림음 목록",
*
* @OA\Items(type="string", example="deposit.wav")
* )
* )
@@ -111,16 +122,20 @@ class PushApi
*
* @OA\RequestBody(
* required=true,
*
* @OA\JsonContent(ref="#/components/schemas/RegisterTokenRequest")
* ),
*
* @OA\Response(
* response=200,
* description="토큰 등록 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(property="message", type="string", example="푸시 토큰이 등록되었습니다."),
* @OA\Property(property="data", ref="#/components/schemas/PushDeviceToken")
* )
@@ -144,16 +159,20 @@ public function registerToken() {}
*
* @OA\RequestBody(
* required=true,
*
* @OA\JsonContent(ref="#/components/schemas/UnregisterTokenRequest")
* ),
*
* @OA\Response(
* response=200,
* description="토큰 해제 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(property="message", type="string", example="푸시 토큰이 해제되었습니다."),
* @OA\Property(
* property="data",
@@ -182,13 +201,17 @@ public function unregisterToken() {}
* @OA\Response(
* response=200,
* description="조회 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(
* property="data",
* type="array",
*
* @OA\Items(ref="#/components/schemas/PushDeviceToken")
* )
* )
@@ -212,10 +235,13 @@ public function getTokens() {}
* @OA\Response(
* response=200,
* description="조회 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(
* property="data",
* type="object",
@@ -248,20 +274,25 @@ public function getSettings() {}
*
* @OA\RequestBody(
* required=true,
*
* @OA\JsonContent(ref="#/components/schemas/UpdatePushSettingsRequest")
* ),
*
* @OA\Response(
* response=200,
* description="설정 업데이트 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(property="message", type="string", example="알림 설정이 업데이트되었습니다."),
* @OA\Property(
* property="data",
* type="array",
*
* @OA\Items(ref="#/components/schemas/PushNotificationSetting")
* )
* )
@@ -286,10 +317,13 @@ public function updateSettings() {}
* @OA\Response(
* response=200,
* description="조회 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(property="data", ref="#/components/schemas/NotificationTypesResponse")
* )
* }
@@ -300,4 +334,4 @@ public function updateSettings() {}
* )
*/
public function getNotificationTypes() {}
}
}

View File

@@ -26,4 +26,4 @@ public function down(): void
$table->dropColumn('options');
});
}
};
};

View File

@@ -157,4 +157,4 @@ private function restoreFieldKeyPrefixes(): void
->where('field_key', 'note')
->update(['field_key' => 'material_receipts_note']);
}
};
};

View File

@@ -25,4 +25,4 @@ public function down(): void
$table->dropColumn('bom');
});
}
};
};

View File

@@ -100,4 +100,4 @@ public function down(): void
{
Schema::dropIfExists('items');
}
};
};

View File

@@ -38,4 +38,4 @@ public function down(): void
{
Schema::dropIfExists('item_id_mappings');
}
};
};

View File

@@ -21,4 +21,4 @@ public function down(): void
{
// 비활성화
}
};
};

View File

@@ -1,7 +1,6 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
@@ -46,4 +45,4 @@ public function down(): void
// items 테이블은 재설계 후 새로운 마이그레이션으로 생성 예정
echo "⚠️ 이 마이그레이션은 롤백되지 않습니다. items 테이블 재설계 후 새로운 마이그레이션을 사용하세요.\n";
}
};
};

View File

@@ -27,7 +27,7 @@ public function up(): void
->whereNotIn('product_type', ['FG', 'PT'])
->count();
Log::info("Phase 0: Normalizing item_types", [
Log::info('Phase 0: Normalizing item_types', [
'total_before' => $beforeCount,
'non_standard_count' => $nonStandardCount,
]);
@@ -57,7 +57,7 @@ public function up(): void
// 4. 삭제 후 건수 확인
$afterCount = DB::table('products')->count();
Log::info("Phase 0: Normalization complete", [
Log::info('Phase 0: Normalization complete', [
'bom_deleted' => $bomDeleted,
'products_deleted' => $deleted,
'total_after' => $afterCount,
@@ -71,6 +71,6 @@ public function up(): void
*/
public function down(): void
{
Log::warning("Phase 0 rollback: Deleted data cannot be restored");
Log::warning('Phase 0 rollback: Deleted data cannot be restored');
}
};
};

View File

@@ -68,4 +68,4 @@ public function down(): void
{
Schema::dropIfExists('items');
}
};
};

View File

@@ -67,4 +67,4 @@ public function down(): void
{
Schema::dropIfExists('item_details');
}
};
};

View File

@@ -163,7 +163,7 @@ public function up(): void
$materialCount++;
}
Log::info("Phase 1.3: Data migration complete", [
Log::info('Phase 1.3: Data migration complete', [
'products_migrated' => $productCount,
'materials_migrated' => $materialCount,
'total' => $productCount + $materialCount,
@@ -182,6 +182,6 @@ public function down(): void
// ID 매핑 테이블 삭제
Schema::dropIfExists('item_id_mappings');
Log::info("Phase 1.3: Data migration rolled back");
Log::info('Phase 1.3: Data migration rolled back');
}
};
};

View File

@@ -35,6 +35,7 @@ public function up(): void
if (! $childItemId || ! $childItemType) {
$newBom[] = $entry;
continue;
}
@@ -47,6 +48,7 @@ public function up(): void
if (! $sourceTable) {
$newBom[] = $entry;
continue;
}
@@ -104,6 +106,7 @@ public function down(): void
if (! $childItemId) {
$newBom[] = $entry;
continue;
}

View File

@@ -32,4 +32,4 @@ public function down(): void
{
Schema::dropIfExists('push_device_tokens');
}
};
};

View File

@@ -31,4 +31,4 @@ public function down(): void
{
Schema::dropIfExists('push_notification_settings');
}
};
};

View File

@@ -3,6 +3,9 @@
use App\Http\Controllers\Api\Admin\GlobalMenuController;
use App\Http\Controllers\Api\V1\AdminController;
use App\Http\Controllers\Api\V1\ApiController;
use App\Http\Controllers\Api\V1\ApprovalController;
use App\Http\Controllers\Api\V1\ApprovalFormController;
use App\Http\Controllers\Api\V1\ApprovalLineController;
use App\Http\Controllers\Api\V1\AttendanceController;
use App\Http\Controllers\Api\V1\BankAccountController;
use App\Http\Controllers\Api\V1\BoardController;
@@ -36,23 +39,21 @@
use App\Http\Controllers\Api\V1\ItemMaster\ItemSectionController;
use App\Http\Controllers\Api\V1\ItemMaster\SectionTemplateController;
use App\Http\Controllers\Api\V1\ItemMaster\UnitOptionController;
// use App\Http\Controllers\Api\V1\MaterialController; // REMOVED: materials 테이블 삭제됨
use App\Http\Controllers\Api\V1\ItemsBomController;
use App\Http\Controllers\Api\V1\ItemsController;
use App\Http\Controllers\Api\V1\ItemsFileController;
// use App\Http\Controllers\Api\V1\MaterialController; // REMOVED: materials 테이블 삭제됨
use App\Http\Controllers\Api\V1\ApprovalController;
use App\Http\Controllers\Api\V1\ApprovalFormController;
use App\Http\Controllers\Api\V1\ApprovalLineController;
use App\Http\Controllers\Api\V1\LeaveController;
use App\Http\Controllers\Api\V1\MenuController;
use App\Http\Controllers\Api\V1\ModelSetController;
use App\Http\Controllers\Api\V1\PayrollController;
use App\Http\Controllers\Api\V1\PermissionController;
use App\Http\Controllers\Api\V1\PostController;
// use App\Http\Controllers\Api\V1\ProductBomItemController; // REMOVED: products 테이블 삭제됨
// use App\Http\Controllers\Api\V1\ProductController; // REMOVED: products 테이블 삭제됨
use App\Http\Controllers\Api\V1\PostController;
use App\Http\Controllers\Api\V1\PricingController;
use App\Http\Controllers\Api\V1\PushNotificationController;
use App\Http\Controllers\Api\V1\PurchaseController;
use App\Http\Controllers\Api\V1\PushNotificationController;
use App\Http\Controllers\Api\V1\QuoteController;
use App\Http\Controllers\Api\V1\RefreshController;
use App\Http\Controllers\Api\V1\RegisterController;
@@ -62,18 +63,17 @@
use App\Http\Controllers\Api\V1\SaleController;
use App\Http\Controllers\Api\V1\SiteController;
use App\Http\Controllers\Api\V1\TenantController;
use App\Http\Controllers\Api\V1\TenantFieldSettingController;
// 설계 전용 (디자인 네임스페이스)
use App\Http\Controllers\Api\V1\TenantFieldSettingController;
use App\Http\Controllers\Api\V1\TenantOptionGroupController;
use App\Http\Controllers\Api\V1\TenantOptionValueController;
use App\Http\Controllers\Api\V1\TenantStatFieldController;
use App\Http\Controllers\Api\V1\TenantUserProfileController;
use App\Http\Controllers\Api\V1\UserController;
// 모델셋 관리 (견적 시스템)
use App\Http\Controllers\Api\V1\UserController;
use App\Http\Controllers\Api\V1\UserRoleController;
use App\Http\Controllers\Api\V1\WithdrawalController;
use App\Http\Controllers\Api\V1\WorkSettingController;
use App\Http\Controllers\Api\V1\PayrollController;
use Illuminate\Support\Facades\Route;
// V1 초기 개발