fix: [production-orders,order] 생산지시 목록 최적화 + 진행률 컬럼 수정 + 중복체크 취소 건 제외

This commit is contained in:
2026-03-18 09:22:41 +09:00
parent 783a41dc82
commit 26e33fdc13
2 changed files with 62 additions and 28 deletions

View File

@@ -28,13 +28,14 @@ public function index(array $params): LengthAwarePaginator
$query = Order::query()
->where('tenant_id', $tenantId)
->whereIn('status_code', self::PRODUCTION_STATUSES)
->with(['client', 'workOrders.process', 'workOrders.assignees.user'])
->with(['client'])
->withCount([
'workOrders' => fn ($q) => $q->whereNotNull('process_id')
->where(fn ($q2) => $q2->whereNull('options->is_auxiliary')
->orWhere('options->is_auxiliary', false)),
'nodes',
]);
])
->withMin('workOrders', 'created_at');
// 검색어 필터
if (! empty($params['search'])) {
@@ -74,24 +75,23 @@ public function index(array $params): LengthAwarePaginator
$perPage = $params['per_page'] ?? 20;
$result = $query->paginate($perPage);
// 작업지시 진행률을 일괄 서브쿼리로 조회 (N+1 방지)
$orderIds = $result->getCollection()->pluck('id')->toArray();
$woProgress = $this->getWorkOrderProgressBatch($orderIds);
// 가공 필드 추가
$result->getCollection()->transform(function (Order $order) {
$minCreatedAt = $order->workOrders->min('created_at');
$result->getCollection()->transform(function (Order $order) use ($woProgress) {
$minCreatedAt = $order->work_orders_min_created_at;
$order->production_ordered_at = $minCreatedAt
? $minCreatedAt->format('Y-m-d')
? \Carbon\Carbon::parse($minCreatedAt)->format('Y-m-d')
: null;
// 개소수 (order_nodes 수)
$order->node_count = $order->nodes_count ?? 0;
// 주요 생산 공정 WO만 (구매품 + 보조 공정 제외)
$productionWOs = $this->filterMainProductionWOs($order->workOrders);
$order->work_order_progress = [
'total' => $productionWOs->count(),
'completed' => $productionWOs->where('status', 'completed')->count()
+ $productionWOs->where('status', 'shipped')->count(),
'in_progress' => $productionWOs->where('status', 'in_progress')->count(),
];
// 주요 생산 공정 WO 진행률 (서브쿼리 결과 사용)
$progress = $woProgress[$order->id] ?? ['total' => 0, 'completed' => 0, 'in_progress' => 0];
$order->work_order_progress = $progress;
// 프론트 탭용 production_status 매핑
$order->production_status = $this->mapProductionStatus($order->status_code);
@@ -109,21 +109,17 @@ public function stats(): array
{
$tenantId = $this->tenantId();
$waiting = Order::where('tenant_id', $tenantId)
->where('status_code', Order::STATUS_IN_PROGRESS)
->count();
$counts = Order::where('tenant_id', $tenantId)
->whereIn('status_code', self::PRODUCTION_STATUSES)
->selectRaw('status_code, COUNT(*) as cnt')
->groupBy('status_code')
->pluck('cnt', 'status_code');
$inProduction = Order::where('tenant_id', $tenantId)
->where('status_code', Order::STATUS_IN_PRODUCTION)
->count();
$completed = Order::where('tenant_id', $tenantId)
->whereIn('status_code', [
Order::STATUS_PRODUCED,
Order::STATUS_SHIPPING,
Order::STATUS_SHIPPED,
])
->count();
$waiting = $counts->get(Order::STATUS_IN_PROGRESS, 0);
$inProduction = $counts->get(Order::STATUS_IN_PRODUCTION, 0);
$completed = $counts->get(Order::STATUS_PRODUCED, 0)
+ $counts->get(Order::STATUS_SHIPPING, 0)
+ $counts->get(Order::STATUS_SHIPPED, 0);
return [
'total' => $waiting + $inProduction + $completed,
@@ -264,6 +260,43 @@ private function extractBomProcessGroups($nodes): array
return array_values($groups);
}
/**
* 주문 ID 목록에 대해 작업지시 진행률을 일괄 조회 (단일 쿼리)
*/
private function getWorkOrderProgressBatch(array $orderIds): array
{
if (empty($orderIds)) {
return [];
}
$rows = \DB::table('work_orders')
->selectRaw('sales_order_id, status, COUNT(*) as cnt')
->whereIn('sales_order_id', $orderIds)
->whereNotNull('process_id')
->where(function ($q) {
$q->whereNull('options->is_auxiliary')
->orWhere('options->is_auxiliary', false);
})
->whereNull('deleted_at')
->groupBy('sales_order_id', 'status')
->get();
$result = [];
foreach ($rows as $row) {
if (! isset($result[$row->sales_order_id])) {
$result[$row->sales_order_id] = ['total' => 0, 'completed' => 0, 'in_progress' => 0];
}
$result[$row->sales_order_id]['total'] += $row->cnt;
if (in_array($row->status, ['completed', 'shipped'])) {
$result[$row->sales_order_id]['completed'] += $row->cnt;
} elseif ($row->status === 'in_progress') {
$result[$row->sales_order_id]['in_progress'] += $row->cnt;
}
}
return $result;
}
/**
* 주요 생산 공정 WO만 필터 (구매품/서비스 + 보조 공정 제외)
*