init project

This commit is contained in:
Jasder
2020-03-09 00:40:16 +08:00
commit 2937b2a94d
6549 changed files with 7215173 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
class Users::ApplyAuthenticationService < ApplicationService
attr_reader :user, :params
def initialize(user, params)
@user = user
@params = params
end
def call
raise Error, '请先完善基本信息' unless user.profile_completed?
Users::ApplyAuthenticationForm.new(params).validate!
# raise Error, '您已经申请过实名认证了' if ApplyUserAuthentication.real_name_auth.processing.exists?(user_id: user.id)
user.lastname = params[:name].to_s.strip
user.firstname = ''
user.ID_number = params[:id_number].to_s.strip.presence
user.show_realname = params[:show_realname].to_s == 'true' if params[:show_realname].to_s.present?
ActiveRecord::Base.transaction do
ApplyUserAuthentication.real_name_auth.processing.where(user_id: user.id).destroy_all
user.authentication = true
user.save!
user.user_extension.update!(gender: params[:gender].to_i) if params[:gender].present?
apply = user.apply_user_authentication.create!(auth_type: 1, status: 0)
Attachment.associate_container(params[:attachment_ids], apply.id, apply.class) if params[:attachment_ids]
# move_image_file! unless params[:upload_image].to_s == 'false'
end
# sms_notify_admin
user
end
private
def move_image_file!
image_url = ApplicationController.helpers.disk_real_name_auth_filename(user.id)
temp_image_url = image_url + 'temp'
FileUtils.mv(temp_image_url, image_url, force: true) if File.exist?(temp_image_url)
rescue RuntimeError => ex
Util.logger_error(ex)
raise Error, '申请失败'
ensure
File.delete(temp_image_url) if File.exist?(temp_image_url)
end
def sms_notify_admin
Educoder::Sms.notify_admin(send_type: 'apply_auth')
rescue => ex
Util.logger_error(ex)
end
end

View File

@@ -0,0 +1,71 @@
class Users::ApplyProfessionalAuthService < ApplicationService
Error = Class.new(StandardError)
attr_reader :user, :params
def initialize(user, params)
@user = user
@params = params
end
def call
raise Error, '请先完善基本信息' unless user.profile_completed?
Users::ApplyProfessionalAuthForm.new(params).validate!
# raise Error, '您已经申请过职业认证了' if ApplyUserAuthentication.professional_auth.processing.exists?(user_id: user.id)
extension = user.user_extension
extension.school_id = params[:school_id]
extension.department_id = params[:department_id]
extension.identity = params[:identity]
user.professional_certification = params[:identity] != "teacher"
extra = params[:extra].to_s.strip.presence
if extension.identity.to_s == 'student'
extension.technical_title = nil
extension.student_id = extra
else
extension.technical_title = extra
extension.student_id = nil
end
ActiveRecord::Base.transaction do
ApplyUserAuthentication.professional_auth.processing.where(user_id: user.id).destroy_all
user.save!
extension.save!
apply = user.apply_user_authentication.create!(auth_type: 2, status: 0)
Attachment.associate_container(params[:attachment_ids], apply.id, apply.class) if params[:attachment_ids]
# move_image_file! unless params[:upload_image].to_s == 'false'
end
# sms_notify_admin
end
private
def move_image_file!
image_url = ApplicationController.helpers.disk_professional_auth_filename(user.id)
temp_image_url = image_url + 'temp'
FileUtils.mv(temp_image_url, image_url, force: true) if File.exist?(temp_image_url)
rescue RuntimeError => ex
Util.logger_error(ex)
raise Error, '申请失败'
ensure
File.delete(temp_image_url) if File.exist?(temp_image_url)
end
def sms_notify_admin
sms_cache = Rails.cache.read('apply_pro_certification')
if sms_cache.nil?
Educoder::Sms.notify_admin(send_type: 'apply_pro_certification')
Rails.cache.write('apply_pro_certification', 1, expires_in: 5.minutes)
end
rescue => ex
Util.logger_error(ex)
end
end

View File

