feat: [finance] 경조사비 관리 API 구현
- Model: CondolenceExpense (BelongsToTenant, Auditable, SoftDeletes) - Service: CRUD + summary 통계 (total_amount 자동 계산) - Controller: 6개 엔드포인트 (목록/등록/상세/수정/삭제/통계) - FormRequest: Store/Update 검증 규칙 분리 - Route: /api/v1/condolence-expenses - Migration: updated_by, deleted_by 컬럼 추가
This commit is contained in:
138
app/Models/Tenants/CondolenceExpense.php
Normal file
138
app/Models/Tenants/CondolenceExpense.php
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Tenants;
|
||||
|
||||
use App\Traits\Auditable;
|
||||
use App\Traits\BelongsToTenant;
|
||||
use App\Traits\ModelTrait;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class CondolenceExpense extends Model
|
||||
{
|
||||
use Auditable, BelongsToTenant, ModelTrait, SoftDeletes;
|
||||
|
||||
protected $table = 'condolence_expenses';
|
||||
|
||||
// 카테고리 상수
|
||||
public const CATEGORY_CONGRATULATION = 'congratulation';
|
||||
|
||||
public const CATEGORY_CONDOLENCE = 'condolence';
|
||||
|
||||
public const CATEGORY_LABELS = [
|
||||
self::CATEGORY_CONGRATULATION => '축의',
|
||||
self::CATEGORY_CONDOLENCE => '부조',
|
||||
];
|
||||
|
||||
// 지출방법 상수
|
||||
public const CASH_METHOD_CASH = 'cash';
|
||||
|
||||
public const CASH_METHOD_TRANSFER = 'transfer';
|
||||
|
||||
public const CASH_METHOD_CARD = 'card';
|
||||
|
||||
public const CASH_METHOD_LABELS = [
|
||||
self::CASH_METHOD_CASH => '현금',
|
||||
self::CASH_METHOD_TRANSFER => '계좌이체',
|
||||
self::CASH_METHOD_CARD => '카드',
|
||||
];
|
||||
|
||||
protected $fillable = [
|
||||
'tenant_id',
|
||||
'event_date',
|
||||
'expense_date',
|
||||
'partner_name',
|
||||
'description',
|
||||
'category',
|
||||
'has_cash',
|
||||
'cash_method',
|
||||
'cash_amount',
|
||||
'has_gift',
|
||||
'gift_type',
|
||||
'gift_amount',
|
||||
'total_amount',
|
||||
'options',
|
||||
'memo',
|
||||
'created_by',
|
||||
'updated_by',
|
||||
'deleted_by',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'event_date' => 'date',
|
||||
'expense_date' => 'date',
|
||||
'has_cash' => 'boolean',
|
||||
'has_gift' => 'boolean',
|
||||
'cash_amount' => 'integer',
|
||||
'gift_amount' => 'integer',
|
||||
'total_amount' => 'integer',
|
||||
'options' => 'array',
|
||||
];
|
||||
|
||||
protected $appends = [
|
||||
'category_label',
|
||||
'cash_method_label',
|
||||
];
|
||||
|
||||
/**
|
||||
* 카테고리 라벨
|
||||
*/
|
||||
public function getCategoryLabelAttribute(): string
|
||||
{
|
||||
return self::CATEGORY_LABELS[$this->category] ?? $this->category;
|
||||
}
|
||||
|
||||
/**
|
||||
* 지출방법 라벨
|
||||
*/
|
||||
public function getCashMethodLabelAttribute(): ?string
|
||||
{
|
||||
if (! $this->cash_method) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return self::CASH_METHOD_LABELS[$this->cash_method] ?? $this->cash_method;
|
||||
}
|
||||
|
||||
/**
|
||||
* 등록자
|
||||
*/
|
||||
public function creator(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(\App\Models\User::class, 'created_by');
|
||||
}
|
||||
|
||||
/**
|
||||
* 카테고리 필터 스코프
|
||||
*/
|
||||
public function scopeByCategory($query, string $category)
|
||||
{
|
||||
return $query->where('category', $category);
|
||||
}
|
||||
|
||||
/**
|
||||
* 연도 필터 스코프
|
||||
*/
|
||||
public function scopeInYear($query, int $year)
|
||||
{
|
||||
return $query->whereYear('event_date', $year);
|
||||
}
|
||||
|
||||
/**
|
||||
* options 헬퍼
|
||||
*/
|
||||
public function getOption(string $key, $default = null)
|
||||
{
|
||||
return data_get($this->options, $key, $default);
|
||||
}
|
||||
|
||||
public function setOption(string $key, $value): self
|
||||
{
|
||||
$options = $this->options ?? [];
|
||||
data_set($options, $key, $value);
|
||||
$this->options = $options;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user