class IssueWorkflowsController < ApplicationController before_action :find_issue before_action :find_or_create_workflow_state def show @steps = @workflow_state.custom_workflow.workflow_steps.ordered @current_step = @workflow_state.current_step end def next_step if @workflow_state.can_proceed?(User.current) selected_assignee_id = params[:assignee_id] if @workflow_state.proceed!(User.current, selected_assignee_id) flash[:notice] = '다음 단계로 이동했습니다.' else flash[:error] = '다음 단계로 이동할 수 없습니다.' end else flash[:error] = '이 단계를 완료할 권한이 없습니다.' end redirect_to issue_path(@issue) end def prev_step if @workflow_state.can_go_back?(User.current) if @workflow_state.go_back!(User.current) flash[:notice] = '이전 단계로 되돌렸습니다.' else flash[:error] = '이전 단계로 이동할 수 없습니다.' end else flash[:error] = '이전 단계로 되돌릴 권한이 없습니다.' end redirect_to issue_path(@issue) end def complete current_step = @workflow_state.current_step if current_step&.is_end && (User.current.admin? || current_step.assignee?(User.current)) @issue.init_journal(User.current, "워크플로우 완료 처리") @issue.status_id = 5 # 완료 상태 if @issue.save(validate: false) @workflow_state.update(completed_at: Time.current, completed_by: User.current) flash[:notice] = '이슈가 완료 처리되었습니다.' else flash[:error] = '완료 처리에 실패했습니다.' end else flash[:error] = '완료 처리 권한이 없습니다.' end redirect_to issue_path(@issue) end def reject current_step = @workflow_state.current_step reason = params[:reason].to_s.strip unless current_step && !current_step.is_start && (User.current.admin? || current_step.assignee?(User.current)) flash[:error] = '반려 권한이 없습니다.' redirect_to issue_path(@issue) return end if reason.blank? flash[:error] = '반려 사유를 입력해주세요.' redirect_to issue_path(@issue) return end # 항상 최초 단계로 반려 first_step = @workflow_state.custom_workflow.workflow_steps.ordered.first if first_step # 이력 남기기 @issue.init_journal(User.current, "[반려] #{current_step.name} → #{first_step.name}\n사유: #{reason}") # 상태 변경 (최초 단계의 상태로) if first_step.issue_status_id.present? @issue.status_id = first_step.issue_status_id end # 담당자 변경 - 개인 사용자일 때만, 그룹/부서는 미지정 user_assignees = first_step.workflow_step_assignees.where(assignee_type: 'user') if user_assignees.any? @issue.assigned_to_id = user_assignees.first.assignee_id elsif first_step.workflow_step_assignees.any? @issue.assigned_to_id = nil end @issue.save(validate: false) @workflow_state.update(current_step: first_step, completed_at: nil, completed_by: nil) flash[:notice] = "#{first_step.name} 단계로 반려되었습니다." else flash[:error] = '반려 대상 단계를 찾을 수 없습니다.' end redirect_to issue_path(@issue) end def skip_step # 관리자만 단계 건너뛰기 가능 unless User.current.admin? flash[:error] = '관리자만 단계를 건너뛸 수 있습니다.' redirect_to issue_path(@issue) return end current_step = @workflow_state.current_step target_step_id = params[:target_step_id] reason = params[:reason].to_s.strip if target_step_id.blank? flash[:error] = '이동할 단계를 선택해주세요.' redirect_to issue_path(@issue) return end target_step = WorkflowStep.find_by(id: target_step_id) if target_step && target_step.custom_workflow_id == @workflow_state.custom_workflow_id # 이력 남기기 note = "[단계 건너뛰기] #{current_step&.name || '(시작)'} → #{target_step.name}" note += "\n사유: #{reason}" if reason.present? @issue.init_journal(User.current, note) # 상태 변경 if target_step.issue_status_id.present? @issue.status_id = target_step.issue_status_id end # 담당자 변경 - 개인 사용자일 때만, 그룹/부서는 미지정 user_assignees = target_step.workflow_step_assignees.where(assignee_type: 'user') if user_assignees.any? @issue.assigned_to_id = user_assignees.first.assignee_id elsif target_step.workflow_step_assignees.any? @issue.assigned_to_id = nil end @issue.save(validate: false) @workflow_state.update(current_step: target_step, completed_at: nil, completed_by: nil) flash[:notice] = "#{target_step.name} 단계로 이동했습니다." else flash[:error] = '이동할 단계를 찾을 수 없습니다.' end redirect_to issue_path(@issue) end private def find_issue @issue = Issue.find(params[:issue_id]) rescue ActiveRecord::RecordNotFound render_404 end def find_or_create_workflow_state @workflow_state = IssueWorkflowState.find_by(issue_id: @issue.id) unless @workflow_state workflow = CustomWorkflow.find_for_issue(@issue) if workflow @workflow_state = IssueWorkflowState.create!( issue: @issue, custom_workflow: workflow, current_step: workflow.start_step, started_at: Time.current ) else flash[:warning] = '이 이슈에 적용할 워크플로우가 없습니다.' redirect_to issue_path(@issue) end end end end