@@ -0,0 +1,60 @@
class Users::ApplyTrailService < ApplicationService
Error = Class.new(StandardError)
attr_reader :user, :remote_ip, :params
def initialize(user, params)
@user = user
@remote_ip = params.delete(:remote_ip)
@params = params
end
def call
Users::ApplyTrailForm.new(params.merge(user: user)).validate!
ActiveRecord::Base.transaction do
bind_user_phone! unless user.phone_binded?
apply = ApplyAction.find_or_initialize_by(user_id: user.id, container_type: 'TrialAuthorization', status: 0)
apply.assign_attributes(ip_addr: remote_ip, apply_reason: params[:reason]) if apply.new_record?
# 自动授权
if auto_authorization_school_student?
user.update!(certification: 1)
apply.status = 1
# else
# sms_cache = Rails.cache.read("apply_auth")
# if sms_cache.nil?
# send_trial_apply_notify!
# Rails.cache.write("apply_auth", 1, expires_in: 5.minutes)
# end
end
apply.save!
end
user
end
private
def bind_user_phone!
code = VerificationCode.where(phone: params[:phone], code: params[:code], code_type: 4).last
raise Error, '无效的验证码' if code.blank? || !code.effective?
user.update!(phone: params[:phone])
end
def auto_authorization_school_student?
user.user_extension&.student? && School.exists?(auto_users_trial: true, id: user.user_extension&.school_id)
end
def send_trial_apply_notify!
Educoder::Sms.notify_admin(send_type:'user_apply_auth')
rescue => ex
Rails.logger.error('发送通知管理员短信失败')
Rails.logger.error(ex.message)
ex.backtrace.each { |msg| Rails.logger.error(msg) }
end
end

View File

@@ -0,0 +1,27 @@
class Users::AttendanceService < ApplicationService
Error = Class.new(StandardError)
attr_reader :user
def initialize(user)
@user = user
end
def call
nearly_attendance = Attendance.find_by(user_id: user.id)
raise Error, '您已签到过了' if nearly_attendance&.today?
attendance = nil
ActiveRecord::Base.transaction do
gold = nearly_attendance&.next_gold || 50
user.increment!(:grade, gold)
attendance = user.attendances.create!(score: gold)
Grade.create!(user_id: user.id, score: gold, container_id: user.id, container_type: 'Attendance')
end
attendance
end
end

View File

@@ -0,0 +1,28 @@
class Users::BindEmailService < ApplicationService
Error = Class.new(StandardError)
attr_reader :user, :params
def initialize(user, params)
@user = user
@params = params
end
def call
Users::BindEmailForm.new(params).validate!
raise Error, '该邮箱已被其他账号绑定' if User.where.not(id: user.id).exists?(mail: params[:email])
code = VerificationCode.where(email: params[:email], code: params[:code], code_type: 5).last
raise Error, '验证码无效' unless code&.effective?
ActiveRecord::Base.transaction do
if user.mail.blank?
RewardGradeService.call(user, container_id: user.id, container_type: 'Mail', score: 500)
end
user.mail = params[:email]
user.save!
end
end
end

View File

@@ -0,0 +1,28 @@
class Users::BindPhoneService < ApplicationService
Error = Class.new(StandardError)
attr_reader :user, :params
def initialize(user, params)
@user = user
@params = params
end
def call
Users::BindPhoneForm.new(params).validate!
raise Error, '该手机号已被其他账号绑定' if User.where.not(id: user.id).exists?(phone: params[:phone])
code = VerificationCode.where(phone: params[:phone], code: params[:code], code_type: 4).last
raise Error, '验证码无效' unless code&.effective?
ActiveRecord::Base.transaction do
if user.phone.blank?
RewardGradeService.call(user, container_id: user.id, container_type: 'Phone', score: 500)
end
user.phone = params[:phone]
user.save!
end
end
end

View File

@@ -0,0 +1,52 @@
class Users::CourseService
include CustomSortable
sort_columns :created_at, :updated_at, default_by: :updated_at, default_direction: :desc
attr_reader :user, :params
def initialize(user, params)
@user = user
@params = params
end
def call
courses = category_scope_courses.not_deleted.not_excellent
courses = status_filter(courses)
custom_sort(courses, params[:sort_by], params[:sort_direction])
end
private
def category_scope_courses
case params[:category]
when 'study' then
user.as_student_courses.started
when 'manage' then
user.manage_courses
else
ids = user.as_student_courses.started.pluck(:id) + user.manage_courses.pluck(:id)
Course.where(id: ids)
end
end
def status_filter(relations)
# 只有自己查看才有过滤
return relations unless observed_logged_user?
case params[:status]
when 'processing' then
relations.processing
when 'end' then
relations.ended
else
relations
end
end
def observed_logged_user?
User.current.id == user.id
end
end

