class IssuesController < ApplicationController
  before_action :require_login, except: [:index, :show, :index_chosen, :index_to_name]
  before_action :require_profile_completed, only: [:create]
  before_action :load_project
  before_action :set_user
  before_action :check_menu_authorize, except: [:index_chosen]
  before_action :check_issue_permission
  before_action :operate_issue_permission, only:[:create, :update, :destroy, :clean, :series_update, :copy]
  before_action :check_project_public, only: [:index ,:show, :copy, :index_chosen, :close_issue, :index_to_name]

  before_action :set_issue, only: [:edit, :update, :destroy, :show, :copy, :close_issue, :lock_issue]
  before_action :check_token_enough, :find_atme_receivers, only: [:create, :update]

  include ApplicationHelper
  include TagChosenHelper

  def index
    @user_operate_issue = current_user.present? && current_user.logged? && (current_user.admin || @project.member?(current_user))
    @user_admin_or_member = current_user.present? && current_user.logged? && (current_user.admin || @project.member?(current_user) || @project.is_public?)
    issues = @project.issues.issue_issue.issue_index_includes
    issues = issues.where(is_private: false) unless @user_admin_or_member

    @all_issues = issues
    @filter_issues = @all_issues
    @filter_issues = @filter_issues.where.not(status_id: IssueStatus::CLOSED) if params[:status_type].to_i == IssueStatus::ADD
    @filter_issues = @filter_issues.where(status_id: IssueStatus::CLOSED) if params[:status_type].to_i == IssueStatus::SOLVING
    @filter_issues = @filter_issues.where("issues.subject LIKE ? OR issues.description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present?
    @open_issues = @all_issues.where.not(status_id: IssueStatus::CLOSED)
    @close_issues = @all_issues.where(status_id: IssueStatus::CLOSED)
    scopes = Issues::ListQueryService.call(issues,params.delete_if{|k,v| v.blank?}, "Issue")
    @issues_size = scopes.size
    @assign_to_me = scopes.where(assigned_to_id: current_user&.id)
    @my_published = scopes.where(author_id: current_user&.id)
    @issues = paginate(scopes)

    respond_to do |format|
      format.json
      #导出功能暂未做，可以考虑隐藏
      # format.xlsx{
        # set_export_cookies
        # export_issues(@issues)
        # export_name = "#{@project.name}_issues列表_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
        # render xlsx: "#{export_name.strip}",template: "issues/index.xlsx.axlsx",locals: {table_columns:@table_columns,issues:@export_issues}
      # }
    end
  end

  def index_chosen
    @issue_chosen = issue_left_chosen(@project, nil)
  end

  def index_to_name
    issues_index = params[:index].map(&:to_i)
    exit_index = []
    issues_result = @project.issues.where(project_issues_index:issues_index).map{ |e|
      exit_index << e.project_issues_index
      { 
        id:e.id,
        project_issues_index:e.project_issues_index,
        subject:e.subject
      }
      
    }
    not_exit = issues_index - exit_index
    not_exit.map{|e|
      issues_result << {id: nil,
        project_issues_index:e,
        subject: nil}
    }
    render json: issues_result
  end

  def commit_issues
    issues = @project.issues.issue_issue.includes(:user,:tracker)
    issues = issues.where(is_private: false) unless current_user.present? && (current_user.admin? || @project.member?(current_user))
    @all_issues_size = issues.size
    @open_issues_size = issues.where.not(status_id: 5).size
    @close_issues_size = issues.where(status_id: 5).size
    @normal_issues_size = issues.where(issue_type: "1").size
    @pay_issues_size = issues.where(issue_type: "2").size

    status_type = params[:status_type].to_s

    if status_type.to_s == "1"  #表示开启中的
      issues = issues.where.not(status_id: 5)
    elsif status_type.to_s == "2"   #表示关闭中的
      issues = issues.where(status_id: 5)
    elsif  status_type.to_s == "3"  #普通
      issues = issues.where(issue_type: "1")
    elsif  status_type.to_s == "4"  #悬赏
      issues = issues.where(issue_type: "2")
    end

    @commit_issues = []
    total_commit_issues = {
      name: "合计",
      user_login: nil,
      all_count: issues.size,
      trackers: trackers_size(issues)
    }
    @commit_issues.push(total_commit_issues)

    members = issues.pluck(:assigned_to_id).uniq
    members.each do |m|
      user = User.select(:id, :login, :firstname, :lastname).find(m)
      user_issues = issues.where(assigned_to_id: m)  #指派给
      member_params = {
        name: user.try(:show_real_name),
        user_login: user.try(:login),
        all_count: issues.size,
        trackers: trackers_size(user_issues)
      }
      @commit_issues.push(member_params)
    end

    un_assign = issues.where(assigned_to_id: nil)
    total_commit_issues = {
      name: "未指派",
      user_login: nil,
      all_count: un_assign.size,
      trackers: trackers_size(un_assign)
    }
    @commit_issues.push(total_commit_issues)

  end

  def new
    @issue_chosen = get_associated_data(@project)
  end

  def create
    issue_params = issue_send_params(params)
    Issues::CreateForm.new({subject: issue_params[:subject], description: issue_params[:description].blank? ? issue_params[:description] : issue_params[:description].b}).validate!
    @issue = Issue.new(issue_params)
    @issue.project_issues_index = @project.get_last_project_issues_index + 1
    if @issue.save!
      @project.del_project_issue_cache_delete_count
      SendTemplateMessageJob.perform_later('IssueAssigned', current_user.id, @issue&.id) if Site.has_notice_menu?
      SendTemplateMessageJob.perform_later('ProjectIssue', current_user.id, @issue&.id) if Site.has_notice_menu?
      if params[:attachment_ids].present?
        params[:attachment_ids].each do |id|
          attachment = Attachment.where_id_or_uuid(id).select(:id, :container_id, :container_type)&.first
          unless attachment.blank?
            attachment.container = @issue
            attachment.author_id = current_user.id
            attachment.description = ""
            attachment.save
          end
        end
      end
      if params[:issue_tag_ids].present?
        if params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size > 1
          return normal_status(-1, "最多只能创建一个标记。")
        elsif params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size == 1
          params[:issue_tag_ids].each do |tag|
            IssueTagsRelate.create!(issue_id: @issue.id, issue_tag_id: tag)
          end
        else
          return normal_status(-1, "请输入正确的标记。")
        end 
      end

      if params[:assigned_to_id].present?
        Tiding.create!(user_id: params[:assigned_to_id], trigger_user_id: current_user.id,
                       container_id: @issue.id, container_type: 'Issue',
                       parent_container_id: @project.id, parent_container_type: "Project",
                       tiding_type: 'issue', status: 0)
      end

      #为悬赏任务时, 扣除当前用户的积分
      if params[:issue_type].to_s == "2"
        post_to_chain("minus", params[:token].to_i, current_user.try(:login))
      end

      @issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")

      @issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: ProjectTrend::CLOSE) if params[:status_id].to_i == 5


      Rails.logger.info "[ATME] maybe to at such users: #{@atme_receivers.pluck(:login)}"
      AtmeService.call(current_user, @atme_receivers, @issue) if @atme_receivers.size > 0
      # 新增时向grimoirelab推送事件
      IssueWebhookJob.set(wait: 5.seconds).perform_later(@issue.id)

      if Site.has_blockchain? && @project.use_blockchain
        # author: zxh
        # 扣除发起人的token
        if @issue.blockchain_token_num > 0
          Blockchain::CreateIssue.call(user_id: @issue.author_id, project_id: @issue.project_id, token_num: @issue.blockchain_token_num)
        end

        # 调用上链API存证
        push_activity_2_blockchain("issue_create", @issue)
      end

      render json: {status: 0, message: "创建成功", id: @issue.id}
    else
      normal_status(-1, "创建失败")
    end
  rescue Exception => exception
    puts exception.message
    normal_status(-1, exception.message)
  end

  def edit
    # @issue_chosen = issue_left_chosen(@project, @issue.id)
    @issue_attachments = @issue.attachments
  end

  def update
    issue_params = issue_send_params(params).except(:issue_classify, :author_id, :project_id)
    return normal_status(-1, "您没有权限修改token") if @issue.will_save_change_to_token? && @issue.user_id != current_user&.id
    last_token = @issue.token
    last_status_id = @issue.status_id
    @issue&.issue_tags_relates&.destroy_all if params[:issue_tag_ids].blank?
    if params[:issue_tag_ids].present? 
      if params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size > 1
        return normal_status(-1, "最多只能创建一个标记。")
      elsif params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size == 1
        @issue&.issue_tags_relates&.destroy_all
        params[:issue_tag_ids].each do |tag|
          next if tag == [""]
          IssueTagsRelate.create!(issue_id: @issue.id, issue_tag_id: tag)
        end
      else
        return normal_status(-1, "请输入正确的标记。")
      end 
    end

    issue_files = params[:attachment_ids]
    change_files = false
    issue_file_ids = []

    if issue_files.present?
      change_files = true
      issue_files.each do |id|
        attachment = Attachment.where_id_or_uuid(id).select(:id, :container_id, :container_type)&.first
        unless attachment.blank?
          attachment.container = @issue
          attachment.author_id = current_user.id
          attachment.description = ""
          attachment.save
        end
      end
    end
      

      # if params[:issue_tag_ids].present?
      #   issue_current_tags = @issue&.issue_tags&.select(:id)&.pluck(:id)
      #   new_tag_ids = params[:issue_tag_ids] - issue_current_tags
      #   old_tag_ids = issue_current_tags - params[:issue_tag_ids]
      #   if old_tag_ids.size > 0
      #     @issue.issue_tags_relates.where(issue_tag_id: old_tag_ids).delete_all
      #   end
      #   if new_tag_ids.size > 0
      #     new_tag_ids.each do |tag|
      #       IssueTagsRelate.create(issue_id: @issue.id, issue_tag_id: tag)
      #     end
      #   end
      # end

    if @issue.issue_type.to_s == "2" &&  params[:status_id].to_i == 5 && @issue.author_id != current_user.try(:id)
      normal_status(-1, "不允许修改为关闭状态")
    else
      issue_params = issue_send_params(params).except(:issue_classify, :author_id, :project_id)
      Issues::UpdateForm.new({subject: issue_params[:subject], description: issue_params[:description].blank? ? issue_params[:description] : issue_params[:description].b}).validate!
      if @issue.update_attributes(issue_params)
        if @issue&.pull_request.present?
          SendTemplateMessageJob.perform_later('PullRequestChanged', current_user.id, @issue&.pull_request&.id, @issue.previous_changes.slice(:assigned_to_id, :priority_id, :fixed_version_id, :issue_tags_value)) if Site.has_notice_menu?
          SendTemplateMessageJob.perform_later('PullRequestAssigned', current_user.id, @issue&.pull_request&.id ) if @issue.previous_changes[:assigned_to_id].present? && Site.has_notice_menu?
        else
          previous_changes = @issue.previous_changes.slice(:status_id, :assigned_to_id, :tracker_id, :priority_id, :fixed_version_id, :done_ratio, :issue_tags_value, :branch_name)
          if @issue.previous_changes[:start_date].present? 
            previous_changes.merge!(start_date: [@issue.previous_changes[:start_date][0].to_s,  @issue.previous_changes[:start_date][1].to_s])
          end
          if @issue.previous_changes[:due_date].present? 
            previous_changes.merge!(due_date: [@issue.previous_changes[:due_date][0].to_s,  @issue.previous_changes[:due_date][1].to_s])
          end
          if @issue.previous_changes[:status_id].present? && @issue.previous_changes[:status_id][1] == 5
            @issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: ProjectTrend::CLOSE)
          end
          if @issue.previous_changes[:status_id].present? && @issue.previous_changes[:status_id][0] == 5
            @issue.project_trends.where(action_type: ProjectTrend::CLOSE).destroy_all
          end
          SendTemplateMessageJob.perform_later('IssueChanged', current_user.id, @issue&.id, previous_changes) if Site.has_notice_menu?
          SendTemplateMessageJob.perform_later('IssueAssigned', current_user.id, @issue&.id) if @issue.previous_changes[:assigned_to_id].present? && Site.has_notice_menu?
        end
        if params[:status_id].to_i == 5  #任务由非关闭状态到关闭状态时
          @issue.issue_times.update_all(end_time: Time.now)
          # @issue.update_closed_issues_count_in_project!
          if @issue.issue_type.to_s == "2" && last_status_id != 5
            if @issue.assigned_to_id.present? && last_status_id == 3 #只有当用户完成100%时，才给token
              post_to_chain("add", @issue.token, @issue.get_assign_user.try(:login))
            else
              post_to_chain("add", @issue.token, @issue.user.try(:login))
            end
          end
        end

        if @issue.issue_type.to_s == "2" && @issue.status_id != 5 && @issue.saved_change_to_attribute("token")
          #表示修改token值
          change_token = last_token - @issue.token
          change_type = change_token > 0 ? "add" : "minus"
          post_to_chain(change_type, change_token.abs, current_user.try(:login))
        end
        @issue.create_journal_detail(change_files, issue_files, issue_file_ids, current_user&.id) if @issue.previous_changes.present? 

        Rails.logger.info "[ATME] maybe to at such users: #{@atme_receivers.pluck(:login)}"
        AtmeService.call(current_user, @atme_receivers, @issue) if @atme_receivers.size > 0

        normal_status(0, "更新成功")
      else
        normal_status(-1, "更新失败")
      end

   
    end
  rescue Exception => exception
    puts exception.message
    normal_status(-1, exception.message)
  end

  def show
    @user_permission = current_user.present? && current_user.logged? && (@project.member?(current_user) || current_user.admin? || @issue.user == current_user)
    @issue_attachments = @issue.attachments
    @issue_user = @issue.user
    @issue_assign_to = @issue.get_assign_user
    @join_users = join_users(@issue)
    @issue.associate_attachment_container
    #总耗时
    # cost_time(@issue)

    # #被依赖
    # @be_depended_issues_array = be_depended_issues(@issue)

    # #依赖于
    # depended_issues(@issue)
  end

  def destroy
    begin
      issue_type = @issue.issue_type
      status_id = @issue.status_id
      token = @issue.token
      login =  @issue.user.try(:login)
      SendTemplateMessageJob.perform_later('IssueDeleted', current_user.id, @issue&.subject, @issue.assigned_to_id, @issue.author_id) if Site.has_notice_menu?
      if @issue.destroy
        @project.incre_project_issue_cache_delete_count
        if issue_type == "2" && status_id != 5
          post_to_chain("add", token, login)
        end
        return normal_status(0, "删除成功")
      else
        return normal_status(-1, "删除失败")
      end
    rescue => exception
      Rails.logger.info("#########_______exception.message_________##########{exception.message}")
      normal_status(-1, "删除失败")
    end
  end

  def clean
    issue_ids = params[:ids]
    issues = Issue.where(id: issue_ids, issue_type: "1")
    if issues.present?
      issues.find_each do |i|
        SendTemplateMessageJob.perform_later('IssueDeleted', current_user.id, i&.subject, i.assigned_to_id, i.author_id) if Site.has_notice_menu?
      end
      if issues.destroy_all
        normal_status(0, "删除成功")
      else
        normal_status(-1, "删除失败")
      end
    else
      normal_status(-1, "请选择任务")
    end
  end

  def series_update
    update_hash = {}
    update_hash.merge!(assigned_to_id: params[:assigned_to_id]) if params[:assigned_to_id].present?
    update_hash.merge!(fixed_version_id: params[:fixed_version_id]) if params[:fixed_version_id].present?
    # update_hash.merge!(status_id: params[:status_id]) if params[:status_id].present?
    if params[:status_id].present?
      status_id = params[:status_id].to_i
      update_hash.merge!(status_id: status_id)
      done_ratio = nil
      case status_id
      when 1
        done_ratio = 0
      when 3
        done_ratio = 100
      end
      update_hash.merge!(done_ratio: done_ratio) if done_ratio
    end
    # update_hash = params[:issue]
    issue_ids = params[:ids]
    if issue_ids.present?
      issues = Issue.where(id: issue_ids)
      if update_hash.blank?
        normal_status(-1, "请选择批量更新内容")
      elsif issues&.update(update_hash)
        issues.each do |i|
          i.create_journal_detail(false, [], [], current_user&.id) if i.previous_changes.present?
          previous_changes = i.previous_changes.slice(:status_id, :assigned_to_id, :tracker_id, :priority_id, :fixed_version_id, :done_ratio, :issue_tags_value, :branch_name)
          if i.previous_changes[:start_date].present? 
            previous_changes.merge!(start_date: [i.previous_changes[:start_date][0].to_s,  i.previous_changes[:start_date][1].to_s])
          end
          if i.previous_changes[:due_date].present? 
            previous_changes.merge!(due_date: [i.previous_changes[:due_date][0].to_s,  i.previous_changes[:due_date][1].to_s])
          end
          if i.previous_changes[:status_id].present? && i.previous_changes[:status_id][1] == 5
            i.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: ProjectTrend::CLOSE)
          end
          if i.previous_changes[:status_id].present? && i.previous_changes[:status_id][0] == 5
            i.project_trends.where(action_type: ProjectTrend::CLOSE).destroy_all
          end
          SendTemplateMessageJob.perform_later('IssueChanged', current_user.id, i&.id, previous_changes) if Site.has_notice_menu?
          SendTemplateMessageJob.perform_later('IssueAssigned', current_user.id, i&.id) if i.previous_changes[:assigned_to_id].present? && Site.has_notice_menu?
        end
        normal_status(0, "批量更新成功")
      else
        normal_status(-1, "批量更新失败")
      end
    else
      normal_status(-1, "请选择任务")
    end
  end

  def copy
    @new_issue = @issue.dup
    @new_issue.author_id = current_user.id
    if @new_issue.save
      SendTemplateMessageJob.perform_later('IssueAssigned', current_user.id, @new_issue&.id) if Site.has_notice_menu?
      SendTemplateMessageJob.perform_later('ProjectIssue', current_user.id, @new_issue&.id) if Site.has_notice_menu?
      issue_tags = @issue.issue_tags.pluck(:id)
      if issue_tags.present?
        issue_tags.each do |tag|
          IssueTagsRelate.create!(issue_id: @new_issue.id, issue_tag_id: tag)
        end
      end
      @new_issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
      @status = 1
    else
      @status = -1
    end
  end

  def close_issue
    type = params[:status_id].to_i || 5

    if type == 5
      message = "关闭"
      old_message = "重新开启"
    else
      message = "重新开启"
      old_message = "关闭"
    end
    if @issue.update_attribute(:status_id, type)
      if type == 5
        @issue&.project_trends&.update_all(action_type: "close")
        @issue.issue_times.update_all(end_time: Time.now)
        if @issue.issue_type.to_s == "2"
          post_to_chain("add", @issue.token, @issue.get_assign_user.try(:login))
        end
        if @issue.issue_classify.to_s == "pull_request"
          @issue&.pull_request&.update_attribute(:status, 2)
        end
      else
        @issue&.project_trends&.update_all(action_type: "create")
        if @issue.issue_classify.to_s == "pull_request"
          @issue&.pull_request&.update_attribute(:status, 0)
        end
      end
      if @issue.issue_classify == "issue"
        close_message = "close_issue"
      else
        close_message = "close_pr"
      end
      @issue.custom_journal_detail(close_message,old_message, "#{message}", current_user&.id)
      normal_status(0, message)
    else
      normal_status(-1, "操作失败")
    end
  end

  def lock_issue
    if @issue.user == current_user || current_user.admin?
      type = (params[:lock_type].to_i == 1)
      if @issue.update_attribute(:is_lock, type)
        if type
          @issue.custom_journal_detail("lock_issue","", "因为#{params[:lock_reason].present? ? params[:lock_reason].to_s : "某种原因"}而锁定，并将对话限制为协作者", current_user&.id)
        else
          @issue.custom_journal_detail("unlock_issue","", "解除锁定", current_user&.id)
        end
        normal_status(0, "操作成功")
      else
        normal_status(-1, "操作失败")
      end
    else
      normal_status(-1, "您没有权限")
    end

  end

  private
  def set_user
    @user = @project&.owner
  end

  def check_project_public
    unless @project.is_public || @project.member?(current_user) || current_user.admin? || (@project.user_id == current_user.id)
      return render_forbidden
    end
  end

  def set_issue
    @issue = Issue.find_by_id(params[:id])
    if @issue.blank?
      return render_not_found
    elsif !(@project.is_public || (current_user.present? && (@project.member?(current_user) || current_user&.admin? || (@project.user_id == current_user&.id))))
      return render_forbidden
    end
  end

  def check_issue_permission
    unless @project.is_public || (current_user.present? && (@project.member?(current_user) || current_user&.admin? || (@project.user_id == current_user&.id)))
      return render_forbidden
    end
  end

  def operate_issue_permission
    @issue = Issue.find_by_id(params[:id]) unless @issue.present?
    return render_forbidden("您没有权限进行此操作.") unless current_user.present? && current_user.logged? && (current_user.admin? || @project.member?(current_user) || (@project.is_public && @issue.nil?) || (@project.is_public && @issue.present? && @issue.author_id == current_user.id))
  end

  def export_issues(issues)
    @table_columns = %w(ID 类型 标题	描述	状态	指派给	优先级 标签 发布人 创建时间 里程碑 开始时间 截止时间 完成度 分类 金额 属于)
    @export_issues = []
    issues.each do |i|
      issue_array = [i.id, i.tracker.try(:name), i.subject, i.description, i.issue_status.try(:name),i.get_assign_user.try(:show_real_name),
                     i.priority.try(:name), i.get_issue_tags_name, i.user.try(:show_real_name), format_time(i.created_on), i.version.try(:name),
                     i.start_date.to_s, i.due_date.to_s, i.done_ratio.to_s + "%", i.issue_type == "2" ? "悬赏" : "普通", i.token.to_s, i.issue_classify]

      @export_issues.push(issue_array)

    end
  end

  def trackers_size(issues)
    trackers_id = Tracker.pluck(:id,:name)
    tracker_array = []
    trackers_id.each do |t|
      tracker_info = {
        id: t[0],
        name: t[1],
        issues_count: issues.issues_count(t[0])
      }
      tracker_array.push(tracker_info)
    end
    tracker_array
  end

  def issue_send_params(params)
    {
        subject: params[:subject],
        description: params[:description],
        is_private: params[:is_private] || false,
        assigned_to_id: params[:assigned_to_id],
        tracker_id: params[:tracker_id],
        status_id: params[:status_id],
        priority_id: params[:priority_id],
        fixed_version_id: params[:fixed_version_id],
        start_date: params[:start_date].to_s.to_date || Time.current.to_date,
        due_date: params[:due_date].to_s.to_date,
        estimated_hours: params[:estimated_hours],
        done_ratio: params[:done_ratio],
        issue_type: params[:issue_type] || "1",
        token: params[:token],
        issue_tags_value: params[:issue_tag_ids].present? ? params[:issue_tag_ids].join(",") : "",
        closed_on: (params[:status_id].to_i == 5) ? Time.current : nil,
        branch_name: params[:branch_name].to_s,
        issue_classify: "issue",
        author_id: current_user.id,
        project_id: @project.id,
        blockchain_token_num: params[:blockchain_token_num]
      }
  end

  def post_to_chain(type, amount,login)
    change_params = {
      type: type,
      chain_params: {
        amount: amount,
        reponame: @project.try(:identifier),
        username: login
      }
    }
    PostChainJob.perform_later(change_params)
  end

  def check_token_enough
    if params[:issue_type].to_s == "2" && (@issue.blank? || (@issue.present? && @issue.author_id == current_user.try(:id)))
      return normal_status(-1, "悬赏的奖金必须大于0") if params[:token].to_i == 0
      query_params = {
        type: "query",
        chain_params: {
          reponame: @project.try(:identifier),
          username: current_user.try(:login)
        }
      }
      response = Gitea::Chain::ChainGetService.new(query_params).call
      return normal_status(-1, "获取token失败，请稍后重试") if response.status != 200
      return normal_status(-1, "您的token值不足") if JSON.parse(response.body)["balance"].to_i < params[:token].to_i
    end
  end

  def check_menu_authorize
    return render_not_found unless @project.has_menu_permission("issues")
  end
end
