- CRUD 테스트 5개 (생성/상세/수정/삭제/404) - 상태전이 테스트 4개 (미배정→대기→준비→진행→완료) - 담당자 배정 테스트 1개 - 공정단계/자재 조회 테스트 3개 - 목록/통계/인증 테스트 3개
300 lines
8.7 KiB
PHP
300 lines
8.7 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature\Production;
|
|
|
|
use App\Models\Orders\Client;
|
|
use App\Models\Orders\Order;
|
|
use App\Models\Process;
|
|
use App\Models\Production\WorkOrder;
|
|
use App\Models\Production\WorkOrderItem;
|
|
use Tests\TestCase;
|
|
|
|
class WorkOrderApiTest extends TestCase
|
|
{
|
|
private Process $process;
|
|
|
|
private Order $order;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
$this->setUpAuthenticatedUser();
|
|
|
|
// 공정
|
|
$this->process = Process::create([
|
|
'tenant_id' => $this->tenant->id,
|
|
'process_code' => 'PRC-'.uniqid(),
|
|
'process_name' => '스크린 조립',
|
|
'process_type' => 'assembly',
|
|
'is_active' => true,
|
|
'created_by' => $this->user->id,
|
|
'updated_by' => $this->user->id,
|
|
]);
|
|
|
|
// 수주 (작업지시의 부모)
|
|
$client = Client::create([
|
|
'tenant_id' => $this->tenant->id,
|
|
'name' => '테스트 거래처',
|
|
'client_code' => 'CLI'.uniqid(),
|
|
'is_active' => true,
|
|
'created_by' => $this->user->id,
|
|
]);
|
|
|
|
$this->order = Order::create([
|
|
'tenant_id' => $this->tenant->id,
|
|
'order_no' => 'ORD-'.uniqid(),
|
|
'order_type_code' => Order::TYPE_ORDER,
|
|
'status_code' => Order::STATUS_CONFIRMED,
|
|
'client_id' => $client->id,
|
|
'client_name' => $client->name,
|
|
'quantity' => 10,
|
|
'supply_amount' => 1000000,
|
|
'tax_amount' => 100000,
|
|
'total_amount' => 1100000,
|
|
'created_by' => $this->user->id,
|
|
'updated_by' => $this->user->id,
|
|
]);
|
|
}
|
|
|
|
// ==================== 목록/통계 조회 ====================
|
|
|
|
public function test_작업지시_목록_조회(): void
|
|
{
|
|
$this->createWorkOrder();
|
|
|
|
$response = $this->api('get', '/api/v1/work-orders');
|
|
|
|
$this->assertApiPaginated($response);
|
|
}
|
|
|
|
public function test_작업지시_통계_조회(): void
|
|
{
|
|
$this->createWorkOrder();
|
|
|
|
$response = $this->api('get', '/api/v1/work-orders/stats');
|
|
|
|
$response->assertStatus(200)
|
|
->assertJsonStructure(['success', 'data']);
|
|
}
|
|
|
|
// ==================== CRUD ====================
|
|
|
|
public function test_작업지시_생성_성공(): void
|
|
{
|
|
$response = $this->api('post', '/api/v1/work-orders', [
|
|
'process_id' => $this->process->id,
|
|
'sales_order_id' => $this->order->id,
|
|
'assignee_ids' => [$this->user->id],
|
|
'priority' => 5,
|
|
'scheduled_date' => now()->addDays(7)->format('Y-m-d'),
|
|
'memo' => '테스트 작업지시',
|
|
]);
|
|
|
|
$response->assertStatus(200);
|
|
$this->assertTrue($response->json('success'));
|
|
|
|
$this->assertDatabaseHas('work_orders', [
|
|
'process_id' => $this->process->id,
|
|
'sales_order_id' => $this->order->id,
|
|
'tenant_id' => $this->tenant->id,
|
|
]);
|
|
}
|
|
|
|
public function test_작업지시_상세_조회(): void
|
|
{
|
|
$wo = $this->createWorkOrder();
|
|
|
|
$response = $this->api('get', "/api/v1/work-orders/{$wo->id}");
|
|
|
|
$this->assertApiSuccess($response);
|
|
|
|
$data = $response->json('data');
|
|
$this->assertEquals($wo->id, $data['id']);
|
|
}
|
|
|
|
public function test_작업지시_수정(): void
|
|
{
|
|
$wo = $this->createWorkOrder();
|
|
|
|
$response = $this->api('put', "/api/v1/work-orders/{$wo->id}", [
|
|
'memo' => '수정된 메모',
|
|
'priority' => 1,
|
|
]);
|
|
|
|
$response->assertStatus(200);
|
|
|
|
$this->assertDatabaseHas('work_orders', [
|
|
'id' => $wo->id,
|
|
'memo' => '수정된 메모',
|
|
]);
|
|
}
|
|
|
|
public function test_작업지시_삭제(): void
|
|
{
|
|
$wo = $this->createWorkOrder();
|
|
|
|
$response = $this->api('delete', "/api/v1/work-orders/{$wo->id}");
|
|
|
|
$response->assertStatus(200);
|
|
|
|
$this->assertSoftDeleted('work_orders', ['id' => $wo->id]);
|
|
}
|
|
|
|
public function test_존재하지_않는_작업지시_조회시_404(): void
|
|
{
|
|
$response = $this->api('get', '/api/v1/work-orders/999999');
|
|
|
|
$response->assertStatus(404);
|
|
}
|
|
|
|
// ==================== 상태 전이 ====================
|
|
|
|
public function test_상태_미배정에서_대기로_변경(): void
|
|
{
|
|
$wo = $this->createWorkOrder(WorkOrder::STATUS_UNASSIGNED);
|
|
|
|
$response = $this->api('patch', "/api/v1/work-orders/{$wo->id}/status", [
|
|
'status' => WorkOrder::STATUS_PENDING,
|
|
]);
|
|
|
|
$response->assertStatus(200);
|
|
|
|
$this->assertDatabaseHas('work_orders', [
|
|
'id' => $wo->id,
|
|
'status' => WorkOrder::STATUS_PENDING,
|
|
]);
|
|
}
|
|
|
|
public function test_상태_대기에서_준비중으로_변경(): void
|
|
{
|
|
$wo = $this->createWorkOrder(WorkOrder::STATUS_PENDING);
|
|
|
|
$response = $this->api('patch', "/api/v1/work-orders/{$wo->id}/status", [
|
|
'status' => WorkOrder::STATUS_WAITING,
|
|
]);
|
|
|
|
$response->assertStatus(200);
|
|
|
|
$this->assertDatabaseHas('work_orders', [
|
|
'id' => $wo->id,
|
|
'status' => WorkOrder::STATUS_WAITING,
|
|
]);
|
|
}
|
|
|
|
public function test_상태_준비중에서_진행중으로_변경(): void
|
|
{
|
|
$wo = $this->createWorkOrder(WorkOrder::STATUS_WAITING);
|
|
|
|
$response = $this->api('patch', "/api/v1/work-orders/{$wo->id}/status", [
|
|
'status' => WorkOrder::STATUS_IN_PROGRESS,
|
|
]);
|
|
|
|
$response->assertStatus(200);
|
|
|
|
$this->assertDatabaseHas('work_orders', [
|
|
'id' => $wo->id,
|
|
'status' => WorkOrder::STATUS_IN_PROGRESS,
|
|
]);
|
|
}
|
|
|
|
public function test_상태_진행중에서_완료로_변경(): void
|
|
{
|
|
$wo = $this->createWorkOrder(WorkOrder::STATUS_IN_PROGRESS);
|
|
|
|
$response = $this->api('patch', "/api/v1/work-orders/{$wo->id}/status", [
|
|
'status' => WorkOrder::STATUS_COMPLETED,
|
|
]);
|
|
|
|
$response->assertStatus(200);
|
|
|
|
$this->assertDatabaseHas('work_orders', [
|
|
'id' => $wo->id,
|
|
'status' => WorkOrder::STATUS_COMPLETED,
|
|
]);
|
|
}
|
|
|
|
// ==================== 담당자 배정 ====================
|
|
|
|
public function test_담당자_배정(): void
|
|
{
|
|
$wo = $this->createWorkOrder(WorkOrder::STATUS_UNASSIGNED);
|
|
|
|
$response = $this->api('patch', "/api/v1/work-orders/{$wo->id}/assign", [
|
|
'assignee_id' => $this->user->id,
|
|
]);
|
|
|
|
$response->assertStatus(200);
|
|
|
|
$this->assertDatabaseHas('work_orders', [
|
|
'id' => $wo->id,
|
|
'assignee_id' => $this->user->id,
|
|
]);
|
|
}
|
|
|
|
// ==================== 공정 단계 ====================
|
|
|
|
public function test_공정_단계_진행_조회(): void
|
|
{
|
|
$wo = $this->createWorkOrder();
|
|
|
|
$response = $this->api('get', "/api/v1/work-orders/{$wo->id}/step-progress");
|
|
|
|
$response->assertStatus(200)
|
|
->assertJsonStructure(['success', 'data']);
|
|
}
|
|
|
|
// ==================== 자재 ====================
|
|
|
|
public function test_자재_목록_조회(): void
|
|
{
|
|
$wo = $this->createWorkOrder();
|
|
|
|
$response = $this->api('get', "/api/v1/work-orders/{$wo->id}/materials");
|
|
|
|
$response->assertStatus(200)
|
|
->assertJsonStructure(['success', 'data']);
|
|
}
|
|
|
|
public function test_자재_투입_이력_조회(): void
|
|
{
|
|
$wo = $this->createWorkOrder();
|
|
|
|
$response = $this->api('get', "/api/v1/work-orders/{$wo->id}/material-input-history");
|
|
|
|
$response->assertStatus(200)
|
|
->assertJsonStructure(['success', 'data']);
|
|
}
|
|
|
|
// ==================== 인증 ====================
|
|
|
|
public function test_미인증_요청시_401(): void
|
|
{
|
|
$response = $this->withHeaders([
|
|
'X-API-KEY' => $this->apiKey,
|
|
'Accept' => 'application/json',
|
|
])->getJson('/api/v1/work-orders');
|
|
|
|
$response->assertStatus(401);
|
|
}
|
|
|
|
// ==================== 헬퍼 ====================
|
|
|
|
private function createWorkOrder(string $status = WorkOrder::STATUS_UNASSIGNED): WorkOrder
|
|
{
|
|
return WorkOrder::create([
|
|
'tenant_id' => $this->tenant->id,
|
|
'work_order_no' => 'WO-'.uniqid(),
|
|
'sales_order_id' => $this->order->id,
|
|
'process_id' => $this->process->id,
|
|
'project_name' => '테스트 프로젝트',
|
|
'status' => $status,
|
|
'priority' => 5,
|
|
'scheduled_date' => now()->addDays(7),
|
|
'memo' => '테스트 작업지시',
|
|
'is_active' => true,
|
|
'created_by' => $this->user->id,
|
|
'updated_by' => $this->user->id,
|
|
]);
|
|
}
|
|
}
|