View File

@@ -0,0 +1,76 @@
class Users::ProjectPackageService < ApplicationService
include CustomSortable
sort_columns :published_at, default_by: :published_at, default_direction: :desc
attr_reader :user, :params
def initialize(user, params)
@user = user
@params = params
end
def call
packages = category_scope_filter
packages = user_policy_filter(packages)
custom_sort(packages, :published_at, params[:sort_direction])
end
private
def category_scope_filter
case params[:category]
when 'bidden' then
user.bidden_project_packages
when 'manage' then
user.project_packages
else
ids = user.bidding_users.pluck(:project_package_id) + user.project_packages.pluck(:id)
ProjectPackage.where(id: ids)
end
end
def user_policy_filter(relations)
if self_or_admin?
status_filter(relations)
else
relations.visible
end
end
def status_filter(relations)
return relations unless self_or_admin?
case params[:category]
when 'bidden' then bidding_status_filter(relations)
when 'manage' then package_status_filter(relations)
else relations
end
end
def bidding_status_filter(relations)
case params[:status]
when 'bidding_lost' then
relations.where(bidding_users: { status: :bidding_lost })
when 'bidding_won' then
relations.where(bidding_users: { status: :bidding_won })
else
relations
end
end
def package_status_filter(relations)
case params[:status]
when 'unpublished' then relations.invisible
when 'bidding' then relations.where(status: :published)
when 'finished' then relations.where(status: %w[bidding_ended bidding_finished])
else relations
end
end
def self_or_admin?
User.current&.id == user.id || User.current&.admin_or_business?
end
end

View File

@@ -0,0 +1,51 @@
class Users::ProjectService
include CustomSortable
sort_columns :created_on, :updated_on, default_by: :updated_on, default_direction: :desc
attr_reader :user, :params
def initialize(user, params)
@user = user
@params = params
end
def call
projects = Project.joins(members: :member_roles).where(members: { user_id: user.id })
keyword = params[:keyword].to_s.strip
projects = projects.where('name LIKE ?', "%#{keyword}%") if keyword.present?
projects = projects.where.not(status: 9) # without archived status
projects = category_filter(projects)
projects = status_filter(projects)
custom_sort(projects, params[:sort_by], params[:sort_direction])
end
private
def category_filter(relations)
roles = case params[:category]
when 'study' then [4, 5]
when 'manage' then 3
else [3, 4, 5]
end
relations.where(member_roles: { role_id: roles })
end
def status_filter(relations)
return relations unless self_or_admin?
case params[:status]
when 'publicly' then relations.where(is_public: true)
when 'personal' then relations.where(is_public: false)
else relations
end
end
def self_or_admin?
User.current.id == user.id || User.current.admin?
end
end

View File

