190 lines
7.0 KiB
PHP
190 lines
7.0 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace App\Services;
|
||
|
|
|
||
|
|
use App\Models\Tenants\CondolenceExpense;
|
||
|
|
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||
|
|
use Illuminate\Support\Facades\DB;
|
||
|
|
|
||
|
|
class CondolenceExpenseService extends Service
|
||
|
|
{
|
||
|
|
/**
|
||
|
|
* 목록 조회 (페이지네이션 + 필터)
|
||
|
|
*/
|
||
|
|
public function index(array $params): LengthAwarePaginator
|
||
|
|
{
|
||
|
|
$query = CondolenceExpense::query();
|
||
|
|
|
||
|
|
// 연도 필터
|
||
|
|
if (! empty($params['year'])) {
|
||
|
|
$query->inYear((int) $params['year']);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 카테고리 필터
|
||
|
|
if (! empty($params['category']) && $params['category'] !== 'all') {
|
||
|
|
$query->byCategory($params['category']);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 통합 검색
|
||
|
|
if (! empty($params['search'])) {
|
||
|
|
$search = $params['search'];
|
||
|
|
$query->where(function ($q) use ($search) {
|
||
|
|
$q->where('partner_name', 'like', "%{$search}%")
|
||
|
|
->orWhere('description', 'like', "%{$search}%")
|
||
|
|
->orWhere('memo', 'like', "%{$search}%");
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
// 정렬
|
||
|
|
$sortBy = $params['sort_by'] ?? 'event_date';
|
||
|
|
$sortOrder = $params['sort_order'] ?? 'desc';
|
||
|
|
$query->orderBy($sortBy, $sortOrder)->orderByDesc('id');
|
||
|
|
|
||
|
|
$perPage = $params['per_page'] ?? 50;
|
||
|
|
|
||
|
|
return $query->paginate($perPage);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 상세 조회
|
||
|
|
*/
|
||
|
|
public function show(int $id): CondolenceExpense
|
||
|
|
{
|
||
|
|
return CondolenceExpense::with('creator:id,name')->findOrFail($id);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 등록
|
||
|
|
*/
|
||
|
|
public function store(array $data): CondolenceExpense
|
||
|
|
{
|
||
|
|
$tenantId = $this->tenantId();
|
||
|
|
$userId = $this->apiUserId();
|
||
|
|
|
||
|
|
return DB::transaction(function () use ($data, $tenantId, $userId) {
|
||
|
|
return CondolenceExpense::create([
|
||
|
|
'tenant_id' => $tenantId,
|
||
|
|
'event_date' => $data['event_date'] ?? null,
|
||
|
|
'expense_date' => $data['expense_date'] ?? null,
|
||
|
|
'partner_name' => $data['partner_name'],
|
||
|
|
'description' => $data['description'] ?? null,
|
||
|
|
'category' => $data['category'],
|
||
|
|
'has_cash' => $data['has_cash'] ?? false,
|
||
|
|
'cash_method' => ($data['has_cash'] ?? false) ? ($data['cash_method'] ?? null) : null,
|
||
|
|
'cash_amount' => ($data['has_cash'] ?? false) ? ($data['cash_amount'] ?? 0) : 0,
|
||
|
|
'has_gift' => $data['has_gift'] ?? false,
|
||
|
|
'gift_type' => ($data['has_gift'] ?? false) ? ($data['gift_type'] ?? null) : null,
|
||
|
|
'gift_amount' => ($data['has_gift'] ?? false) ? ($data['gift_amount'] ?? 0) : 0,
|
||
|
|
'total_amount' => $this->calculateTotal($data),
|
||
|
|
'memo' => $data['memo'] ?? null,
|
||
|
|
'created_by' => $userId,
|
||
|
|
'updated_by' => $userId,
|
||
|
|
]);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 수정
|
||
|
|
*/
|
||
|
|
public function update(int $id, array $data): CondolenceExpense
|
||
|
|
{
|
||
|
|
$userId = $this->apiUserId();
|
||
|
|
|
||
|
|
return DB::transaction(function () use ($id, $data, $userId) {
|
||
|
|
$expense = CondolenceExpense::findOrFail($id);
|
||
|
|
|
||
|
|
$expense->fill([
|
||
|
|
'event_date' => $data['event_date'] ?? $expense->event_date,
|
||
|
|
'expense_date' => $data['expense_date'] ?? $expense->expense_date,
|
||
|
|
'partner_name' => $data['partner_name'] ?? $expense->partner_name,
|
||
|
|
'description' => $data['description'] ?? $expense->description,
|
||
|
|
'category' => $data['category'] ?? $expense->category,
|
||
|
|
'has_cash' => $data['has_cash'] ?? $expense->has_cash,
|
||
|
|
'cash_method' => ($data['has_cash'] ?? $expense->has_cash) ? ($data['cash_method'] ?? $expense->cash_method) : null,
|
||
|
|
'cash_amount' => ($data['has_cash'] ?? $expense->has_cash) ? ($data['cash_amount'] ?? $expense->cash_amount) : 0,
|
||
|
|
'has_gift' => $data['has_gift'] ?? $expense->has_gift,
|
||
|
|
'gift_type' => ($data['has_gift'] ?? $expense->has_gift) ? ($data['gift_type'] ?? $expense->gift_type) : null,
|
||
|
|
'gift_amount' => ($data['has_gift'] ?? $expense->has_gift) ? ($data['gift_amount'] ?? $expense->gift_amount) : 0,
|
||
|
|
'total_amount' => $this->calculateTotal(array_merge($expense->toArray(), $data)),
|
||
|
|
'memo' => $data['memo'] ?? $expense->memo,
|
||
|
|
'updated_by' => $userId,
|
||
|
|
]);
|
||
|
|
|
||
|
|
$expense->save();
|
||
|
|
|
||
|
|
return $expense->fresh();
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 삭제 (소프트)
|
||
|
|
*/
|
||
|
|
public function destroy(int $id): bool
|
||
|
|
{
|
||
|
|
$userId = $this->apiUserId();
|
||
|
|
|
||
|
|
return DB::transaction(function () use ($id, $userId) {
|
||
|
|
$expense = CondolenceExpense::findOrFail($id);
|
||
|
|
$expense->deleted_by = $userId;
|
||
|
|
$expense->save();
|
||
|
|
$expense->delete();
|
||
|
|
|
||
|
|
return true;
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 통계 조회
|
||
|
|
*/
|
||
|
|
public function summary(array $params): array
|
||
|
|
{
|
||
|
|
$query = CondolenceExpense::query();
|
||
|
|
|
||
|
|
if (! empty($params['year'])) {
|
||
|
|
$query->inYear((int) $params['year']);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (! empty($params['category']) && $params['category'] !== 'all') {
|
||
|
|
$query->byCategory($params['category']);
|
||
|
|
}
|
||
|
|
|
||
|
|
$stats = $query->selectRaw('
|
||
|
|
COUNT(*) as total_count,
|
||
|
|
COALESCE(SUM(total_amount), 0) as total_amount,
|
||
|
|
COALESCE(SUM(cash_amount), 0) as cash_total,
|
||
|
|
COALESCE(SUM(gift_amount), 0) as gift_total,
|
||
|
|
COALESCE(SUM(CASE WHEN category = ? THEN 1 ELSE 0 END), 0) as congratulation_count,
|
||
|
|
COALESCE(SUM(CASE WHEN category = ? THEN 1 ELSE 0 END), 0) as condolence_count,
|
||
|
|
COALESCE(SUM(CASE WHEN category = ? THEN total_amount ELSE 0 END), 0) as congratulation_amount,
|
||
|
|
COALESCE(SUM(CASE WHEN category = ? THEN total_amount ELSE 0 END), 0) as condolence_amount
|
||
|
|
', [
|
||
|
|
CondolenceExpense::CATEGORY_CONGRATULATION,
|
||
|
|
CondolenceExpense::CATEGORY_CONDOLENCE,
|
||
|
|
CondolenceExpense::CATEGORY_CONGRATULATION,
|
||
|
|
CondolenceExpense::CATEGORY_CONDOLENCE,
|
||
|
|
])->first();
|
||
|
|
|
||
|
|
return [
|
||
|
|
'total_count' => (int) $stats->total_count,
|
||
|
|
'total_amount' => (int) $stats->total_amount,
|
||
|
|
'cash_total' => (int) $stats->cash_total,
|
||
|
|
'gift_total' => (int) $stats->gift_total,
|
||
|
|
'congratulation_count' => (int) $stats->congratulation_count,
|
||
|
|
'condolence_count' => (int) $stats->condolence_count,
|
||
|
|
'congratulation_amount' => (int) $stats->congratulation_amount,
|
||
|
|
'condolence_amount' => (int) $stats->condolence_amount,
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 총금액 자동 계산
|
||
|
|
*/
|
||
|
|
private function calculateTotal(array $data): int
|
||
|
|
{
|
||
|
|
$cash = ($data['has_cash'] ?? false) ? (int) ($data['cash_amount'] ?? 0) : 0;
|
||
|
|
$gift = ($data['has_gift'] ?? false) ? (int) ($data['gift_amount'] ?? 0) : 0;
|
||
|
|
|
||
|
|
return $cash + $gift;
|
||
|
|
}
|
||
|
|
}
|