feat: 작업지시 목록에 assigned_to_me 필터 추가
- 작업자 화면에서 나에게 배정된 작업만 조회하도록 지원 - 주 담당자(assignee_id) 또는 공동 담당자(assignees) 모두 포함 - 프론트엔드 WorkerScreen의 assigned_to_me=1 파라미터 처리 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -32,6 +32,7 @@ public function index(array $params)
|
||||
$status = $params['status'] ?? null;
|
||||
$processId = $params['process_id'] ?? null;
|
||||
$assigneeId = $params['assignee_id'] ?? null;
|
||||
$assignedToMe = isset($params['assigned_to_me']) && $params['assigned_to_me'];
|
||||
$teamId = $params['team_id'] ?? null;
|
||||
$scheduledFrom = $params['scheduled_from'] ?? null;
|
||||
$scheduledTo = $params['scheduled_to'] ?? null;
|
||||
@@ -63,6 +64,15 @@ public function index(array $params)
|
||||
$query->where('assignee_id', $assigneeId);
|
||||
}
|
||||
|
||||
// 나에게 배정된 작업만 필터 (주 담당자 또는 공동 담당자)
|
||||
if ($assignedToMe) {
|
||||
$userId = $this->apiUserId();
|
||||
$query->where(function ($q) use ($userId) {
|
||||
$q->where('assignee_id', $userId)
|
||||
->orWhereHas('assignees', fn ($aq) => $aq->where('user_id', $userId));
|
||||
});
|
||||
}
|
||||
|
||||
// 팀 필터
|
||||
if ($teamId !== null) {
|
||||
$query->where('team_id', $teamId);
|
||||
@@ -329,8 +339,12 @@ public function destroy(int $id)
|
||||
|
||||
/**
|
||||
* 상태 변경
|
||||
*
|
||||
* @param int $id 작업지시 ID
|
||||
* @param string $status 변경할 상태
|
||||
* @param array|null $resultData 완료 시 결과 데이터 (선택)
|
||||
*/
|
||||
public function updateStatus(int $id, string $status)
|
||||
public function updateStatus(int $id, string $status, ?array $resultData = null)
|
||||
{
|
||||
$tenantId = $this->tenantId();
|
||||
$userId = $this->apiUserId();
|
||||
@@ -357,36 +371,106 @@ public function updateStatus(int $id, string $status)
|
||||
);
|
||||
}
|
||||
|
||||
$oldStatus = $workOrder->status;
|
||||
$workOrder->status = $status;
|
||||
$workOrder->updated_by = $userId;
|
||||
return DB::transaction(function () use ($workOrder, $status, $resultData, $tenantId, $userId) {
|
||||
$oldStatus = $workOrder->status;
|
||||
$workOrder->status = $status;
|
||||
$workOrder->updated_by = $userId;
|
||||
|
||||
// 상태에 따른 타임스탬프 업데이트
|
||||
switch ($status) {
|
||||
case WorkOrder::STATUS_IN_PROGRESS:
|
||||
$workOrder->started_at = $workOrder->started_at ?? now();
|
||||
break;
|
||||
case WorkOrder::STATUS_COMPLETED:
|
||||
$workOrder->completed_at = now();
|
||||
break;
|
||||
case WorkOrder::STATUS_SHIPPED:
|
||||
$workOrder->shipped_at = now();
|
||||
break;
|
||||
// 상태에 따른 타임스탬프 업데이트
|
||||
switch ($status) {
|
||||
case WorkOrder::STATUS_IN_PROGRESS:
|
||||
$workOrder->started_at = $workOrder->started_at ?? now();
|
||||
break;
|
||||
case WorkOrder::STATUS_COMPLETED:
|
||||
$workOrder->completed_at = now();
|
||||
// 모든 품목에 결과 데이터 저장
|
||||
$this->saveItemResults($workOrder, $resultData, $userId);
|
||||
break;
|
||||
case WorkOrder::STATUS_SHIPPED:
|
||||
$workOrder->shipped_at = now();
|
||||
break;
|
||||
}
|
||||
|
||||
$workOrder->save();
|
||||
|
||||
// 상태 변경 감사 로그
|
||||
$this->auditLogger->log(
|
||||
$tenantId,
|
||||
self::AUDIT_TARGET,
|
||||
$workOrder->id,
|
||||
'status_changed',
|
||||
['status' => $oldStatus],
|
||||
['status' => $status]
|
||||
);
|
||||
|
||||
return $workOrder->load(['assignee:id,name', 'assignees.user:id,name', 'team:id,name', 'process:id,process_name,process_code']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 작업지시 품목에 결과 데이터 저장
|
||||
*/
|
||||
private function saveItemResults(WorkOrder $workOrder, ?array $resultData, int $userId): void
|
||||
{
|
||||
$items = $workOrder->items;
|
||||
$lotNo = $this->generateLotNo($workOrder);
|
||||
|
||||
foreach ($items as $item) {
|
||||
$itemResult = [
|
||||
'completed_at' => now()->toDateTimeString(),
|
||||
'good_qty' => $item->quantity, // 기본값: 지시수량 전체가 양품
|
||||
'defect_qty' => 0,
|
||||
'defect_rate' => 0,
|
||||
'lot_no' => $lotNo,
|
||||
'is_inspected' => false,
|
||||
'is_packaged' => false,
|
||||
'worker_id' => $userId,
|
||||
'memo' => null,
|
||||
];
|
||||
|
||||
// 개별 품목 결과 데이터가 있으면 병합
|
||||
if ($resultData && isset($resultData['items'][$item->id])) {
|
||||
$itemResult = array_merge($itemResult, $resultData['items'][$item->id]);
|
||||
// 불량률 재계산
|
||||
$totalQty = ($itemResult['good_qty'] ?? 0) + ($itemResult['defect_qty'] ?? 0);
|
||||
$itemResult['defect_rate'] = $totalQty > 0
|
||||
? round(($itemResult['defect_qty'] / $totalQty) * 100, 2)
|
||||
: 0;
|
||||
}
|
||||
|
||||
// 품목 상태도 완료로 변경
|
||||
$item->status = WorkOrderItem::STATUS_COMPLETED;
|
||||
$options = $item->options ?? [];
|
||||
$options['result'] = $itemResult;
|
||||
$item->options = $options;
|
||||
$item->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* LOT 번호 생성
|
||||
*/
|
||||
private function generateLotNo(WorkOrder $workOrder): string
|
||||
{
|
||||
$date = now()->format('ymd');
|
||||
$prefix = 'KD-SA';
|
||||
|
||||
// 오늘 날짜의 마지막 LOT 번호 조회
|
||||
$lastLotNo = WorkOrderItem::where('tenant_id', $workOrder->tenant_id)
|
||||
->whereNotNull('options->result->lot_no')
|
||||
->where('options->result->lot_no', 'like', "{$prefix}-{$date}-%")
|
||||
->orderByDesc('id')
|
||||
->value('options->result->lot_no');
|
||||
|
||||
if ($lastLotNo) {
|
||||
// 마지막 번호에서 시퀀스 추출 후 증가
|
||||
$parts = explode('-', $lastLotNo);
|
||||
$seq = (int) end($parts) + 1;
|
||||
} else {
|
||||
$seq = 1;
|
||||
}
|
||||
|
||||
$workOrder->save();
|
||||
|
||||
// 상태 변경 감사 로그
|
||||
$this->auditLogger->log(
|
||||
$tenantId,
|
||||
self::AUDIT_TARGET,
|
||||
$workOrder->id,
|
||||
'status_changed',
|
||||
['status' => $oldStatus],
|
||||
['status' => $status]
|
||||
);
|
||||
|
||||
return $workOrder->load(['assignee:id,name', 'assignees.user:id,name', 'team:id,name', 'process:id,process_name,process_code']);
|
||||
return sprintf('%s-%s-%02d', $prefix, $date, $seq);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user