@@ -0,0 +1,99 @@
class Users::QuestionBankService
attr_reader :user, :params
def initialize(user, params)
@user = user
@params = params
end
def call
relations = class_name.classify.constantize.all
relations = category_filter(relations)
relations = type_filter(relations) if params[:type].present?
relations = relations.where(course_list_id: params[:course_list_id]) if params[:course_list_id].present?
custom_sort(relations, params[:sort_by], params[:sort_direction])
end
def course_lists
relation_name = class_name.underscore.pluralize.to_sym
course_lists = CourseList.joins(relation_name).where.not(relation_name => { id: nil })
category_condition =
case params[:object_type]
when 'normal' then { homework_type: 1 }
when 'group' then { homework_type: 3 }
when 'exercise' then { container_type: 'Exercise' }
when 'poll' then { container_type: 'Poll' }
when 'gtask', 'gtopic' then {}
else raise ArgumentError
end
course_lists = course_lists.where(relation_name => category_condition) if category_condition.present?
type_condition =
case params[:type]
when 'personal' then { user_id: user.id }
when 'publicly' then { is_public: true }
else {}
end
course_lists = course_lists.where(relation_name => type_condition) if type_condition.present?
course_lists.distinct.select(:id, :name)
end
private
def class_name
@_class_name ||= begin
case params[:object_type]
when 'normal', 'group' then 'HomeworkBank'
when 'exercise', 'poll' then 'ExerciseBank'
when 'gtask' then 'GtaskBank'
when 'gtopic' then 'GtopicBank'
else raise ArgumentError
end
end
end
def category_filter(relations)
case params[:object_type]
when 'normal' then
relations.where(homework_type: 1)
when 'group' then
relations.where(homework_type: 3)
when 'exercise' then
relations.where(container_type: 'Exercise')
when 'poll' then
relations.where(container_type: 'Poll')
when 'gtask', 'gtopic' then
relations.all
else
raise ArgumentError
end
end
def type_filter(relations)
case params[:type]
when 'personal' then relations.where(user_id: user.id)
when 'publicly' then relations.where(is_public: true)
else relations
end
end
def custom_sort(relations, sort_by, sort_direction)
case sort_by
when 'updated_at' then
relations.order("updated_at #{sort_direction}, id #{sort_direction}")
when 'name' then
relations.order("CONVERT(name USING gbk) COLLATE gbk_chinese_ci #{sort_direction}")
when 'contributor' then
order_sql = "CONVERT (users.lastname USING gbk) COLLATE gbk_chinese_ci #{sort_direction},"\
" CONVERT (users.firstname USING gbk) COLLATE gbk_chinese_ci #{sort_direction}"
relations.joins(:user).where(users: { status: 1 }).order(order_sql)
else
relations
end
end
end

View File

@@ -0,0 +1,85 @@
class Users::UpdateAccountService < ApplicationService
attr_reader :user, :params
def initialize(user, params)
@user = user
@params = params
end
def call
form = Users::UpdateAccountForm.new(params.merge(user: user))
form.validate!
first_full_reward = false
ActiveRecord::Base.transaction do
first_full_reward = user.nickname.blank?
extension = user.user_extension || user.build_user_extension
user.assign_attributes(user_attributes)
extension.assign_attributes(user_extension_attributes)
# 未认证下才能修改姓名
if !user.authentication? && user.process_real_name_apply.blank?
user.lastname = params[:name]
user.firstname = ''
extension.gender = params[:gender]
end
if extension.student?
extension.student_id = params[:student_id]
extension.technical_title = nil
else
extension.student_id = nil
extension.technical_title = params[:technical_title]
end
# 职业、学校变动需要重新进行职业认证
if extension.identity_changed? || extension.school_id_changed?
user.professional_certification = false
# 撤销之前的职业认证
user.apply_user_authentication.professional_auth.passed.update_all(status: 3)
end
# 表示资料完整
user.profile_completed = true
extension.save!
user.save!
end
if first_full_reward
# RewardGradeService.call(user, container_id: user.id, container_type: 'Account', score: 500)
if user.user_extension.teacher?
join_course(user.id,1309, 2)
# sms_notify_admin(user.lastname)
end
end
user
end
private
def user_attributes
params.slice(*%i[nickname show_realname])
end
def user_extension_attributes
params.slice(*%i[location location_city identity student_id technical_title school_id department_id])
end
def sms_notify_admin name
Educoder::Sms.send(mobile:'17680641960', send_type:'teacher_register', name: name, user_name:'管理员')
rescue => ex
Util.logger_error(ex)
end
def join_course(user_id, course_id, identity)
course = Course.find_by(id: course_id)
return unless course
attr = {course_id: course_id, role: identity, user_id: user_id}
CourseMember.create!(attr)
end
end

View File

@@ -0,0 +1,32 @@
class Users::UpdatePasswordService < ApplicationService
Error = Class.new(StandardError)
attr_reader :user, :params
def initialize(user, params)
@user = user
@params = params
end
def call
Users::UpdatePasswordForm.new(params).validate!
raise Error, '旧密码不匹配' unless user.check_password?(params[:old_password]) || user.hashed_password.blank?
ActiveRecord::Base.transaction do
user.update!(password: params[:password])
if user.gid.present?
# 同步修改gitlab密码
begin
Gitlab.client.edit_user(user.gid, password: params[:password])
rescue Exception => ex
Rails.logger.error(ex.message)
raise Error, '修改失败'
end
end
end
user
end
end