feat: DB 연결 오버라이딩 및 대시보드 통계 위젯 추가

- DB 연결: 로컬/Docker 환경 오버라이딩 설정 (.env)
- 테넌트 위젯: redirect 버그 수정 (TenantSelectorWidget)
- 통계 위젯: 사용자/제품/자재/주문 카드 추가 (StatsOverviewWidget)
- 리소스 한국어화: Product, Material 모델 레이블 추가
- 대시보드: 위젯 등록 및 캐시 최적화

🤖 Generated with [Claude Code](https://claude.ai/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-09-30 23:31:14 +09:00
parent d94ab59fd1
commit bf8036a64b
81 changed files with 22632 additions and 102 deletions

View File

@@ -0,0 +1,339 @@
<?php
namespace Tests\Feature\Design;
use Tests\TestCase;
use App\Models\Design\DesignModel;
use App\Models\Design\ModelParameter;
use App\Models\User;
use App\Models\Tenant;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Auth;
use Laravel\Sanctum\Sanctum;
class ModelParameterTest extends TestCase
{
use RefreshDatabase;
private User $user;
private Tenant $tenant;
private DesignModel $model;
protected function setUp(): void
{
parent::setUp();
// Create test tenant and user
$this->tenant = Tenant::factory()->create();
$this->user = User::factory()->create();
// Associate user with tenant
$this->user->tenants()->attach($this->tenant->id, ['is_active' => true, 'is_default' => true]);
// Create test design model
$this->model = DesignModel::factory()->create([
'tenant_id' => $this->tenant->id,
'code' => 'TEST01',
'name' => 'Test Model',
'is_active' => true
]);
// Authenticate user
Sanctum::actingAs($this->user, ['*']);
Auth::login($this->user);
}
/** @test */
public function can_create_model_parameter()
{
$parameterData = [
'model_id' => $this->model->id,
'parameter_name' => 'width',
'parameter_type' => 'NUMBER',
'is_required' => true,
'default_value' => '800',
'min_value' => 100,
'max_value' => 2000,
'unit' => 'mm',
'description' => 'Width parameter for model',
'sort_order' => 1
];
$response = $this->postJson('/api/v1/design/model-parameters', $parameterData);
$response->assertStatus(201)
->assertJson([
'success' => true,
'message' => 'message.created'
]);
$this->assertDatabaseHas('model_parameters', [
'tenant_id' => $this->tenant->id,
'model_id' => $this->model->id,
'parameter_name' => 'width',
'parameter_type' => 'NUMBER'
]);
}
/** @test */
public function can_list_model_parameters()
{
// Create test parameters
ModelParameter::factory()->count(3)->create([
'tenant_id' => $this->tenant->id,
'model_id' => $this->model->id
]);
$response = $this->getJson('/api/v1/design/model-parameters?model_id=' . $this->model->id);
$response->assertStatus(200)
->assertJson([
'success' => true,
'message' => 'message.fetched'
])
->assertJsonStructure([
'data' => [
'data' => [
'*' => [
'id',
'parameter_name',
'parameter_type',
'is_required',
'default_value',
'min_value',
'max_value',
'unit',
'description',
'sort_order'
]
]
]
]);
}
/** @test */
public function can_show_model_parameter()
{
$parameter = ModelParameter::factory()->create([
'tenant_id' => $this->tenant->id,
'model_id' => $this->model->id,
'parameter_name' => 'height',
'parameter_type' => 'NUMBER'
]);
$response = $this->getJson('/api/v1/design/model-parameters/' . $parameter->id);
$response->assertStatus(200)
->assertJson([
'success' => true,
'message' => 'message.fetched',
'data' => [
'id' => $parameter->id,
'parameter_name' => 'height',
'parameter_type' => 'NUMBER'
]
]);
}
/** @test */
public function can_update_model_parameter()
{
$parameter = ModelParameter::factory()->create([
'tenant_id' => $this->tenant->id,
'model_id' => $this->model->id,
'parameter_name' => 'depth',
'min_value' => 50
]);
$updateData = [
'parameter_name' => 'depth_updated',
'min_value' => 100,
'max_value' => 500,
'description' => 'Updated depth parameter'
];
$response = $this->putJson('/api/v1/design/model-parameters/' . $parameter->id, $updateData);
$response->assertStatus(200)
->assertJson([
'success' => true,
'message' => 'message.updated'
]);
$this->assertDatabaseHas('model_parameters', [
'id' => $parameter->id,
'parameter_name' => 'depth_updated',
'min_value' => 100,
'max_value' => 500
]);
}
/** @test */
public function can_delete_model_parameter()
{
$parameter = ModelParameter::factory()->create([
'tenant_id' => $this->tenant->id,
'model_id' => $this->model->id
]);
$response = $this->deleteJson('/api/v1/design/model-parameters/' . $parameter->id);
$response->assertStatus(200)
->assertJson([
'success' => true,
'message' => 'message.deleted'
]);
$this->assertSoftDeleted('model_parameters', [
'id' => $parameter->id
]);
}
/** @test */
public function validates_parameter_type_and_constraints()
{
// Test NUMBER type with invalid range
$invalidData = [
'model_id' => $this->model->id,
'parameter_name' => 'invalid_width',
'parameter_type' => 'NUMBER',
'min_value' => 1000,
'max_value' => 500 // max < min
];
$response = $this->postJson('/api/v1/design/model-parameters', $invalidData);
$response->assertStatus(422);
// Test SELECT type with options
$validSelectData = [
'model_id' => $this->model->id,
'parameter_name' => 'screen_type',
'parameter_type' => 'SELECT',
'options' => ['FABRIC', 'STEEL', 'PLASTIC'],
'default_value' => 'FABRIC'
];
$response = $this->postJson('/api/v1/design/model-parameters', $validSelectData);
$response->assertStatus(201);
}
/** @test */
public function can_validate_parameter_values()
{
// Create NUMBER parameter
$numberParam = ModelParameter::factory()->create([
'tenant_id' => $this->tenant->id,
'model_id' => $this->model->id,
'parameter_name' => 'test_number',
'parameter_type' => 'NUMBER',
'min_value' => 100,
'max_value' => 1000
]);
// Test valid value
$this->assertTrue($numberParam->validateValue(500));
// Test invalid values
$this->assertFalse($numberParam->validateValue(50)); // below min
$this->assertFalse($numberParam->validateValue(1500)); // above max
$this->assertFalse($numberParam->validateValue('abc')); // non-numeric
// Create SELECT parameter
$selectParam = ModelParameter::factory()->create([
'tenant_id' => $this->tenant->id,
'model_id' => $this->model->id,
'parameter_name' => 'test_select',
'parameter_type' => 'SELECT',
'options' => ['OPTION1', 'OPTION2', 'OPTION3']
]);
// Test valid and invalid options
$this->assertTrue($selectParam->validateValue('OPTION1'));
$this->assertFalse($selectParam->validateValue('INVALID'));
}
/** @test */
public function can_cast_parameter_values()
{
$numberParam = ModelParameter::factory()->create([
'tenant_id' => $this->tenant->id,
'model_id' => $this->model->id,
'parameter_type' => 'NUMBER'
]);
$booleanParam = ModelParameter::factory()->create([
'tenant_id' => $this->tenant->id,
'model_id' => $this->model->id,
'parameter_type' => 'BOOLEAN'
]);
$textParam = ModelParameter::factory()->create([
'tenant_id' => $this->tenant->id,
'model_id' => $this->model->id,
'parameter_type' => 'TEXT'
]);
// Test casting
$this->assertSame(123.5, $numberParam->castValue('123.5'));
$this->assertSame(true, $booleanParam->castValue('1'));
$this->assertSame('test', $textParam->castValue('test'));
}
/** @test */
public function enforces_tenant_isolation()
{
// Create parameter for different tenant
$otherTenant = Tenant::factory()->create();
$otherParameter = ModelParameter::factory()->create([
'tenant_id' => $otherTenant->id
]);
// Should not be able to access other tenant's parameter
$response = $this->getJson('/api/v1/design/model-parameters/' . $otherParameter->id);
$response->assertStatus(404);
// Should not be able to list other tenant's parameters
$response = $this->getJson('/api/v1/design/model-parameters');
$response->assertStatus(200);
$data = $response->json('data.data');
$this->assertEmpty(collect($data)->where('tenant_id', $otherTenant->id));
}
/** @test */
public function can_reorder_parameters()
{
$param1 = ModelParameter::factory()->create([
'tenant_id' => $this->tenant->id,
'model_id' => $this->model->id,
'sort_order' => 1
]);
$param2 = ModelParameter::factory()->create([
'tenant_id' => $this->tenant->id,
'model_id' => $this->model->id,
'sort_order' => 2
]);
$reorderData = [
['id' => $param1->id, 'sort_order' => 2],
['id' => $param2->id, 'sort_order' => 1]
];
$response = $this->postJson('/api/v1/design/model-parameters/reorder', [
'items' => $reorderData
]);
$response->assertStatus(200);
$this->assertDatabaseHas('model_parameters', [
'id' => $param1->id,
'sort_order' => 2
]);
$this->assertDatabaseHas('model_parameters', [
'id' => $param2->id,
'sort_order' => 1
]);
}
}