2023-11-01 16:49:00 +08:00
class Api :: Pm :: IssuesController < Api :: Pm :: BaseController
2023-11-01 10:42:27 +08:00
before_action :require_login , except : [ :index ]
2023-11-01 16:49:00 +08:00
before_action :load_project
2023-12-12 09:47:54 +08:00
before_action :load_issue , only : % i [ show update destroy link_index link_issues parent_issues ]
2023-11-02 11:38:52 +08:00
before_action :load_issues , only : % i [ batch_update batch_destroy ]
before_action :check_issue_operate_permission , only : % i [ update destroy ]
2023-11-01 16:49:00 +08:00
2023-11-01 10:42:27 +08:00
def index
@object_result = Api :: V1 :: Issues :: ListService . call ( @project , query_params , current_user )
@total_issues_count = @object_result [ :total_issues_count ]
@opened_issues_count = @object_result [ :opened_issues_count ]
@closed_issues_count = @object_result [ :closed_issues_count ]
2023-12-01 09:19:08 +08:00
@complete_issues_count = @object_result [ :complete_issues_count ]
2023-11-01 10:42:27 +08:00
if params [ :only_name ] . present?
@issues = kaminary_select_paginate (
@object_result [ :data ] . select ( :id , :subject , :project_issues_index , :updated_on , :created_on ) )
else
@issues = kaminari_paginate ( @object_result [ :data ] )
end
2023-11-01 16:49:00 +08:00
render 'api/v1/issues/index'
2023-11-01 10:42:27 +08:00
end
2023-11-07 17:16:25 +08:00
def link_index
2023-11-08 14:45:40 +08:00
pm_issue_type = params [ :pm_issue_type ] || [ 1 , 2 , 3 ]
2023-11-15 14:18:36 +08:00
not_join_id = case params [ :issue_filter_type ]
when 'leaf_issue'
Issue . where ( root_id : @issue . id ) . pluck ( :id )
2023-11-16 15:30:16 +08:00
when 'link_issue'
@issue . pm_links . pluck ( :be_linkable_id )
2023-11-15 14:18:36 +08:00
end
2023-11-07 17:16:25 +08:00
2023-11-15 11:47:17 +08:00
not_join_id << @issue . id
object_issues = Issue . where (
pm_project_id : params [ :pm_project_id ] ,
pm_issue_type : pm_issue_type
2023-11-16 15:13:45 +08:00
) . where . not ( id : not_join_id ) . order ( updated_on : :desc )
2023-11-16 15:08:04 +08:00
object_issues = object_issues . where ( root_id : nil , child_count : 0 ) if params [ :issue_filter_type ] == 'leaf_issue'
2023-11-15 11:47:17 +08:00
@issues = kaminari_paginate ( object_issues )
render 'api/v1/issues/index'
end
2023-12-12 09:47:54 +08:00
def parent_issues
@issues = Issue . where ( pm_project_id : params [ :pm_project_id ] )
. where . not ( id : @issue . id )
. where . not ( id : Issue . full_children_issues ( @issue ) . map { | i | i . id } )
2023-12-12 11:23:38 +08:00
@issues = @issues . where ( pm_issue_type : params [ :pm_issue_type ] ) if params [ :pm_issue_type ] . present?
2023-12-13 11:05:16 +08:00
@issues = @issues . ransack ( id_or_project_issues_index_eq : params [ :keyword ] ) . result . or ( @issues . ransack ( subject_or_description_cont : params [ :keyword ] ) . result ) if params [ :keyword ] . present?
@issues = @issues . reorder ( " #{ issue_sort_by } #{ issue_sort_direction } " )
2023-12-12 09:47:54 +08:00
if params [ :only_name ] . present?
@issues = kaminary_select_paginate (
@issues . select ( :id , :subject , :project_issues_index , :updated_on , :created_on ) )
else
@issues = @issues . includes ( :priority , :issue_status , :user , :show_assigners , :show_issue_tags , :version , :comment_journals )
@issues = kaminari_paginate ( @issues )
end
end
2023-11-01 10:42:27 +08:00
def show
@issue . associate_attachment_container
2023-11-01 16:49:00 +08:00
render 'api/v1/issues/show'
2023-11-01 10:42:27 +08:00
end
def create
2024-08-20 15:56:40 +08:00
@object_result = Api :: Pm :: Issues :: CreateService . call ( @project , issue_params , current_user )
2023-11-01 16:49:00 +08:00
render 'api/v1/issues/create'
2023-11-01 10:42:27 +08:00
end
def update
2024-08-20 15:56:40 +08:00
@object_result = Api :: Pm :: Issues :: UpdateService . call ( @project , @issue , issue_params , current_user )
2023-11-01 16:49:00 +08:00
render 'api/v1/issues/update'
end
def batch_update
2024-08-20 15:56:40 +08:00
@object_result = Api :: Pm :: Issues :: BatchUpdateService . call ( @project , @issues , batch_issue_params , current_user )
2023-11-01 16:49:00 +08:00
if @object_result
render_ok
else
render_error ( '批量更新疑修失败!' )
end
end
def batch_destroy
2023-11-17 15:28:29 +08:00
return render_ok if params [ :ids ] . is_a? ( Array ) && params [ :ids ] . blank?
2024-08-20 15:56:40 +08:00
@object_result = Api :: Pm :: Issues :: BatchDeleteService . call ( @project , @issues , current_user )
2023-11-01 16:49:00 +08:00
if @object_result
render_ok
else
render_error ( '批量删除疑修失败!' )
end
end
def priorities
@priorities = IssuePriority . order ( position : :asc )
@priorities = @priorities . ransack ( name_cont : params [ :keyword ] ) . result if params [ :keyword ]
@priorities = kaminary_select_paginate ( @priorities )
render " api/v1/issues/issue_priorities/index "
end
def tags
2024-01-10 14:03:08 +08:00
# IssueTag.pm_init_data(params[:pm_project_id]) unless $redis_cache.hget("pm_project_init_issue_tags", params[:pm_project_id])
2023-11-02 09:17:32 +08:00
@issue_tags = IssueTag . where ( pm_project_id : params [ :pm_project_id ] ) . reorder ( " #{ tag_sort_by } #{ tag_sort_direction } " )
@issue_tags = @issue_tags . ransack ( name_cont : params [ :keyword ] ) . result if params [ :keyword ] . present?
params [ :only_name ] = true #强制渲染 不走project
@issue_tags = kaminary_select_paginate ( @issue_tags . select ( :id , :name , :color ) )
render " api/v1/issues/issue_tags/index "
2023-11-01 16:49:00 +08:00
end
def statues
2023-12-06 13:59:28 +08:00
@statues = IssueStatus . order ( " position asc " )
2023-11-01 16:49:00 +08:00
@statues = @statues . ransack ( name_cont : params [ :keyword ] ) . result if params [ :keyword ] . present?
@statues = kaminary_select_paginate ( @statues )
render " api/v1/issues/statues/index "
end
2023-11-07 09:54:50 +08:00
2023-11-01 10:42:27 +08:00
def destroy
2024-08-20 15:56:40 +08:00
@object_result = Api :: Pm :: Issues :: DeleteService . call ( @project , @issue , current_user )
2023-11-01 10:42:27 +08:00
if @object_result
render_ok
else
render_error ( '删除疑修失败!' )
end
end
2023-11-01 16:49:00 +08:00
2024-08-07 11:01:24 +08:00
def export
return render_error ( '请输入正确的项目ID.' ) if params [ :pm_project_id ] . blank?
Axlsx :: Package . new do | p |
[ [ 'requirement' , 1 ] , [ 'task' , 2 ] , [ 'bug' , 3 ] ] . each do | type |
p . workbook . add_worksheet ( :name = > type [ 0 ] ) do | sheet |
@issues = Issue . where ( pm_project_id : params [ :pm_project_id ] , pm_issue_type : type [ 1 ] )
2024-09-05 10:29:11 +08:00
sheet . add_row [ " ID " , " 标题* " , " 正文 " , " 创建者* " , " 创建时间 " , " 修改者 " , " 更新时间 " , " 状态 " , " 负责人 " , " 优先级 " , " 标记 " , " 开始时间 " , " 结束时间 " , " 预估工时 " ]
2024-08-07 11:01:24 +08:00
@issues . each do | issue |
2024-08-27 13:42:02 +08:00
sheet . add_row [ issue . id , issue . subject , issue . description , issue . user . try ( :login ) , issue . created_on . strftime ( " %Y-%m-%d %H:%M:%S " ) , issue . changer . try ( :login ) , issue . updated_on . strftime ( " %Y-%m-%d %H:%M:%S " ) , issue . status_id , issue . assigners . pluck ( :login ) . join ( " , " ) , issue . priority_id , issue . issue_tags . pluck ( :name , :color ) . join ( " , " ) , issue . start_date . present? ? issue . start_date . strftime ( " %Y-%m-%d " ) : " " , issue . due_date . present? ? issue . due_date . strftime ( " %Y-%m-%d " ) : " " , issue . time_scale ]
2024-08-07 11:01:24 +08:00
end
end
end
2024-08-27 13:42:02 +08:00
p . workbook . add_worksheet ( :name = > 'leaf_relations' ) do | sheet |
leaf_issues = Issue . where ( pm_project_id : params [ :pm_project_id ] ) . where . not ( root_id : nil )
sheet . add_row [ " ID " , " 父工作项ID " ]
leaf_issues . each do | issue |
sheet . add_row [ issue . id , issue . root_id ]
end
end
p . workbook . add_worksheet ( :name = > 'link_relations' ) do | sheet |
2024-09-12 09:12:24 +08:00
# links = PmLink.joins(:linkable_issue).where(issues: {pm_project_id: params[:pm_project_id]})
2024-09-14 14:18:51 +08:00
links = PmLink . find_by_sql ( " SELECT `pm_links`.* FROM `pm_links` INNER JOIN `issues` ON `issues`.`id` = `pm_links`.`linkable_id` AND `pm_links`.`linkable_type` = 'Issue' WHERE `issues`.`pm_project_id` = #{ params [ :pm_project_id ] } " )
2024-08-27 13:42:02 +08:00
sheet . add_row [ " ID " , " 被关联工作项ID " ]
links . each do | link |
sheet . add_row [ link . linkable_id , link . be_linkable_id ]
end
end
2024-08-07 11:01:24 +08:00
p . serialize ( 'public/导出工作项.xlsx' )
end
2024-08-28 11:55:35 +08:00
send_file ( 'public/导出工作项.xlsx' , :type = > 'application/octet-stream;charset=utf-8' )
2024-08-07 11:01:24 +08:00
end
def import
2024-08-27 13:42:02 +08:00
begin
return render_error ( '请上传正确的文件' ) if params [ :file ] . blank? || ! params [ :file ] . is_a? ( ActionDispatch :: Http :: UploadedFile )
return render_error ( '请输入正确的项目ID.' ) if params [ :pm_project_id ] . blank?
return render_error ( '请输入正确的组织ID.' ) if params [ :organization_id ] . blank?
ActiveRecord :: Base . transaction do
types = { requirement : 1 , task : 2 , bug : 3 }
doc = SimpleXlsxReader . open ( params [ :file ] . tempfile )
doc . sheets . each do | sheet |
case sheet . name
when 'requirement' , 'task' , 'bug'
type = types [ " #{ sheet . name } " . to_sym ]
sheet . rows . each . with_index do | row , index |
next if index == 0
issue = Issue . new ( issue_classify : " issue " , project_id : 0 , pm_project_id : params [ :pm_project_id ] , pm_issue_type : type , tracker_id : Tracker . first . id )
issue . fake_id = row [ 0 ]
issue . subject = row [ 1 ]
issue . description = row [ 2 ]
2024-09-04 09:46:39 +08:00
author = User . find_by ( login : row [ 3 ] )
2024-08-27 13:42:02 +08:00
issue . user = author
issue . created_on = row [ 4 ]
2024-09-04 09:46:39 +08:00
changer = User . find_by ( login : row [ 5 ] )
2024-08-27 13:42:02 +08:00
issue . changer = changer
issue . updated_on = row [ 6 ]
issue . status_id = row [ 7 ] . to_i
if row [ 8 ] . present?
row [ 8 ] . split ( ',' ) . each do | a |
u = User . find_by ( login : a )
next unless u . present?
issue . assigners << u
end
end
issue . priority_id = row [ 9 ]
if row [ 10 ] . present?
row [ 10 ] . split ( ',' ) . each_slice ( 2 ) . to_a . each do | t |
tag = IssueTag . find_by ( project_id : 0 , organization_id : params [ :organization_id ] , name : t [ 0 ] )
if tag . present?
issue . issue_tags << tag
else
tag = IssueTag . create ( project_id : 0 , organization_id : params [ :organization_id ] , name : t [ 0 ] , color : t [ 1 ] )
issue . issue_tags << tag
end
end
end
issue . start_date = row [ 11 ]
issue . due_date = row [ 12 ]
issue . time_scale = row [ 13 ]
issue . save!
end
when 'leaf_relations'
sheet . rows . each . with_index do | row , index |
next if index == 0
children_issue = Issue . where ( fake_id : row [ 0 ] ) . last
parent_issue = Issue . where ( fake_id : row [ 1 ] ) . last
next if children_issue . blank? || parent_issue . blank?
2024-08-27 14:20:35 +08:00
children_issue . root_id = parent_issue . id
children_issue . save ( touch : false )
2024-08-27 13:42:02 +08:00
end
when 'link_relations'
sheet . rows . each . with_index do | row , index |
next if index == 0
link_issue = Issue . where ( fake_id : row [ 0 ] ) . last
be_link_issue = Issue . where ( fake_id : row [ 1 ] ) . last
next if link_issue . blank? || be_link_issue . blank?
PmLink . create! ( linkable_type : 'Issue' , linkable_id : link_issue . id , be_linkable_type : 'Issue' , be_linkable_id : be_link_issue . id )
2024-08-07 11:27:14 +08:00
end
2024-09-04 09:46:39 +08:00
else
return render_error ( '导入失败, 请上传正确格式的excel文件' )
2024-08-07 11:01:24 +08:00
end
2024-08-27 13:42:02 +08:00
2024-08-07 11:01:24 +08:00
end
end
2024-08-27 13:58:35 +08:00
render_ok
2024-08-27 13:42:02 +08:00
rescue
return render_error ( '导入失败, 请上传正确格式的excel文件' )
2024-08-07 11:01:24 +08:00
end
end
2024-12-06 10:41:15 +08:00
def link_issues
2024-12-10 17:20:08 +08:00
children_issues = @issue . pm_issue_type == 1 ? @issue . child_count > 0 ? Issue . where ( id : @issue . id ) : Issue . none : Issue . where ( root_id : @issue . id )
2024-12-06 10:59:10 +08:00
linkable_issues = Issue . where ( id : PmLink . where ( linkable_type : " Issue " , linkable_id : @issue . id ) . pluck ( :be_linkable_id ) )
belinkable_issues = Issue . where ( id : PmLink . where ( be_linkable_type : " Issue " , be_linkable_id : @issue . id ) . pluck ( :linkable_id ) )
2024-12-06 10:41:15 +08:00
full_link_issues_ids = children_issues . pluck ( :id ) | linkable_issues . pluck ( :id ) | belinkable_issues . pluck ( :id )
2024-12-06 11:31:58 +08:00
compare_link_issues_ids = children_issues . pluck ( :id ) | linkable_issues . pluck ( :id ) | belinkable_issues . pluck ( :id )
2024-12-06 10:41:15 +08:00
i = compare_link_issues_ids . count
while i > 0 do
2024-12-11 17:22:27 +08:00
children_issues = Issue . where ( root_id : compare_link_issues_ids )
2024-12-06 10:59:10 +08:00
linkable_issues = Issue . where ( id : PmLink . where ( linkable_type : " Issue " , linkable_id : compare_link_issues_ids ) . pluck ( :be_linkable_id ) )
belinkable_issues = Issue . where ( id : PmLink . where ( be_linkable_type : " Issue " , be_linkable_id : compare_link_issues_ids ) . pluck ( :linkable_id ) )
2024-12-06 10:41:15 +08:00
2024-12-06 11:20:53 +08:00
compare_link_issues_ids = ( children_issues . pluck ( :id ) | linkable_issues . pluck ( :id ) | belinkable_issues . pluck ( :id ) ) - full_link_issues_ids
2024-12-06 10:41:15 +08:00
full_link_issues_ids = full_link_issues_ids | compare_link_issues_ids
i = compare_link_issues_ids . count
end
2024-12-12 09:10:09 +08:00
exclude_issues_ids = [ ]
exclude_issues = Issue . where ( id : full_link_issues_ids ) . where . not ( root_id : nil )
exclude_issues . each do | i |
exclude_issues_ids << i . id if i . pm_issue_type == 1 && full_link_issues_ids . include? ( i . root_id )
2024-12-11 17:22:27 +08:00
end
2024-12-12 09:10:09 +08:00
full_link_issues_ids = full_link_issues_ids - exclude_issues_ids
@requirement_issues = Issue . where ( id :full_link_issues_ids , pm_issue_type : 1 , root_id : nil ) . pm_includes
2024-12-16 16:04:23 +08:00
@task_issues = Issue . where ( id :full_link_issues_ids , pm_issue_type : 2 ) . pm_includes
@bug_issues = Issue . where ( id :full_link_issues_ids , pm_issue_type : 3 ) . pm_includes
2024-12-06 10:41:15 +08:00
end
2023-11-01 10:42:27 +08:00
private
2024-12-06 10:41:15 +08:00
def circle_link_issues ( issue_ids )
if issue_ids . present?
children_issues = Issue . joins ( :parent_issue ) . where ( issues : { id : issue_ids } )
linkable_issues = Issue . where ( id : PmLink . where ( linkable_type : " Issue " , linkable_id : issue_ids ) )
belinkable_issues = Issue . where ( id : PmLink . where ( be_linkable_type : " Issue " , be_linkable_id : issue_ids ) )
return circle_link_issues ( children_issues . pluck ( :id ) )
else
return [ ]
end
end
2023-11-01 16:49:00 +08:00
def check_issue_operate_permission
2023-11-02 14:41:33 +08:00
return if params [ :project_id ] . to_i . zero?
2023-11-01 16:49:00 +08:00
render_forbidden ( '您没有操作权限!' ) unless @project . member? ( current_user ) || current_user . admin? || @issue . user == current_user
end
2023-11-07 17:16:25 +08:00
def load_issue
2025-05-22 14:11:09 +08:00
# return render_parameter_missing if params[:pm_project_id].blank?
2025-05-22 14:13:50 +08:00
@issue = Issue . issue_issue . find_by_id ( params [ :id ] )
2023-11-07 17:16:25 +08:00
render_not_found ( '疑修不存在!' ) if @issue . blank?
end
2025-05-21 09:33:00 +08:00
# def load_issue_by_index
# return render_parameter_missing if params[:pm_project_id].blank? || params[:pm_issue_type].blank? || params[:enterprise_identifier].blank?
# @issue = Issue.find_issues_by_pm(params[:enterprise_identifier], params[:pm_issue_type])
# .find_by(pm_issue_type_index3: params[:index])
# render_not_found('疑修不存在!') if @issue.blank?
# end
2023-11-01 16:49:00 +08:00
def load_issues
return render_error ( '请输入正确的ID数组! ' ) unless params [ :ids ] . is_a? ( Array )
params [ :ids ] . each do | id |
@issue = Issue . find_by ( id : id , pm_project_id : params [ :pm_project_id ] )
2023-11-16 15:08:04 +08:00
return render_not_found ( " ID为 #{ id } 的疑修不存在! " ) if @issue . blank?
2023-11-01 10:42:27 +08:00
end
2023-11-14 10:37:16 +08:00
if params [ :ids ] . blank?
@issues = Issue . where ( pm_project_id : params [ :pm_project_id ] )
else
@issues = Issue . where ( id : params [ :ids ] , pm_project_id : params [ :pm_project_id ] )
end
2023-11-01 10:42:27 +08:00
end
2023-11-01 16:49:00 +08:00
2023-11-01 10:42:27 +08:00
def query_params
params . permit (
:only_name ,
:category ,
:participant_category ,
:keyword , :author_id ,
:milestone_id , :assigner_id ,
2023-12-04 15:46:34 +08:00
:status_id , :priority_id ,
2023-11-01 10:42:27 +08:00
:begin_date , :end_date ,
2024-03-26 17:31:47 +08:00
:update_begin_date , :update_end_date ,
2023-11-07 14:30:28 +08:00
:sort_by , :sort_direction , :root_id ,
2024-01-25 15:49:03 +08:00
:issue_tag_ids , :pm_project_id , :pm_sprint_id , :pm_issue_type , :pm_project_ids ,
2025-05-22 13:52:03 +08:00
:status_ids , :ids , :exclude_ids , :pm_issue_types , :participator_id , :enterprise_identifier
2023-11-01 10:42:27 +08:00
)
end
def issue_params
params . permit (
:status_id , :priority_id , :milestone_id ,
2023-11-07 09:40:50 +08:00
:branch_name , :start_date , :due_date , :time_scale ,
2024-05-27 11:51:51 +08:00
:subject , :description , :blockchain_token_num , :root_subject ,
2023-11-17 17:18:34 +08:00
:pm_project_id , :pm_sprint_id , :pm_issue_type , :root_id , :link_able_id , :project_id ,
2025-05-21 09:33:00 +08:00
:status_msg , :enterprise_identifier ,
2023-11-01 10:42:27 +08:00
issue_tag_ids : [ ] ,
assigner_ids : [ ] ,
attachment_ids : [ ] ,
receivers_login : [ ]
)
end
2023-11-02 09:17:32 +08:00
2023-11-09 14:20:34 +08:00
def batch_issue_params
params . permit (
2024-01-31 08:43:10 +08:00
:status_id , :priority_id , :milestone_id , :pm_sprint_id , :due_date , :pm_issue_type , :root_id , :target_pm_project_id , :project_id ,
2023-11-09 14:20:34 +08:00
:issue_tag_ids = > [ ] ,
:assigner_ids = > [ ] )
end
2023-12-13 11:05:16 +08:00
def issue_sort_by
sort_by = params . fetch ( :sort_by , " updated_on " )
sort_by = Issue . column_names . include? ( sort_by ) ? sort_by : " updated_on "
sort_by
end
def issue_sort_direction
sort_direction = params . fetch ( :sort_direction , " desc " ) . downcase
sort_direction = %w( desc asc ) . include? ( sort_direction ) ? sort_direction : " desc "
sort_direction
end
2023-11-02 09:17:32 +08:00
def tag_sort_by
sort_by = params . fetch ( :sort_by , " created_at " )
sort_by = IssueTag . column_names . include? ( sort_by ) ? sort_by : " created_at "
sort_by
end
def tag_sort_direction
sort_direction = params . fetch ( :sort_direction , " desc " ) . downcase
sort_direction = %w( desc asc ) . include? ( sort_direction ) ? sort_direction : " desc "
sort_direction
end
2023-11-01 10:42:27 +08:00
end