feat(API): 견적-주문 연동 필드 및 마이그레이션 추가
- Order, OrderItem 모델에 견적 연동 필드 추가 - Quote 모델에 order_id 관계 추가 - QuoteService 개선 - 관련 마이그레이션 파일 추가 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace App\Services\Quote;
|
||||
|
||||
use App\Models\Orders\Order;
|
||||
use App\Models\Orders\OrderItem;
|
||||
use App\Models\Quote\Quote;
|
||||
use App\Models\Quote\QuoteItem;
|
||||
use App\Models\Quote\QuoteRevision;
|
||||
@@ -369,7 +371,10 @@ public function convertToOrder(int $id): Quote
|
||||
$tenantId = $this->tenantId();
|
||||
$userId = $this->apiUserId();
|
||||
|
||||
$quote = Quote::where('tenant_id', $tenantId)->find($id);
|
||||
$quote = Quote::where('tenant_id', $tenantId)
|
||||
->with(['items', 'client'])
|
||||
->find($id);
|
||||
|
||||
if (! $quote) {
|
||||
throw new NotFoundHttpException(__('error.quote_not_found'));
|
||||
}
|
||||
@@ -378,19 +383,69 @@ public function convertToOrder(int $id): Quote
|
||||
throw new BadRequestHttpException(__('error.quote_not_convertible'));
|
||||
}
|
||||
|
||||
return DB::transaction(function () use ($quote, $userId) {
|
||||
// TODO: 수주(Order) 생성 로직 구현
|
||||
// $order = $this->orderService->createFromQuote($quote);
|
||||
return DB::transaction(function () use ($quote, $userId, $tenantId) {
|
||||
// 수주번호 생성
|
||||
$orderNo = $this->generateOrderNumber($tenantId);
|
||||
|
||||
// 수주 마스터 생성
|
||||
$order = Order::createFromQuote($quote, $orderNo);
|
||||
$order->created_by = $userId;
|
||||
$order->save();
|
||||
|
||||
// 수주 상세 품목 생성
|
||||
$serialIndex = 1;
|
||||
foreach ($quote->items as $quoteItem) {
|
||||
$orderItem = OrderItem::createFromQuoteItem($quoteItem, $order->id, $serialIndex);
|
||||
$orderItem->created_by = $userId;
|
||||
$orderItem->save();
|
||||
$serialIndex++;
|
||||
}
|
||||
|
||||
// 수주 합계 재계산
|
||||
$order->load('items');
|
||||
$order->recalculateTotals();
|
||||
$order->save();
|
||||
|
||||
// 견적 상태 변경
|
||||
$quote->update([
|
||||
'status' => Quote::STATUS_CONVERTED,
|
||||
'order_id' => $order->id,
|
||||
'updated_by' => $userId,
|
||||
]);
|
||||
|
||||
return $quote->refresh()->load(['items', 'client']);
|
||||
return $quote->refresh()->load(['items', 'client', 'order']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 수주번호 생성
|
||||
* 형식: ORD-YYMMDD-NNN (예: ORD-260105-001)
|
||||
*/
|
||||
private function generateOrderNumber(int $tenantId): string
|
||||
{
|
||||
$dateStr = now()->format('ymd');
|
||||
$prefix = "ORD-{$dateStr}-";
|
||||
|
||||
$lastOrder = Order::withTrashed()
|
||||
->where('tenant_id', $tenantId)
|
||||
->where('order_no', 'like', $prefix.'%')
|
||||
->orderBy('order_no', 'desc')
|
||||
->first();
|
||||
|
||||
$sequence = 1;
|
||||
if ($lastOrder) {
|
||||
$parts = explode('-', $lastOrder->order_no);
|
||||
if (count($parts) >= 3) {
|
||||
$lastSeq = (int) end($parts);
|
||||
$sequence = $lastSeq + 1;
|
||||
}
|
||||
}
|
||||
|
||||
$seqStr = str_pad((string) $sequence, 3, '0', STR_PAD_LEFT);
|
||||
|
||||
return "{$prefix}{$seqStr}";
|
||||
}
|
||||
|
||||
/**
|
||||
* 견적 품목 생성
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user