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:
김보곤
2026-03-19 13:07:20 +09:00
parent 5e5aecd992
commit abb024f0bd
7 changed files with 594 additions and 1 deletions

View File

@@ -0,0 +1,69 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
// 테이블이 없으면 전체 생성 (이전 마이그레이션이 실행됐지만 테이블이 누락된 경우)
if (! Schema::hasTable('condolence_expenses')) {
Schema::create('condolence_expenses', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('tenant_id')->index();
$table->date('event_date')->nullable()->comment('경조사일자');
$table->date('expense_date')->nullable()->comment('지출일자');
$table->string('partner_name', 100)->comment('거래처명/대상자');
$table->string('description', 200)->nullable()->comment('내역');
$table->string('category', 20)->default('congratulation')->comment('구분: congratulation(축의), condolence(부조)');
$table->boolean('has_cash')->default(false)->comment('부조금 여부');
$table->string('cash_method', 30)->nullable()->comment('지출방법: cash, transfer, card');
$table->integer('cash_amount')->default(0)->comment('부조금 금액');
$table->boolean('has_gift')->default(false)->comment('선물 여부');
$table->string('gift_type', 50)->nullable()->comment('선물 종류');
$table->integer('gift_amount')->default(0)->comment('선물 금액');
$table->integer('total_amount')->default(0)->comment('총금액');
$table->json('options')->nullable();
$table->text('memo')->nullable()->comment('비고');
$table->unsignedBigInteger('created_by')->nullable();
$table->unsignedBigInteger('updated_by')->nullable();
$table->unsignedBigInteger('deleted_by')->nullable();
$table->timestamps();
$table->softDeletes();
$table->index(['tenant_id', 'event_date']);
$table->index(['tenant_id', 'category']);
});
return;
}
// 테이블이 있으면 컬럼만 추가
Schema::table('condolence_expenses', function (Blueprint $table) {
if (! Schema::hasColumn('condolence_expenses', 'updated_by')) {
$table->unsignedBigInteger('updated_by')->nullable()->after('created_by');
}
if (! Schema::hasColumn('condolence_expenses', 'deleted_by')) {
$table->unsignedBigInteger('deleted_by')->nullable()->after('updated_by');
}
});
}
public function down(): void
{
// 이 마이그레이션이 테이블 전체를 생성한 경우 삭제하지 않음
// (원본 create 마이그레이션의 down에서 처리)
if (Schema::hasTable('condolence_expenses')) {
Schema::table('condolence_expenses', function (Blueprint $table) {
if (Schema::hasColumn('condolence_expenses', 'updated_by')) {
$table->dropColumn('updated_by');
}
if (Schema::hasColumn('condolence_expenses', 'deleted_by')) {
$table->dropColumn('deleted_by');
}
});
}
}
};