forked from Trustie/forgeplus
【苏州大学大数据】项目托管/协同开发新增申请加入审核功能(#10197)
This commit is contained in:
parent
a71c834fda
commit
2e8ca4ee9a
|
|
@ -29,7 +29,7 @@ class ApplicationController < ActionController::Base
|
|||
DCODES = %W(2 3 4 5 6 7 8 9 a b c f e f g h i j k l m n o p q r s t u v w x y z)
|
||||
OPENKEY = "79e33abd4b6588941ab7622aed1e67e8"
|
||||
|
||||
helper_method :current_user, :base_url
|
||||
helper_method :current_user, :base_url, :judge_file_type_by_suffix
|
||||
|
||||
# 所有请求必须合法签名
|
||||
def check_sign
|
||||
|
|
@ -883,4 +883,28 @@ class ApplicationController < ActionController::Base
|
|||
HotSearchKeyword.add(keyword)
|
||||
end
|
||||
|
||||
# 根据文件后缀判断文件类型,默认使用文本打开渲染
|
||||
def judge_file_type_by_suffix filename
|
||||
return "other" if filename.blank?
|
||||
suffix = File.basename(filename).split(".").last
|
||||
return "other" if suffix.blank?
|
||||
case suffix.downcase
|
||||
when "py", "h", "c", "cpp", "cc", "java", "php", "html", "css", "scss", "go", "r", "graphql", "swift", "xml", "yaml", "json", "lua",
|
||||
"scheme", "less", "ini", "coffee", "litcoffee", "js", "cs", "kt", "md", "sql", "m", "mm", "pas", "perl", "perl", "ejs",
|
||||
"pl", "rb", "rs", "rust", "sh", "makefile", "circ", "readme", "yml", "sml", "thy", "conf", "txt", "gitignore", "in", "cu",
|
||||
"gemfile", "scala", "m", "net", "l", "v", "config", "properties", "log", "htm", "cnf", "hex", "bat", "asm", "hex", "bash",
|
||||
"ts", "tsx", "sass", "jsx", "jsp", "gitkeep", "sv", "hql", "y", "jj", "pls", "sol", "ignore", "ctrl", "vue", "tex", "bib",
|
||||
"cls", "bst", "log", "toc", "sty", "g4", "sy", "cfg", "s", "ll", "mml", "hpp","api", "vhdl", "lex" then "txt"
|
||||
when "jpg", "jpeg", "png", "gif", "webp", "bmp" then "image"
|
||||
when "avi", "mp4", "mov" then "video"
|
||||
when "mp3", "wav", "ogg" then "audio"
|
||||
when "pptm", "pptx", "ppt", "pot", "pps", "ppa", "potx", "ppsx", "ppam", "pptm", "potm", "ppsm", "doc", "docx",
|
||||
"dot", "dotx", "docm", "dotm", "xls", "xlsx", "xlt", "xla", "xltx", "xlsm", "xltm", "xlam", "xlsb" then "office"
|
||||
when "tex" then "latex"
|
||||
when "pdf" then "pdf"
|
||||
else
|
||||
"other"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,12 +2,58 @@ class AppliedProjectsController < ApplicationController
|
|||
before_action :require_login
|
||||
def create
|
||||
@applied_project = Projects::ApplyJoinService.call(current_user, applied_params)
|
||||
if @applied_project.class.to_s != "AppliedProject"
|
||||
render_ok({data: @applied_project})
|
||||
end
|
||||
rescue Projects::ApplyJoinService::Error => ex
|
||||
render_error(ex.message)
|
||||
end
|
||||
|
||||
#审核列表
|
||||
def index
|
||||
project = Project.find_by(identifier: params[:project_identifier])
|
||||
tip_exception(-1, "该项目不存在~") if project.blank?
|
||||
status = params[:status] || 1
|
||||
if status.to_i == 1
|
||||
status = ["common"]
|
||||
elsif status.to_i == 2
|
||||
status = ["accepted", "refused"]
|
||||
end
|
||||
applied_projects = project.applied_projects
|
||||
if status.present?
|
||||
applied_projects = applied_projects.where(status: status)
|
||||
end
|
||||
keyword = params[:keyword].to_s.strip
|
||||
if keyword.present?
|
||||
applied_projects = applied_projects.joins(user: :user_extension).where("CONCAT(users.lastname, users.firstname) LIKE :keyword OR users.phone LIKE :keyword", keyword: "%#{params[:keyword].to_s.strip}%")
|
||||
end
|
||||
@count = applied_projects.size
|
||||
@applied_projects = paginate applied_projects.order(updated_at: :DESC)
|
||||
end
|
||||
|
||||
#审核
|
||||
def verify
|
||||
tip_exception(-1, "参数值有误") if !["agree","reject"].include?(params[:verify_status])
|
||||
applied_project = AppliedProject.find_by(id: params[:id])
|
||||
tip_exception(-1, '该数据不存在') if applied_project.blank?
|
||||
tip_exception(-1, '该数据已审核,请勿重复操作') if applied_project.status != "common"
|
||||
begin
|
||||
ActiveRecord::Base.transaction do
|
||||
if params[:verify_status] == "agree"
|
||||
Projects::VerifyService.new(applied_project, current_user, params).agree
|
||||
elsif params[:verify_status] == "reject"
|
||||
Projects::VerifyService.new(applied_project, current_user, params).reject
|
||||
end
|
||||
render_ok
|
||||
end
|
||||
rescue => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception("审核失败:#{e.message}")
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def applied_params
|
||||
params.require(:applied_project).permit(:code, :role)
|
||||
params.require(:applied_project).permit(:code, :role, :alert_remarks, :remarks, :attachment_id)
|
||||
end
|
||||
end
|
||||
|
|
@ -28,20 +28,20 @@ class ProjectsController < ApplicationController
|
|||
end
|
||||
|
||||
def index
|
||||
scope = Projects::ListQuery.call(params)
|
||||
scope = Projects::ListQuery.call(params, current_user)
|
||||
|
||||
# @projects = kaminari_paginate(scope)
|
||||
@projects = paginate scope.includes(:project_category, :project_language, :repository, :project_educoder, :owner, :project_units)
|
||||
|
||||
category_id = params[:category_id]
|
||||
@total_count =
|
||||
if category_id.blank?
|
||||
ps = ProjectStatistic.first
|
||||
ps.common_projects_count + ps.mirror_projects_count unless ps.blank?
|
||||
else
|
||||
cate = ProjectCategory.find_by(id: category_id)
|
||||
cate&.projects_count || 0
|
||||
end
|
||||
@total_count = scope.size
|
||||
@projects = paginate scope.includes(:project_category, :project_language, :repository, :project_educoder, :owner, :project_units, :applied_projects)
|
||||
# category_id = params[:category_id]
|
||||
# @total_count =
|
||||
# if category_id.blank?
|
||||
# ps = ProjectStatistic.first
|
||||
# ps.common_projects_count + ps.mirror_projects_count unless ps.blank?
|
||||
# else
|
||||
# cate = ProjectCategory.find_by(id: category_id)
|
||||
# cate&.projects_count || 0
|
||||
# end
|
||||
end
|
||||
|
||||
def create
|
||||
|
|
@ -121,7 +121,7 @@ class ProjectsController < ApplicationController
|
|||
@project.update(project_params)
|
||||
else
|
||||
validate_params = project_params.slice(:name, :description,
|
||||
:project_category_id, :project_language_id, :private)
|
||||
:project_category_id, :project_language_id, :private, :join_project_need_verify)
|
||||
|
||||
Projects::UpdateForm.new(validate_params).validate!
|
||||
|
||||
|
|
@ -223,7 +223,7 @@ class ProjectsController < ApplicationController
|
|||
private
|
||||
def project_params
|
||||
params.permit(:user_id, :name, :description, :repository_name, :website, :lesson_url,
|
||||
:project_category_id, :project_language_id, :license_id, :ignore_id, :private)
|
||||
:project_category_id, :project_language_id, :license_id, :ignore_id, :private, :join_project_need_verify)
|
||||
end
|
||||
|
||||
def mirror_params
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
class Projects::CreateForm < BaseForm
|
||||
REPOSITORY_NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾
|
||||
attr_accessor :user_id, :name, :description, :repository_name, :project_category_id,
|
||||
:project_language_id, :ignore_id, :license_id, :private, :owner
|
||||
:project_language_id, :ignore_id, :license_id, :private, :owner, :join_project_need_verify
|
||||
|
||||
validates :user_id, :name, :description,:repository_name,
|
||||
:project_category_id, :project_language_id, presence: true
|
||||
|
|
@ -10,6 +10,7 @@ class Projects::CreateForm < BaseForm
|
|||
validates :name, length: { maximum: 50 }
|
||||
validates :repository_name, length: { maximum: 100 }
|
||||
validates :description, length: { maximum: 200 }
|
||||
validates :join_project_need_verify, inclusion: { in: [true, false] }
|
||||
|
||||
validate :check_ignore, :check_license, :check_owner, :check_max_repo_creation
|
||||
validate do
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
class Projects::UpdateForm < BaseForm
|
||||
attr_accessor :name, :description, :project_category_id, :project_language_id, :private
|
||||
attr_accessor :name, :description, :project_category_id, :project_language_id, :private, :join_project_need_verify
|
||||
validates :name, :description, :project_category_id, :project_language_id, presence: true
|
||||
validates :name, length: { maximum: 50 }
|
||||
validates :description, length: { maximum: 200 }
|
||||
validates :join_project_need_verify, inclusion: { in: [true, false] }
|
||||
validate do
|
||||
check_project_category(project_category_id)
|
||||
check_project_language(project_language_id)
|
||||
|
|
|
|||
|
|
@ -24,7 +24,22 @@ class AppliedProject < ApplicationRecord
|
|||
has_many :applied_messages, as: :applied, dependent: :destroy
|
||||
# has_many :forge_activities, as: :forge_act, dependent: :destroy
|
||||
|
||||
has_one :file, class_name: 'Attachment', as: :container
|
||||
belongs_to :dealer_user, class_name: 'User' , foreign_key: :dealer, optional: true # 审批人
|
||||
|
||||
enum role: {manager: 3, developer: 4, reporter: 5}
|
||||
enum status: {canceled: -1, common: 0, accepted: 1, refused: 2} # -1 已取消 0 待操作 1 已接收 2 已拒绝
|
||||
|
||||
def role_cn
|
||||
role_cn = ""
|
||||
if self.role == "manager"
|
||||
role_cn = "管理员"
|
||||
elsif self.role == "developer"
|
||||
role_cn = "开发者"
|
||||
elsif self.role == "reporter"
|
||||
role_cn = "报告者"
|
||||
end
|
||||
role_cn
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -126,6 +126,7 @@ class Project < ApplicationRecord
|
|||
has_many :pinned_projects, dependent: :destroy
|
||||
has_many :has_pinned_users, through: :pinned_projects, source: :user
|
||||
has_many :sonarqubes, dependent: :destroy
|
||||
has_many :applied_projects, dependent: :destroy
|
||||
|
||||
after_save :check_project_members, :reset_cache_data
|
||||
before_save :set_invite_code
|
||||
|
|
|
|||
|
|
@ -1,22 +1,34 @@
|
|||
class Projects::ListQuery < ApplicationQuery
|
||||
include CustomSortable
|
||||
|
||||
attr_reader :params
|
||||
attr_reader :params, :user
|
||||
|
||||
sort_columns :updated_on, :created_on, :forked_count, :praises_count, default_by: :updated_on, default_direction: :desc
|
||||
|
||||
def initialize(params)
|
||||
def initialize(params, user=nil)
|
||||
@params = params
|
||||
@user = user
|
||||
end
|
||||
|
||||
def call
|
||||
q = Project.visible.by_name_or_identifier(params[:search])
|
||||
|
||||
# q = Project.visible.by_name_or_identifier(params[:search])
|
||||
q = Project.visible
|
||||
scope = q
|
||||
.with_project_type(params[:project_type])
|
||||
.with_project_category(params[:category_id])
|
||||
.with_project_language(params[:language_id])
|
||||
|
||||
if params[:search].present?
|
||||
scope = scope.joins(:managers).joins("JOIN users ON members.user_id = users.id").where("CONCAT(users.lastname, users.firstname) LIKE :search OR projects.name LIKE :search OR identifier LIKE :search", search: "%#{params[:search].to_s.strip}%")
|
||||
end
|
||||
#我管理的、我学习的
|
||||
if params[:filter] == "manage"
|
||||
scope = scope.joins(:managers).where(members:{user_id: user&.id})
|
||||
elsif params[:filter] == "study"
|
||||
scope = scope.joins(:except_owner_members).where(members:{user_id: user&.id})
|
||||
end
|
||||
scope = scope.distinct
|
||||
|
||||
sort = params[:sort_by] || "updated_on"
|
||||
sort_direction = params[:sort_direction] || "desc"
|
||||
|
||||
|
|
|
|||
|
|
@ -18,8 +18,23 @@ class Projects::ApplyJoinService < ApplicationService
|
|||
|
||||
ActiveRecord::Base.transaction do
|
||||
validate!
|
||||
apply = user.applied_projects.create!(project: project, role: role_value)
|
||||
apply
|
||||
#如果需要审核
|
||||
if project.join_project_need_verify.present?
|
||||
if params[:alert_remarks].blank?
|
||||
res = {
|
||||
need_verify: true
|
||||
}
|
||||
return res
|
||||
end
|
||||
apply = user.applied_projects.create!(project: project, role: role_value, remarks: params[:remarks].to_s.strip)
|
||||
Attachment.find_by(id: params[:attachment_id])&.update_attributes!(container_type: apply.class.to_s, container_id: apply.id)
|
||||
deal_tiding!(apply)
|
||||
return apply
|
||||
else
|
||||
apply = user.applied_projects.create!(project: project, role: role_value)
|
||||
return apply
|
||||
end
|
||||
|
||||
# apply.forge_activities.find_or_create_by!(user: user, project: project)
|
||||
|
||||
# notify_project_manager!(apply)
|
||||
|
|
@ -75,11 +90,15 @@ class Projects::ApplyJoinService < ApplicationService
|
|||
# params check
|
||||
raise Error, '邀请码不能为空' if params[:code].blank?
|
||||
raise Error, '请输入6位项目邀请码' unless valid_invite_code( params[:code])
|
||||
|
||||
# logical check
|
||||
raise Error, '邀请码无效' if project.blank?
|
||||
raise Error, '您已是项目成员' if project.member?(user)
|
||||
raise Error, '您已经提交过申请' if user.applied_projects.common.exists?(project: project)
|
||||
if params[:alert_remarks].present? && project.join_project_need_verify.present?
|
||||
raise Error, '请输入个人情况描述' if params[:remarks].blank?
|
||||
raise Error, '个人情况描述不能超过200个字符' if params[:remarks].size > 200
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def valid_invite_code(str)
|
||||
|
|
@ -88,4 +107,32 @@ class Projects::ApplyJoinService < ApplicationService
|
|||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def deal_tiding!(apply)
|
||||
user_ids = Project.where(id: project.id).joins(:managers).pluck("members.user_id")
|
||||
return if user_ids.blank?
|
||||
columns = %i[user_id trigger_user_id container_id container_type belong_container_id belong_container_type parent_container_id parent_container_type tiding_type viewed extra created_at updated_at]
|
||||
Tiding.bulk_insert(*columns) do |worker|
|
||||
base_attr = {
|
||||
trigger_user_id: user.id,
|
||||
container_id: apply.id,
|
||||
container_type: apply.class.to_s,
|
||||
belong_container_id: project.id,
|
||||
belong_container_type: project.class.to_s,
|
||||
parent_container_id: project.id,
|
||||
parent_container_type: project.class.to_s,
|
||||
tiding_type: "Apply",
|
||||
viewed: 0,
|
||||
extra: "#{apply.role_cn}"
|
||||
}
|
||||
|
||||
user_ids.each do |user_id|
|
||||
worker.add(base_attr.merge(user_id: user_id))
|
||||
end
|
||||
end
|
||||
|
||||
# Tiding.create!(:user_id => @user.id, :trigger_user_id => 1, :container_id => @applied_project.id, :container_type => @applied_project.class.to_s, :belong_container_id => @project.id, :belong_container_type => @project.class.to_s, :tiding_type => "System", :viewed => 0, :extra => extra)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
|
@ -43,6 +43,7 @@ class Projects::CreateService < ApplicationService
|
|||
ignore_id: params[:ignore_id],
|
||||
license_id: params[:license_id],
|
||||
website: params[:website],
|
||||
join_project_need_verify: params[:join_project_need_verify],
|
||||
identifier: params[:repository_name] #新增,hs
|
||||
}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
class Projects::VerifyService < ApplicationService
|
||||
# include ApplicationHelper
|
||||
attr_reader :applied_project, :user, :params
|
||||
|
||||
|
||||
def initialize(applied_project, user, params)
|
||||
@applied_project = applied_project
|
||||
@user = user
|
||||
@params = params
|
||||
@project = @applied_project.project
|
||||
|
||||
end
|
||||
|
||||
def agree
|
||||
@applied_project.update!(status: "accepted", dealer_id: @user.id)
|
||||
member = @project.members.create!(user: @applied_project.user)
|
||||
member.member_roles.create!(role_id: AppliedProject.roles[@applied_project.role])
|
||||
|
||||
# extra = "您申请加入的#{@project.name}项目(#{@applied_project.role_cn})已通过项目管理者审核。"
|
||||
|
||||
deal_tiding!(1)
|
||||
end
|
||||
|
||||
def reject
|
||||
@applied_project.update!(status: "refused", dealer_id: @user.id, reason: params[:reason].to_s.strip)
|
||||
# extra = "您申请加入的#{@project.name}项目(#{@applied_project.role_cn})被管理者驳回,驳回原因:#{params[:reason].to_s.strip}"
|
||||
deal_tiding!(2)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def deal_tiding!(status)
|
||||
Tiding.create!(
|
||||
:user_id => @applied_project.user_id,
|
||||
:trigger_user_id => 1,
|
||||
:container_id => @applied_project.id,
|
||||
:container_type => @applied_project.class.to_s,
|
||||
:belong_container_id => @project.id,
|
||||
:belong_container_type => @project.class.to_s,
|
||||
:parent_container_id => @project.id,
|
||||
:parent_container_type => @project.class.to_s,
|
||||
:tiding_type => "System",
|
||||
:status => status,
|
||||
:viewed => 0,
|
||||
:extra => "#{@applied_project.role_cn}")
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
json.partial! "commons/success"
|
||||
json.data do
|
||||
json.count @count
|
||||
json.list do
|
||||
json.array! @applied_projects.each do |apply|
|
||||
json.id apply.id
|
||||
json.user_name apply.user&.real_name
|
||||
json.applied_project apply.role
|
||||
json.student_id apply.user&.student_id
|
||||
json.mail apply.user&.mail
|
||||
json.remarks apply.remarks
|
||||
json.reason apply.reason
|
||||
json.status apply.status
|
||||
|
||||
#附件
|
||||
if apply&.file.present?
|
||||
json.attachment_info do
|
||||
json.partial! 'attachments/attachment_small', attachment: apply&.file
|
||||
end
|
||||
else
|
||||
json.attachment_info [].to_h
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -18,6 +18,12 @@ json.forked_from_project_id project.forked_from_project_id
|
|||
json.open_devops project.open_devops?
|
||||
json.platform project.platform
|
||||
json.is_pinned project.has_pinned_users.include?(current_user)
|
||||
json.join_project_need_verify project.join_project_need_verify
|
||||
json.pending_verify_count project.applied_projects.select{|x|x.status == "common"}.size
|
||||
json.invite_code project.invite_code
|
||||
json.is_manager project.manager?(current_user)
|
||||
json.is_member project.member?(current_user)
|
||||
|
||||
json.author do
|
||||
if project.educoder?
|
||||
project_educoder = project.project_educoder
|
||||
|
|
|
|||
|
|
@ -17,6 +17,11 @@ json.projects @projects do |project|
|
|||
json.forked_from_project_id project.forked_from_project_id
|
||||
json.open_devops project.open_devops?
|
||||
json.platform project.platform
|
||||
json.join_project_need_verify project.join_project_need_verify
|
||||
json.pending_verify_count project.applied_projects.select{|x|x.status == "common"}.size
|
||||
json.invite_code project.invite_code
|
||||
json.is_manager project.manager?(current_user)
|
||||
json.is_member project.member?(current_user)
|
||||
json.author do
|
||||
if project.educoder?
|
||||
project_educoder = project.project_educoder
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ json.mirror_url @project&.repository.remote_mirror_url
|
|||
json.mirror @project&.repository.mirror_url.present?
|
||||
json.type @project.numerical_for_project_type
|
||||
json.open_devops @project.open_devops?
|
||||
json.pending_verify_count @project.applied_projects.select{|x|x.status == "common"}.size
|
||||
|
||||
unless @project.common?
|
||||
json.mirror_status @repository.mirror_status
|
||||
|
|
|
|||
|
|
@ -13,4 +13,6 @@ json.is_transfering @project.is_transfering
|
|||
json.transfer do
|
||||
json.partial! "/users/user_simple", locals: {user: @project&.applied_transfer_project&.owner}
|
||||
end
|
||||
json.is_pinned @project.has_pinned_users.include?(current_user)
|
||||
json.is_pinned @project.has_pinned_users.include?(current_user)
|
||||
json.pending_verify_count @project.applied_projects.select{|x|x.status == "common"}.size
|
||||
json.join_project_need_verify @project.join_project_need_verify
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
json.username @user.full_name
|
||||
json.real_name @user.real_name
|
||||
json.gender @user.gender
|
||||
json.login @user.login
|
||||
json.login @user.logged? ? @user.login : ""
|
||||
json.user_id @user.id
|
||||
json.image_url url_to_avatar(@user)
|
||||
json.admin @user.admin?
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ module Educoderplus
|
|||
|
||||
# Custom directories with classes and modules you want to be autoloadable.
|
||||
|
||||
config.active_record.default_timezone = :utc
|
||||
config.active_record.default_timezone = :local
|
||||
config.time_zone = 'Beijing'
|
||||
|
||||
# I18n
|
||||
|
|
|
|||
|
|
@ -148,7 +148,13 @@ Rails.application.routes.draw do
|
|||
resources :issue_depends, only: [:create, :destroy]
|
||||
end
|
||||
|
||||
resources :applied_projects, only: [:create]
|
||||
resources :applied_projects, only: [:create, :index] do
|
||||
collection do
|
||||
end
|
||||
member do
|
||||
post :verify
|
||||
end
|
||||
end
|
||||
|
||||
resources :project_categories, only: [:index, :show] do
|
||||
get :group_list, on: :collection
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
class AddJoinProjectNeedVerifyToProject < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
unless column_exists?(:projects, :join_project_need_verify)
|
||||
add_column :projects, :join_project_need_verify, :boolean, default: 0, comment:"用户加入项目是否需要审核"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
class AddRemarksToForgeAppliedProject < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
unless column_exists?(:forge_applied_projects, :remarks)
|
||||
add_column :forge_applied_projects, :remarks, :string
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
class AddReasonToForgeAppliedProject < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
unless column_exists?(:forge_applied_projects, :reason)
|
||||
add_column :forge_applied_projects, :reason, :string
|
||||
end
|
||||
unless column_exists?(:forge_applied_projects, :dealer_id)
|
||||
add_column :forge_applied_projects, :dealer_id, :integer
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Reference in New Issue