feat: Phase 6.1 악성채권 추심관리 API 구현

- 테이블 3개: bad_debts, bad_debt_documents, bad_debt_memos
- 모델 3개: BadDebt, BadDebtDocument, BadDebtMemo
- BadDebtService: CRUD, 요약 통계, 서류/메모 관리
- API 엔드포인트 11개 (목록, 등록, 상세, 수정, 삭제, 토글, 서류/메모 CRUD)
- Swagger 문서 작성 완료
This commit is contained in:
2025-12-19 15:57:04 +09:00
parent 3020026abf
commit c0af888bed
15 changed files with 1498 additions and 1 deletions

View File

@@ -0,0 +1,47 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('bad_debts', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('tenant_id')->comment('테넌트 ID');
$table->unsignedBigInteger('client_id')->comment('거래처 ID');
$table->decimal('debt_amount', 15, 2)->default(0)->comment('채권 금액');
$table->string('status', 20)->default('collecting')->comment('상태: collecting(추심중), legal_action(법적조치), recovered(회수완료), bad_debt(대손처리)');
$table->integer('overdue_days')->default(0)->comment('연체일수');
$table->unsignedBigInteger('assigned_user_id')->nullable()->comment('담당자 ID');
$table->date('occurred_at')->nullable()->comment('악성채권 발생일');
$table->date('closed_at')->nullable()->comment('악성채권 종료일');
$table->boolean('is_active')->default(true)->comment('설정 활성화 여부');
$table->json('options')->nullable()->comment('추가 옵션 JSON');
$table->unsignedBigInteger('created_by')->nullable()->comment('생성자 ID');
$table->unsignedBigInteger('updated_by')->nullable()->comment('수정자 ID');
$table->unsignedBigInteger('deleted_by')->nullable()->comment('삭제자 ID');
$table->timestamps();
$table->softDeletes();
$table->index('tenant_id');
$table->index('client_id');
$table->index('status');
$table->index('is_active');
$table->index(['tenant_id', 'status']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('bad_debts');
}
};

View File

@@ -0,0 +1,38 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('bad_debt_documents', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('bad_debt_id')->comment('악성채권 ID');
$table->string('document_type', 50)->comment('서류 유형: business_license(사업자등록증), tax_invoice(세금계산서), additional(추가서류)');
$table->unsignedBigInteger('file_id')->comment('파일 ID');
$table->timestamps();
$table->index('bad_debt_id');
$table->index('document_type');
$table->foreign('bad_debt_id')
->references('id')
->on('bad_debts')
->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('bad_debt_documents');
}
};

View File

@@ -0,0 +1,37 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('bad_debt_memos', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('bad_debt_id')->comment('악성채권 ID');
$table->text('content')->comment('메모 내용');
$table->unsignedBigInteger('created_by')->nullable()->comment('작성자 ID');
$table->timestamps();
$table->index('bad_debt_id');
$table->foreign('bad_debt_id')
->references('id')
->on('bad_debts')
->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('bad_debt_memos');
}
};