feat: 견적 단가 자동 적용 기능 추가

- 고객 그룹별 단가 조정 지원
- 견적 생성 시 자동 단가 조회
- 매출단가만 사용 (매입단가는 경고)
This commit is contained in:
2025-10-13 21:52:34 +09:00
parent be36073282
commit a6b06be61d
17 changed files with 3794 additions and 47 deletions

View File

@@ -0,0 +1,46 @@
<?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('client_groups', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('tenant_id')->comment('테넌트 ID');
$table->string('group_code', 30)->comment('그룹 코드');
$table->string('group_name', 100)->comment('그룹명');
$table->decimal('price_rate', 5, 4)->default(1.0000)->comment('가격 배율 (1.0 = 기준가, 0.9 = 90%, 1.1 = 110%)');
$table->tinyInteger('is_active')->default(1)->comment('활성 여부 (1=활성, 0=비활성)');
// 감사 컬럼
$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', 'is_active']);
$table->unique(['tenant_id', 'group_code'], 'uq_client_groups_tenant_code');
// 외래키
$table->foreign('tenant_id')->references('id')->on('tenants')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('client_groups');
}
};

View File

@@ -0,0 +1,36 @@
<?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::table('clients', function (Blueprint $table) {
$table->unsignedBigInteger('client_group_id')
->nullable()
->after('tenant_id')
->comment('고객 그룹 ID (NULL = 기본 그룹)');
$table->index(['tenant_id', 'client_group_id']);
$table->foreign('client_group_id')->references('id')->on('client_groups')->onDelete('set null');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('clients', function (Blueprint $table) {
$table->dropForeign(['client_group_id']);
$table->dropIndex(['tenant_id', 'client_group_id']);
$table->dropColumn('client_group_id');
});
}
};

View File

@@ -0,0 +1,40 @@
<?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::table('price_histories', function (Blueprint $table) {
$table->unsignedBigInteger('client_group_id')
->nullable()
->after('price_type_code')
->comment('고객 그룹 ID (NULL = 기본 가격, 값 있으면 그룹별 차등 가격)');
// 기존 인덱스에 client_group_id 추가
$table->dropIndex('idx_price_histories_main');
$table->index(['tenant_id', 'item_type_code', 'item_id', 'client_group_id', 'started_at'], 'idx_price_histories_main');
$table->foreign('client_group_id')->references('id')->on('client_groups')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('price_histories', function (Blueprint $table) {
$table->dropForeign(['client_group_id']);
$table->dropIndex('idx_price_histories_main');
$table->index(['tenant_id', 'item_type_code', 'item_id', 'started_at'], 'idx_price_histories_main');
$table->dropColumn('client_group_id');
});
}
};