201 lines
5.9 KiB
PHP
201 lines
5.9 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace App\Services\Quote;
|
||
|
|
|
||
|
|
use App\Models\Quote\QuoteFormulaCategory;
|
||
|
|
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||
|
|
use Illuminate\Database\Eloquent\Collection;
|
||
|
|
use Illuminate\Support\Facades\DB;
|
||
|
|
|
||
|
|
class QuoteFormulaCategoryService
|
||
|
|
{
|
||
|
|
/**
|
||
|
|
* 카테고리 목록 조회 (페이지네이션)
|
||
|
|
*/
|
||
|
|
public function getCategories(array $filters = [], int $perPage = 15): LengthAwarePaginator
|
||
|
|
{
|
||
|
|
$tenantId = session('selected_tenant_id');
|
||
|
|
|
||
|
|
$query = QuoteFormulaCategory::query()
|
||
|
|
->withCount('formulas')
|
||
|
|
->withCount(['formulas as active_formulas_count' => function ($q) {
|
||
|
|
$q->where('is_active', true);
|
||
|
|
}]);
|
||
|
|
|
||
|
|
// 테넌트 필터
|
||
|
|
if ($tenantId && $tenantId !== 'all') {
|
||
|
|
$query->where('tenant_id', $tenantId);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 검색
|
||
|
|
if (! empty($filters['search'])) {
|
||
|
|
$search = $filters['search'];
|
||
|
|
$query->where(function ($q) use ($search) {
|
||
|
|
$q->where('name', 'like', "%{$search}%")
|
||
|
|
->orWhere('code', 'like', "%{$search}%")
|
||
|
|
->orWhere('description', 'like', "%{$search}%");
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
// 활성화 필터
|
||
|
|
if (isset($filters['is_active']) && $filters['is_active'] !== '') {
|
||
|
|
$query->where('is_active', (bool) $filters['is_active']);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 정렬
|
||
|
|
$sortBy = $filters['sort_by'] ?? 'sort_order';
|
||
|
|
$sortDirection = $filters['sort_direction'] ?? 'asc';
|
||
|
|
$query->orderBy($sortBy, $sortDirection);
|
||
|
|
|
||
|
|
return $query->paginate($perPage);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 전체 카테고리 목록 (선택용)
|
||
|
|
*/
|
||
|
|
public function getAllCategories(): Collection
|
||
|
|
{
|
||
|
|
$tenantId = session('selected_tenant_id');
|
||
|
|
|
||
|
|
return QuoteFormulaCategory::query()
|
||
|
|
->where('tenant_id', $tenantId)
|
||
|
|
->where('is_active', true)
|
||
|
|
->orderBy('sort_order')
|
||
|
|
->get();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 활성 카테고리 목록 (드롭다운용)
|
||
|
|
*/
|
||
|
|
public function getActiveCategories(): Collection
|
||
|
|
{
|
||
|
|
return $this->getAllCategories();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 카테고리 상세 조회
|
||
|
|
*/
|
||
|
|
public function getCategoryById(int $id): ?QuoteFormulaCategory
|
||
|
|
{
|
||
|
|
return QuoteFormulaCategory::with('formulas')->find($id);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 카테고리 생성
|
||
|
|
*/
|
||
|
|
public function createCategory(array $data): QuoteFormulaCategory
|
||
|
|
{
|
||
|
|
$tenantId = session('selected_tenant_id');
|
||
|
|
|
||
|
|
return DB::transaction(function () use ($data, $tenantId) {
|
||
|
|
// 자동 sort_order 할당
|
||
|
|
if (! isset($data['sort_order'])) {
|
||
|
|
$maxOrder = QuoteFormulaCategory::where('tenant_id', $tenantId)->max('sort_order');
|
||
|
|
$data['sort_order'] = ($maxOrder ?? 0) + 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
return QuoteFormulaCategory::create([
|
||
|
|
'tenant_id' => $tenantId,
|
||
|
|
'code' => $data['code'],
|
||
|
|
'name' => $data['name'],
|
||
|
|
'description' => $data['description'] ?? null,
|
||
|
|
'sort_order' => $data['sort_order'],
|
||
|
|
'is_active' => $data['is_active'] ?? true,
|
||
|
|
'created_by' => auth()->id(),
|
||
|
|
]);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 카테고리 수정
|
||
|
|
*/
|
||
|
|
public function updateCategory(int $id, array $data): QuoteFormulaCategory
|
||
|
|
{
|
||
|
|
$category = QuoteFormulaCategory::findOrFail($id);
|
||
|
|
|
||
|
|
$category->update([
|
||
|
|
'code' => $data['code'] ?? $category->code,
|
||
|
|
'name' => $data['name'] ?? $category->name,
|
||
|
|
'description' => array_key_exists('description', $data) ? $data['description'] : $category->description,
|
||
|
|
'sort_order' => $data['sort_order'] ?? $category->sort_order,
|
||
|
|
'is_active' => $data['is_active'] ?? $category->is_active,
|
||
|
|
'updated_by' => auth()->id(),
|
||
|
|
]);
|
||
|
|
|
||
|
|
return $category->fresh();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 카테고리 삭제
|
||
|
|
*/
|
||
|
|
public function deleteCategory(int $id): void
|
||
|
|
{
|
||
|
|
$category = QuoteFormulaCategory::findOrFail($id);
|
||
|
|
|
||
|
|
// 연관 수식이 있으면 삭제 불가
|
||
|
|
if ($category->formulas()->count() > 0) {
|
||
|
|
throw new \Exception('연관된 수식이 있어 삭제할 수 없습니다. 먼저 수식을 삭제해주세요.');
|
||
|
|
}
|
||
|
|
|
||
|
|
$category->delete();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 카테고리 순서 변경
|
||
|
|
*/
|
||
|
|
public function reorderCategories(array $orderData): void
|
||
|
|
{
|
||
|
|
DB::transaction(function () use ($orderData) {
|
||
|
|
foreach ($orderData as $item) {
|
||
|
|
QuoteFormulaCategory::where('id', $item['id'])
|
||
|
|
->update(['sort_order' => $item['sort_order']]);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 카테고리 활성/비활성 토글
|
||
|
|
*/
|
||
|
|
public function toggleActive(int $id): QuoteFormulaCategory
|
||
|
|
{
|
||
|
|
$category = QuoteFormulaCategory::findOrFail($id);
|
||
|
|
|
||
|
|
$category->is_active = ! $category->is_active;
|
||
|
|
$category->updated_by = auth()->id();
|
||
|
|
$category->save();
|
||
|
|
|
||
|
|
return $category;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 코드 중복 체크
|
||
|
|
*/
|
||
|
|
public function isCodeExists(string $code, ?int $excludeId = null): bool
|
||
|
|
{
|
||
|
|
$tenantId = session('selected_tenant_id');
|
||
|
|
|
||
|
|
$query = QuoteFormulaCategory::where('tenant_id', $tenantId)
|
||
|
|
->where('code', $code);
|
||
|
|
|
||
|
|
if ($excludeId) {
|
||
|
|
$query->where('id', '!=', $excludeId);
|
||
|
|
}
|
||
|
|
|
||
|
|
return $query->exists();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 카테고리 통계
|
||
|
|
*/
|
||
|
|
public function getCategoryStats(): array
|
||
|
|
{
|
||
|
|
$tenantId = session('selected_tenant_id');
|
||
|
|
|
||
|
|
return [
|
||
|
|
'total' => QuoteFormulaCategory::where('tenant_id', $tenantId)->count(),
|
||
|
|
'active' => QuoteFormulaCategory::where('tenant_id', $tenantId)->where('is_active', true)->count(),
|
||
|
|
'inactive' => QuoteFormulaCategory::where('tenant_id', $tenantId)->where('is_active', false)->count(),
|
||
|
|
];
|
||
|
|
}
|
||
|
|
}
|