fix: 견적 선택 다이얼로그에서 수주 전환된 견적 제외
- QuoteIndexRequest: for_order 파라미터 추가
- Quote 모델: orders() HasMany 관계 추가 (Order.quote_id 기준)
- QuoteService: for_order 필터링 로직 추가
- whereNull('order_id') - 빠른 체크
- whereDoesntHave('orders') - 이중 체크
- OrderService: 수주 생성 시 견적 상태를 converted로 업데이트
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -33,6 +33,12 @@ protected function prepareForValidation(): void
|
||||
'with_items' => filter_var($this->with_items, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE),
|
||||
]);
|
||||
}
|
||||
|
||||
if ($this->has('for_order')) {
|
||||
$this->merge([
|
||||
'for_order' => filter_var($this->for_order, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
@@ -58,6 +64,7 @@ public function rules(): array
|
||||
'sort_by' => 'nullable|in:registration_date,quote_number,client_name,total_amount,status,created_at',
|
||||
'sort_order' => 'nullable|in:asc,desc',
|
||||
'with_items' => 'nullable|boolean', // 수주 전환용 품목 포함 여부
|
||||
'for_order' => 'nullable|boolean', // 수주 전환용: 이미 수주가 생성된 견적 제외
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -175,13 +175,22 @@ public function item(): BelongsTo
|
||||
}
|
||||
|
||||
/**
|
||||
* 전환된 수주
|
||||
* 전환된 수주 (Quote.order_id 기준)
|
||||
*/
|
||||
public function order(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Order::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 이 견적을 참조하는 수주들 (Order.quote_id 기준)
|
||||
* 수주 전환 여부 확인 시 사용
|
||||
*/
|
||||
public function orders(): HasMany
|
||||
{
|
||||
return $this->hasMany(Order::class, 'quote_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 현장설명회 (자동생성 시 연결)
|
||||
*/
|
||||
|
||||
@@ -26,11 +26,21 @@ public function index(array $params)
|
||||
$clientId = $params['client_id'] ?? null;
|
||||
$dateFrom = $params['date_from'] ?? null;
|
||||
$dateTo = $params['date_to'] ?? null;
|
||||
$forWorkOrder = filter_var($params['for_work_order'] ?? false, FILTER_VALIDATE_BOOLEAN);
|
||||
|
||||
$query = Order::query()
|
||||
->where('tenant_id', $tenantId)
|
||||
->with(['client:id,name', 'items', 'quote:id,quote_number']);
|
||||
|
||||
// 작업지시 생성 가능한 수주만 필터링
|
||||
if ($forWorkOrder) {
|
||||
// 1. DRAFT(등록) 상태만 (생산지시 전)
|
||||
$query->where('status_code', Order::STATUS_DRAFT);
|
||||
|
||||
// 2. 작업지시가 아직 없는 수주만
|
||||
$query->whereDoesntHave('workOrders');
|
||||
}
|
||||
|
||||
// 검색어 (수주번호, 현장명, 거래처명)
|
||||
if ($q !== '') {
|
||||
$query->where(function ($qq) use ($q) {
|
||||
@@ -40,8 +50,8 @@ public function index(array $params)
|
||||
});
|
||||
}
|
||||
|
||||
// 상태 필터
|
||||
if ($status !== null) {
|
||||
// 상태 필터 (for_work_order와 함께 사용시 무시)
|
||||
if ($status !== null && ! $forWorkOrder) {
|
||||
$query->where('status_code', $status);
|
||||
}
|
||||
|
||||
@@ -393,6 +403,13 @@ public function createFromQuote(int $quoteId, array $data = [])
|
||||
$order->refresh();
|
||||
$order->recalculateTotals()->save();
|
||||
|
||||
// 견적 상태를 '수주전환완료'로 변경
|
||||
$quote->update([
|
||||
'status' => Quote::STATUS_CONVERTED,
|
||||
'order_id' => $order->id,
|
||||
'updated_by' => $userId,
|
||||
]);
|
||||
|
||||
return $order->load(['client:id,name', 'items', 'quote:id,quote_number']);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -40,9 +40,18 @@ public function index(array $params): LengthAwarePaginator
|
||||
$sortBy = $params['sort_by'] ?? 'registration_date';
|
||||
$sortOrder = $params['sort_order'] ?? 'desc';
|
||||
$withItems = filter_var($params['with_items'] ?? false, FILTER_VALIDATE_BOOLEAN);
|
||||
$forOrder = filter_var($params['for_order'] ?? false, FILTER_VALIDATE_BOOLEAN);
|
||||
|
||||
$query = Quote::query()->where('tenant_id', $tenantId);
|
||||
|
||||
// 수주 전환용 조회: 아직 수주가 생성되지 않은 견적만
|
||||
if ($forOrder) {
|
||||
// 1. Quote.order_id가 null인 것 (빠른 체크)
|
||||
$query->whereNull('order_id');
|
||||
// 2. Orders 테이블에 해당 quote_id가 없는 것 (이중 체크, 인덱스 있음)
|
||||
$query->whereDoesntHave('orders');
|
||||
}
|
||||
|
||||
// items 포함 (수주 전환용)
|
||||
if ($withItems) {
|
||||
$query->with(['items', 'client:id,name,contact_person,phone']);
|
||||
|
||||
Reference in New Issue
Block a user