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,20 @@
class Admins::AddDepartmentMemberService < ApplicationService
attr_reader :department, :params
def initialize(department, params)
@department = department
@params = params
end
def call
columns = %i[]
DepartmentMember.bulk_insert(*columns) do |worker|
Array.wrap(params[:user_ids]).compact.each do |user_id|
next if department.department_members.exists?(user_id: user_id)
worker.add(department_id: department.id, user_id: user_id)
end
end
end
end

View File

@@ -0,0 +1,19 @@
class Admins::AddLaboratoryUserService < ApplicationService
attr_reader :laboratory, :params
def initialize(laboratory, params)
@laboratory = laboratory
@params = params
end
def call
columns = %i[]
LaboratoryUser.bulk_insert(*columns) do |worker|
Array.wrap(params[:user_ids]).compact.each do |user_id|
next if laboratory.laboratory_users.exists?(user_id: user_id)
worker.add(laboratory_id: laboratory.id, user_id: user_id)
end
end
end
end

View File

@@ -0,0 +1,89 @@
class Admins::CheckShixunMirrorsService < ApplicationService
Error = Class.new(StandardError)
def call
bridge_images
ActiveRecord::Base.transaction do
check_sync_mirrors!
check_mirrors!
end
end
private
def mirrors
bridge_images['images']
end
def sync_mirrors
bridge_images['imagesNotSync']
end
def check_mirrors!
return if mirrors.blank?
image_names = []
mirrors.each do |data|
mirror = JSON.parse(data)
name_repository = MirrorRepository.find_by(name: mirror['imageName'])
id_repository = MirrorRepository.find_by(mirrorID: mirror['imageID'])
image_names << mirror['imageName']
if name_repository.blank? && id_repository.present? # 镜像名称被修改
id_repository.update_column(:status, 2)
MirrorOperationRecord.create!(mirror_repository_id: id_repository.id, mirror_id: mirror['imageID'],
mirror_name: mirror['imageName'], status: 2, user_id: -1)
elsif name_repository.blank? # 镜像不存在、创建镜像
new_repository = MirrorRepository.create!(mirrorID: mirror['imageID'], name: mirror['imageName'])
MirrorOperationRecord.create!(mirror_repository_id: new_repository.id, mirror_id: mirror['imageID'],
mirror_name: mirror['imageName'], status: 0, user_id: -1)
elsif name_repository.mirrorID != mirror['imageID'] # 镜像ID被修改
name_repository.update_column(:status, 2)
MirrorOperationRecord.create!(mirror_repository_id: name_repository.id, mirror_id: mirror['imageID'],
mirror_name: mirror['imageName'], status: 1, user_id: -1)
end
end
# 判断中间层镜像是否被删除
MirrorRepository.find_each do |mirror|
next if mirror&.name.blank? || image_names.index(mirror.name)
mirror.update_column(:status, 4)
MirrorOperationRecord.create!(mirror_repository_id: mirror.id, mirror_id: mirror&.mirrorID,
mirror_name: mirror.name, status: 3, user_id: -1)
end
end
def check_sync_mirrors!
return if sync_mirrors.blank?
sync_mirrors.each do |data|
mirror = JSON.parse(data)
repository = MirrorRepository.find_by(name: mirror['imageName'])
next if repository.blank? || repository.status != 1
repository.update_column(:status, 5)
MirrorOperationRecord.create!(mirror_repository_id: repository.id, mirror_id: mirror['imageID'],
mirror_name: mirror['imageName'], status: 4, user_id: -1)
end
end
def bridge_images
@_bridge_images ||= begin
url = "#{EduSetting.get('cloud_bridge')}/bridge/docker/images"
res = Faraday.get(url)
res = JSON.parse(res.body)
raise Error, '拉取镜像信息异常' if res && res['code'] != 0
res
rescue => e
Rails.logger.error("get response failed ! #{e.message}")
raise Error, '实训云平台繁忙繁忙等级84'
end
end
end

View File

@@ -0,0 +1,21 @@
class Admins::ChooseMirrorService < ApplicationService
attr_reader :mirror, :user, :number
def initialize(mirror, user, mirror_number)
@mirror = mirror
@user = user
@number = mirror_number
end
def call
if mirror.mirrorID == number
mirror.update_column(:status, 1)
return
end
old_number = mirror.mirrorID
mirror.update!(mirrorID: number, status: 1)
MirrorOperationRecord.create!(mirror_repository_id: mirror.id, mirror_id: number, mirror_name: mirror.name,
status: 1, user_id: user.id, old_tag: old_number, new_tag: mirror.mirrorID)
end
end

View File

@@ -0,0 +1,20 @@
class Admins::CreateLaboratoryService < ApplicationService
Error = Class.new(StandardError)
attr_reader :params
def initialize(params)
@params = params
end
def call
raise Error, '单位不能为空' if params[:school_id].blank?
raise Error, '该单位已存在' if Laboratory.exists?(school_id: params[:school_id])
ActiveRecord::Base.transaction do
laboratory = Laboratory.create!(school_id: params[:school_id])
laboratory.create_laboratory_setting!
end
end
end

View File

@@ -0,0 +1,56 @@
class Admins::DeleteUnitApplyService < ApplicationService
attr_reader :department, :params
def initialize(unit_apply, params)
@unit_apply = unit_apply
@params = params
end
def call
ActiveRecord::Base.transaction do
@unit_apply.update_attribute("status",3)
@unit_apply&.applied_messages&.update_all(status:3)
@unit_apply&.school&.apply_add_departments&.update_all(status:3)
applied_departments = ApplyAddDepartment.where(school_id: @unit_apply.school_id)
applied_departments.update_all(status: 3)
use_extensions = UserExtension&.where(school_id: @unit_apply.school_id)
user_ids = UserExtension&.where(school_id: @unit_apply.school_id)&.pluck(:user_id)
User.where(id: user_ids).update_all(profile_completed: false)
use_extensions.update_all(school_id: nil,department_id: nil)
@unit_apply&.user&.user_extension&.update_attribute("department_id", nil)
# 申请了职业认证的用户撤销申请
apply_user_auth = ApplyUserAuthentication.where(user_id: user_ids, auth_type: 2, status: 0)
apply_user_auth.each do |apply|
apply.tidings.destroy_all
apply.update_attribute('status', 3)
diskfile2 = disk_auth_filename('UserAuthentication', apply.user_id, 'PRO')
diskfilePRO = diskfile2 + 'temp'
File.delete(diskfilePRO) if File.exist?(diskfilePRO)
File.delete(diskfile2) if File.exist?(diskfile2)
end
# 未审批删除
if params[:tip] == "unapplied"
Tiding.where(:user_id => 1, :trigger_user_id => @unit_apply.user_id, :container_id => @unit_apply.id, :container_type => 'ApplyAddSchools', :status => 0, :tiding_type => "Apply").update_all(status: 1)
Tiding.create(:user_id => @unit_apply.user_id, :trigger_user_id => 0, :container_id => @unit_apply.id, :container_type =>'ApplyAddSchools', :belong_container_id => @unit_apply.school_id, :belong_container_type=> 'School', :tiding_type => "System", :status => 2, :extra => params[:reason])
Tiding.where(:user_id => 1, :container_id => applied_departments.pluck(:id), :container_type => 'ApplyAddDepartment', :status => 0, :tiding_type => "Apply").update_all(status: 1)
if applied_departments&.first.present?
Tiding.create(:user_id => applied_departments.first.user_id, :trigger_user_id => 0, :container_id => applied_departments.first.id, :container_type =>'ApplyAddDepartment', :belong_container_id => @unit_apply.school_id, :belong_container_type=> 'School', :tiding_type => "System", :status => 2)
AppliedMessage.create(:user_id => applied_departments.first.user_id, :status => 3, :viewed => 0, :applied_id => applied_departments.first.id, :applied_type => "ApplyAddDepartment", :name => applied_departments.first.name )
end
@unit_apply&.school&.destroy
@unit_apply&.school&.departments&.destroy_all
elsif params[:tip] == "applied"
applied_departments.destroy_all
@unit_apply.destroy
end
end
end
end

View File

@@ -0,0 +1,35 @@
class Admins::DragCooperativeService < ApplicationService
Error = Class.new(StandardError)
attr_reader :move, :after
def initialize(move, after)
@move = move
@after = after # 移动后下一个位置的元素
end
def call
return if move.position + 1 == after&.position # 未移动
raise Error, '未知错误' if after && move.img_type != after.img_type
coo_imgs = CooImg.where(img_type: move.img_type)
ActiveRecord::Base.transaction do
if after.blank? # 移动至末尾
total = coo_imgs.count
coo_imgs.where('position > ?', move.position).update_all('position = position - 1')
move.update!(position: total)
return
end
if move.position > after.position # 前移
coo_imgs.where('position >= ? AND position < ?', after.position, move.position).update_all('position = position + 1')
move.update!(position: after.position)
else # 后移
coo_imgs.where('position > ? AND position <= ?', move.position, after.position).update_all('position = position - 1')
move.update!(position: after.position)
end
end
end
end

View File

@@ -0,0 +1,35 @@
class Admins::DragPortalImageService < ApplicationService
Error = Class.new(StandardError)
attr_reader :laboratory, :move, :after
def initialize(laboratory, move, after)
@laboratory = laboratory
@move = move
@after = after # 移动后下一个位置的元素
end
def call
return if move.position + 1 == after&.position # 未移动
images = laboratory.portal_images
ActiveRecord::Base.transaction do
if after.blank? || move.id == after.id # 移动至末尾
total = images.count
images.where('position > ?', move.position).update_all('position = position - 1')
move.update!(position: total)
return
end
if move.position > after.position # 前移
images.where('position >= ? AND position < ?', after.position, move.position).update_all('position = position + 1')
move.update!(position: after.position)
else # 后移
images.where('position > ? AND position < ?', move.position, after.position).update_all('position = position - 1')
move.update!(position: after.position - 1)
end
end
end
end

View File

@@ -0,0 +1,32 @@
class Admins::DragWeappAdvertService < ApplicationService
attr_reader :move, :after
def initialize(move, after)
@move = move
@after = after # 移动后下一个位置的元素
end
def call
return if move.position + 1 == after&.position # 未移动
adverts = WeappSettings::Advert.all
ActiveRecord::Base.transaction do
if after.blank? || move.id == after.id # 移动至末尾
total = adverts.count
adverts.where('position > ?', move.position).update_all('position = position - 1')
move.update!(position: total)
return
end
if move.position > after.position # 前移
adverts.where('position >= ? AND position < ?', after.position, move.position).update_all('position = position + 1')
move.update!(position: after.position)
else # 后移
adverts.where('position > ? AND position < ?', move.position, after.position).update_all('position = position - 1')
move.update!(position: after.position - 1)
end
end
end
end

View File

@@ -0,0 +1,32 @@
class Admins::DragWeappCarouselService < ApplicationService
attr_reader :move, :after
def initialize(move, after)
@move = move
@after = after # 移动后下一个位置的元素
end
def call
return if move.position + 1 == after&.position # 未移动
carousels = WeappSettings::Carousel.all
ActiveRecord::Base.transaction do
if after.blank? || move.id == after.id # 移动至末尾
total = carousels.count
carousels.where('position > ?', move.position).update_all('position = position - 1')
move.update!(position: total)
return
end
if move.position > after.position # 前移
carousels.where('position >= ? AND position < ?', after.position, move.position).update_all('position = position + 1')
move.update!(position: after.position)
else # 后移
carousels.where('position > ? AND position < ?', move.position, after.position).update_all('position = position - 1')
move.update!(position: after.position - 1)
end
end
end
end

View File

@@ -0,0 +1,38 @@
class Admins::IdentityAuths::AgreeApplyService < ApplicationService
attr_reader :apply, :user
def initialize(apply)
@apply = apply
@user = apply.user
end
def call
ActiveRecord::Base.transaction do
apply.update!(status: 1)
user.update!(authentication: true)
RewardGradeService.call(user, container_id: user.id, container_type: 'Authentication', score: 500)
deal_tiding!
apply.attachment&.destroy
# delete_auth_file!
end
end
private
def deal_tiding!
apply.tidings.where(tiding_type: 'Apply').update_all(status: 1)
Tiding.create!(user_id: apply.user_id, trigger_user_id: 0,
container_id: apply.id, container_type: 'ApplyUserAuthentication',
belong_container_id: apply.user_id, belong_container_type: 'User',
status: 1, tiding_type: 'System')
end
def delete_auth_file!
path = Util::FileManage.disk_real_name_auth_filename(user.id)
File.delete(path) if File.exists?(path)
apply.update!(is_delete: true)
end
end

View File

@@ -0,0 +1,42 @@
class Admins::IdentityAuths::RefuseApplyService < ApplicationService
attr_reader :apply, :user, :params
def initialize(apply, params)
@apply = apply
@user = apply.user
@params = params
end
def call
ActiveRecord::Base.transaction do
apply.update!(status: 2, remarks: reason)
user.update!(authentication: false)
deal_tiding!
apply.attachment&.destroy
# delete_auth_file!
end
end
private
def reason
params[:reason].to_s.strip
end
def deal_tiding!
apply.tidings.where(tiding_type: 'Apply').update_all(status: 1)
Tiding.create!(user_id: apply.user_id, trigger_user_id: 0,
container_id: apply.id, container_type: 'ApplyUserAuthentication',
belong_container_id: apply.user_id, belong_container_type: 'User',
status: 2, tiding_type: 'System')
end
def delete_auth_file!
path = Util::FileManage.disk_real_name_auth_filename(user.id)
File.delete(path) if File.exists?(path)
apply.update!(is_delete: true)
end
end

View File

@@ -0,0 +1,26 @@
class Admins::IdentityAuths::RevokeApplyService < ApplicationService
attr_reader :apply, :user
def initialize(apply)
@apply = apply
@user = apply.user
end
def call
ActiveRecord::Base.transaction do
apply.revoke!
user.update!(authentication: false)
deal_tiding!
end
end
private
def deal_tiding!
Tiding.create!(user_id: apply.user_id, trigger_user_id: 0,
container_id: apply.id, container_type: 'CancelUserAuthentication',
belong_container_id: apply.user_id, belong_container_type: 'User',
status: 1, tiding_type: 'System')
end
end

View File

@@ -0,0 +1,63 @@
class Admins::ImportCourseMemberService < ApplicationService
Error = Class.new(StandardError)
attr_reader :file, :result
def initialize(file)
@file = file
@result = { success: 0, fail: [] }
end
def call
raise Error, '文件不存在' if file.blank?
excel = Admins::ImportCourseMemberExcel.new(file)
excel.read_each(&method(:create_course_member))
result
rescue ApplicationImport::Error => ex
raise Error, ex.message
end
private
def create_course_member(data)
raise '课堂角色必须为 2、3、4' unless [2, 3, 4].include?(data.role.to_i)
user = User.joins(:user_extension).where(user_extensions: { student_id: data.student_id, school_id: data.school_id }).first
raise '该学号的用户不存在' if user.blank?
course = Course.find_by(id: data.course_id)
raise '该课堂不存在' if course.blank?
course_group = nil
if data.course_group_name.present?
course_group = course.course_groups.find_or_create_by!(name: data.course_group_name)
end
member = course.course_members.find_by(user_id: user.id, role: data.role.to_i)
# 如果已是课堂成员且是学生身份and不在指定的分班则移动到该分班
if member.present? && member.role == 'STUDENT' && course_group && member.course_group_id != course_group&.id.to_i
member.update!(course_group_id: course_group&.id.to_i)
elsif member.blank?
course.course_members.create!(user_id: user.id, role: data.role.to_i, course_group_id: course_group&.id.to_i)
extra =
case data.role.to_i
when 2 then 9
when 3 then 7
else 10
end
Tiding.create!(user_id: user.id, trigger_user_id: course.tea_id, container_id: course.id,
container_type: 'TeacherJoinCourse', belong_container_id: course.id,
belong_container_type: 'Course', tiding_type: 'System', extra: extra)
end
result[:success] += 1
rescue Exception => ex
fail_data = data.as_json
fail_data[:data] = fail_data.values.join(',')
fail_data[:message] = ex.message
result[:fail] << fail_data
end
end

View File

@@ -0,0 +1,52 @@
class Admins::ImportDisciplineService < ApplicationService
Error = Class.new(StandardError)
attr_reader :file, :result
def initialize(file)
@file = file
@result = { success: 0, fail: [] }
end
def call
raise Error, '文件不存在' if file.blank?
excel = Admins::ImportDisciplineExcel.new(file)
excel.read_each(&method(:save_discipline))
result
rescue ApplicationImport::Error => ex
raise Error, ex.message
end
private
def save_discipline(data)
count = 0
discipline_name = data.discipline_name.to_s.strip
sub_discipline_name = data.sub_discipline_name.to_s.strip
return unless discipline_name.present?
discipline = Discipline.find_by(name: discipline_name)
if discipline.blank?
discipline = Discipline.create!(name: discipline_name, position: Discipline.all.pluck(:position).max + 1)
count += 1
end
if sub_discipline_name.present?
sub_discipline = SubDiscipline.find_by(name: discipline_name, discipline: discipline)
if sub_discipline.blank?
SubDiscipline.create!(name: sub_discipline_name, discipline: discipline, position: discipline.sub_disciplines.pluck(:position).max + 1)
count += 1
end
end
result[:success] += count
rescue Exception => ex
fail_data = data.as_json
fail_data[:data] = fail_data.values.join(',')
fail_data[:message] = ex.message
result[:fail] << fail_data
end
end

View File

@@ -0,0 +1,92 @@
class Admins::ImportUserService < ApplicationService
Error = Class.new(StandardError)
attr_reader :file, :school, :prefix, :result
def initialize(file)
@file = file
@result = { success: 0, fail: [] }
end
def call
raise Error, '文件不存在' if file.blank?
excel = Admins::ImportUserExcel.new(file)
@school = excel.school
@prefix = excel.identifier
excel.read_each(&method(:save_user))
result
rescue ApplicationImport::Error => ex
raise Error, ex.message
end
private
def save_user(data)
user = find_user(data)
if user.blank?
create_user(data)
else
user.update_column(:certification, 1)
end
result[:success] += 1
rescue Exception => ex
fail_data = data.as_json
fail_data[:data] = fail_data.values.join(',')
fail_data[:message] = ex.message
result[:fail] << fail_data
end
def create_user(data)
department = school.departments.find_by(name: data.department_name)
attr = {
type: 'User',
status: User::STATUS_ACTIVE,
login: "#{prefix}#{data.student_id}",
firstname: '',
lastname: data.name,
nickname: data.name,
professional_certification: 1,
certification: 1,
password: '12345678',
phone: data.phone,
mail: "#{prefix}#{data.student_id}@qq.com",
profile_completed: true
}
ActiveRecord::Base.transaction do
user = User.create!(attr)
extension_attr = {
school_id: school.id, location: school.province, location_city: school.city,
gender: 0, identity: data.identity.to_i, department_id: department&.id, student_id: data.student_id
}
extension_attr[:technical_title] =
case data.identity.to_i
when 0 then %w(教授 副教授 讲师 助教).include?(data.technical_title) ? data.technical_title : '讲师'
when 2 then %w(企业管理者 部门管理者 高级工程师 工程师 助理工程师).include?(data.technical_title) ? data.technical_title : '助理工程师'
else nil
end
user.create_user_extension!(extension_attr)
end
end
def find_user(data)
users = User.joins(:user_extension).where(user_extensions: { identity: data.identity, school_id: school.id })
if data.identity.to_i == 1
users = users.where(user_extensions: { student_id: data.student_id })
else
users = users.where(user_extensions: { technical_title: data.technical_title }).where('CONCAT(users.lastname,users.firstname) = ?', data.name)
end
users.first
end
end

View File

@@ -0,0 +1,39 @@
class Admins::ProfessionalAuths::AgreeApplyService < ApplicationService
attr_reader :apply, :user
def initialize(apply)
@apply = apply
@user = apply.user
end
def call
ActiveRecord::Base.transaction do
apply.update!(status: 1)
user.update!(professional_certification: true)
user.update!(is_shixun_marker: true) if user.is_teacher?
RewardGradeService.call(user, container_id: user.id, container_type: 'Professional', score: 500)
deal_tiding!
apply.attachment&.destroy
# delete_auth_file!
end
end
private
def deal_tiding!
apply.tidings.where(tiding_type: 'Apply').update_all(status: 1)
Tiding.create!(user_id: apply.user_id, trigger_user_id: 0,
container_id: apply.id, container_type: 'ApplyUserAuthentication',
belong_container_id: apply.user_id, belong_container_type: 'User',
status: 1, tiding_type: 'System')
end
def delete_auth_file!
path = Util::FileManage.disk_professional_auth_filename(user.id)
File.delete(path) if File.exists?(path)
apply.update!(is_delete: true)
end
end

View File

@@ -0,0 +1,42 @@
class Admins::ProfessionalAuths::RefuseApplyService < ApplicationService
attr_reader :apply, :user, :params
def initialize(apply, params)
@apply = apply
@user = apply.user
@params = params
end
def call
ActiveRecord::Base.transaction do
apply.update!(status: 2, remarks: reason)
user.update!(professional_certification: false)
deal_tiding!
apply.attachment&.destroy
# delete_auth_file!
end
end
private
def reason
params[:reason].to_s.strip
end
def deal_tiding!
apply.tidings.where(tiding_type: 'Apply').update_all(status: 1)
Tiding.create!(user_id: apply.user_id, trigger_user_id: 0,
container_id: apply.id, container_type: 'ApplyUserAuthentication',
belong_container_id: apply.user_id, belong_container_type: 'User',
status: 2, tiding_type: 'System')
end
def delete_auth_file!
path = Util::FileManage.disk_professional_auth_filename(user.id)
File.delete(path) if File.exists?(path)
apply.update!(is_delete: true)
end
end

View File

@@ -0,0 +1,26 @@
class Admins::ProfessionalAuths::RevokeApplyService < ApplicationService
attr_reader :apply, :user
def initialize(apply)
@apply = apply
@user = apply.user
end
def call
ActiveRecord::Base.transaction do
apply.revoke!
user.update!(professional_certification: false)
deal_tiding!
end
end
private
def deal_tiding!
Tiding.create!(user_id: apply.user_id, trigger_user_id: 0,
container_id: apply.id, container_type: 'CancelUserProCertification',
belong_container_id: apply.user_id, belong_container_type: 'User',
status: 1, tiding_type: 'System')
end
end

View File

@@ -0,0 +1,56 @@
class Admins::SaveLaboratorySettingService < ApplicationService
attr_reader :laboratory, :laboratory_setting, :params
def initialize(laboratory, params)
@params = params
@laboratory = laboratory
@laboratory_setting = laboratory.laboratory_setting
end
def call
ActiveRecord::Base.transaction do
laboratory.identifier = strip params[:identifier]
laboratory_setting.name = strip params[:name]
laboratory_setting.navbar = navbar_config
laboratory_setting.footer = strip params[:footer]
laboratory.save!
laboratory_setting.save!
deal_image_file
end
laboratory
end
private
def navbar_config
params[:navbar].map do |nav|
hash = {}
hash[:name] = strip nav[:name]
hash[:link] = strip nav[:link]
hash[:hidden] = nav[:hidden].to_s != '0'
hash
end
end
def deal_image_file
save_image_file(params[:nav_logo], 'nav')
save_image_file(params[:login_logo], 'login')
save_image_file(params[:tab_logo], 'tab')
save_image_file(params[:subject_banner], '_subject_banner')
save_image_file(params[:course_banner], '_course_banner')
save_image_file(params[:competition_banner], '_competition_banner')
save_image_file(params[:moop_cases_banner], '_moop_cases_banner')
save_image_file(params[:oj_banner], '_oj_banner')
end
def save_image_file(file, type)
return unless file.present? && file.is_a?(ActionDispatch::Http::UploadedFile)
file_path = Util::FileManage.source_disk_filename(laboratory_setting, type)
File.delete(file_path) if File.exist?(file_path) # 删除之前的文件
Util.write_file(file, file_path)
end
end

View File

@@ -0,0 +1,37 @@
class Admins::SaveMirrorRepositoryService < ApplicationService
Error = Class.new(StandardError)
attr_reader :mirror, :user, :params
def initialize(mirror, user, params)
@mirror = mirror
@user = user
@params = params
end
def call
mirror.assign_attributes(params)
raise Error, '镜像别名重复' if MirrorRepository.where.not(id: mirror.id).exists?(type_name: params[:type_name])
ActiveRecord::Base.transaction do
record_operation! if mirror.persisted?
mirror.save!
end
end
private
def record_operation!
if mirror.type_name_changed?
MirrorOperationRecord.create!(mirror_repository_id: mirror.id, status: 5,
user_id: user.id, old_tag: mirror.type_name_in_database,
new_tag: mirror.type_name)
elsif mirror.status_changed?
MirrorOperationRecord.create!(mirror_repository_id: mirror.id, status: 5,
user_id: user.id, old_tag: mirror.status_in_database,
new_tag: mirror.status)
end
end
end

View File

@@ -0,0 +1,123 @@
class Admins::SchoolDailyStatisticService < ApplicationService
include CustomSortable
attr_reader :params
sort_columns :student_count, :teacher_count, :homework_count, :other_homework_count,
:course_count, :active_course_count, :nearly_course_time, :shixun_count, :shixun_evaluate_count,
default_by: :teacher_count, default_direction: :desc
def initialize(params)
@params = params
end
def call
schools = School.group('schools.id')
keyword = params[:keyword].try(:to_s).try(:strip)
if keyword.present?
schools = schools.where("schools.name LIKE :keyword OR schools.id LIKE :keyword", keyword: "%#{keyword}%")
end
count = schools.count.count
# 根据排序字段进行查询
schools = query_by_sort_column(schools, params[:sort_by])
schools = custom_sort(schools, params[:sort_by], params[:sort_direction])
schools = schools.limit(page_size).offset(offset)
# 查询并组装其它数据
schools = package_other_data(schools)
[count, schools]
end
def package_other_data(schools)
ids = schools.map(&:id)
student_map = UserExtension.where(school_id: ids, identity: :student).group(:school_id).count
teacher_map = UserExtension.where(school_id: ids, identity: :teacher).group(:school_id).count
homeworks = HomeworkCommon.joins(:course)
shixun_homework_map = homeworks.where(homework_type: 4, courses: { school_id: ids }).group('school_id').count
other_homework_map = homeworks.where(homework_type: [1, 3], courses: { school_id: ids }).group('school_id').count
courses = Course.where(is_delete: 0, school_id: ids).group('school_id')
course_map = courses.count
nearly_course_time_map = courses.joins(:course_acts).maximum('course_activities.updated_at')
active_course_map = courses.where(is_end: false).count
shixun_map = Shixun.joins(user: :user_extension).where(user_extensions: { identity: :teacher, school_id: ids })
.where(fork_from: nil).group('school_id').count
reports = SchoolReport.where(school_id: ids)
evaluate_count_map = reports.each_with_object({}) { |report, obj| obj[report.school_id] = report.shixun_evaluate_count }
schools.map do |school|
{
id: school.id,
name: school.name,
teacher_count: teacher_map[school.id],
student_count: student_map[school.id],
homework_count: shixun_homework_map[school.id],
other_homework_count: other_homework_map[school.id],
course_count: course_map[school.id],
nearly_course_time: nearly_course_time_map[school.id],
active_course_count: active_course_map[school.id],
shixun_count: shixun_map.fetch(school.id, 0),
shixun_evaluate_count: evaluate_count_map.fetch(school.id, 0)
}
end
end
private
def query_by_sort_column(schools, sort_by_column)
base_query_column = 'schools.id, schools.name'
case sort_by_column.to_s
when 'teacher_count' then
schools.joins('LEFT JOIN user_extensions ue ON ue.school_id = schools.id AND ue.identity = 0')
.select("#{base_query_column}, COUNT(*) teacher_count")
when 'student_count' then
schools.joins('LEFT JOIN user_extensions ue ON ue.school_id = schools.id AND ue.identity = 1')
.select("#{base_query_column}, COUNT(*) student_count")
when 'homework_count' then
schools.joins('LEFT JOIN courses ON courses.school_id = schools.id')
.joins('LEFT JOIN homework_commons hc ON hc.course_id = courses.id AND hc.homework_type = 4')
.select("#{base_query_column}, COUNT(*) homework_count")
when 'other_homework_count' then
schools.joins('LEFT JOIN courses ON courses.school_id = schools.id')
.joins('LEFT JOIN homework_commons hc ON hc.course_id = courses.id AND hc.homework_type IN (1, 3)')
.select("#{base_query_column}, COUNT(*) other_homework_count")
when 'course_count' then
schools.joins('LEFT JOIN courses cs ON cs.school_id = schools.id AND cs.is_delete = 0')
.select("#{base_query_column}, COUNT(*) course_count")
when 'shixun_count' then
schools.joins('LEFT JOIN user_extensions ue ON ue.school_id = schools.id AND ue.identity = 0')
.joins('LEFT JOIN users ON users.id = ue.user_id')
.joins('LEFT JOIN shixuns sx ON sx.user_id = users.id AND sx.fork_from IS NULL')
.select("#{base_query_column}, COUNT(*) shixun_count")
when 'shixun_evaluate_count' then
schools.joins('LEFT JOIN school_reports ON school_reports.school_id = schools.id')
.select("#{base_query_column}, shixun_evaluate_count")
when 'nearly_course_time' then
schools.joins('LEFT JOIN courses cs ON cs.school_id = schools.id AND cs.is_delete = 0')
.joins('LEFT JOIN course_activities acs ON acs.course_id = cs.id')
.select("#{base_query_column}, MAX(acs.updated_at) nearly_course_time")
when 'active_course_count' then
schools.joins('LEFT JOIN courses cs ON cs.school_id = schools.id AND cs.is_delete = 0 AND cs.is_end = false')
.select("#{base_query_column}, COUNT(*) active_course_count")
else
schools.joins('LEFT JOIN user_extensions ue ON ue.school_id = schools.id AND ue.identity = 0')
.select("#{base_query_column}, COUNT(*) teacher_count")
end
end
def page_size
params[:per_page] || 20
end
def offset
(params[:page].to_i.zero? ? 0 : params[:page].to_i - 1) * page_size
end
end

View File

@@ -0,0 +1,43 @@
class Admins::ShixunAuths::AgreeApplyService < ApplicationService
attr_reader :apply, :user, :shixun
def initialize(apply, user)
@apply = apply
@user = user
@shixun = Shixun.find(apply.container_id)
end
def call
ActiveRecord::Base.transaction do
apply.update!(status: 1, dealer_id: user.id)
shixun.update!(public: 2, publish_time: Time.now)
# 奖励金币、经验
reward_grade_and_experience!
deal_tiding!
end
end
private
def reward_grade_and_experience!
score = shixun.all_score
shixun_creator = shixun.user
RewardGradeService.call(shixun_creator, container_id: shixun.id, container_type: 'shixunPublish', score: score)
Experience.create!(user_id: shixun_creator.id, container_id: shixun.id, container_type: 'shixunPublish', score: score)
shixun_creator.update_column(:experience, shixun_creator.experience.to_i + score)
end
def deal_tiding!
apply.tidings.where(tiding_type: 'Apply', status: 0).update_all(status: 1)
Tiding.create!(user_id: apply.user_id, trigger_user_id: 0,
container_id: apply.id, container_type: 'ApplyAction',
parent_container_id: apply.container_id, parent_container_type: apply.container_type,
belong_container_id: apply.container_id, belong_container_type: 'Shixun',
status: 1, tiding_type: 'System')
end
end

View File

@@ -0,0 +1,35 @@
class Admins::ShixunAuths::RefuseApplyService < ApplicationService
attr_reader :apply, :user, :shixun, :params
def initialize(apply, user, params)
@apply = apply
@user = user
@shixun = Shixun.find(apply.container_id)
@params = params
end
def call
ActiveRecord::Base.transaction do
shixun.update!(public: 0)
apply.update!(status: 2, reason: reason, dealer_id: user.id)
deal_tiding!
end
end
private
def reason
params[:reason].to_s.strip
end
def deal_tiding!
apply.tidings.where(tiding_type: 'Apply', status: 0).update_all(status: 1)
Tiding.create!(user_id: apply.user_id, trigger_user_id: 0,
container_id: apply.id, container_type: 'ApplyAction',
parent_container_id: apply.container_id, parent_container_type: apply.container_type,
belong_container_id: apply.container_id, belong_container_type: 'Shixun',
status: 2, tiding_type: 'System')
end
end

View File

@@ -0,0 +1,80 @@
class Admins::StatisticSchoolContrastDataService < ApplicationService
ParameterError = Class.new(StandardError)
PAGE_SIZE = 20
CONTRAST_COLUMN_LIST = %w(
teacher_increase_count student_increase_count course_increase_count
shixun_increase_count active_user_count shixun_homework_count shixun_evaluate_count
).freeze
attr_reader :params, :sort_direction, :contrast_column
def initialize(params)
@params = params
@sort_direction = params[:sort_direction].to_s
@contrast_column = params[:contrast_column].to_s
end
def call
validate_parameter!
reports = School.joins(:school_daily_reports).select(select_columns)
keyword = params[:keyword].try(:to_s).try(:strip)
if keyword.present?
reports = reports.where("schools.name LIKE :keyword OR schools.id LIKE :keyword", keyword: "%#{keyword}%")
end
count = reports.count('distinct(schools.id)')
sql = query_report_sql(reports.group('schools.id').to_sql)
reports = SchoolDailyReport.find_by_sql(sql)
[count, reports]
end
private
def validate_parameter!
if %i[begin_date end_date other_begin_date other_end_date].any? { |key| params[key].blank? }
raise ParameterError
end
unless %w(desc asc).include?(sort_direction)
raise ParameterError
end
unless CONTRAST_COLUMN_LIST.include?(contrast_column)
raise ParameterError
end
end
def format_date(date)
Time.zone.parse(date).strftime("%Y-%m-%d")
end
def offset
(params[:page].to_i.zero? ? 0 : params[:page].to_i - 1) * PAGE_SIZE
end
def select_columns
if contrast_column != 'active_user_count'
"schools.id school_id, schools.name school_name,"\
"(SUM(IF(date BETWEEN '#{format_date(params[:begin_date])}' AND '#{format_date(params[:end_date])}', #{contrast_column}, 0))) total,"\
"(SUM(IF(date BETWEEN '#{format_date(params[:other_begin_date])}' AND '#{format_date(params[:other_end_date])}', #{contrast_column}, 0))) other_total"
else
# 活跃用户对比时处理方法不同
relations = SchoolDailyActiveUser.select('COUNT(distinct user_id)').joins(:school_daily_report)
.where('school_id = schools.id')
total_subquery = relations.where("date BETWEEN '#{format_date(params[:begin_date])}' AND '#{format_date(params[:end_date])}'").to_sql
other_total_subquery = relations.where("date BETWEEN '#{format_date(params[:other_begin_date])}' AND '#{format_date(params[:other_end_date])}'").to_sql
"schools.id school_id, schools.name school_name, (#{total_subquery}) AS total, (#{other_total_subquery}) AS other_total"
end
end
def query_report_sql(from_sql)
order_by = "(total = 0 AND other_total != 0) #{sort_direction}, (percentage != 0) #{sort_direction}, percentage #{sort_direction}"
"SELECT reports.*, (other_total - total) increase, (IF(other_total - total = 0, 0.0, round((other_total - total) / IF(total = 0, 1, total), 5))) percentage "\
"FROM (#{from_sql}) reports ORDER BY #{order_by} LIMIT #{PAGE_SIZE} OFFSET #{offset}"
end
end

View File

@@ -0,0 +1,107 @@
class Admins::StatisticSchoolDataGrowService < ApplicationService
include CustomSortable
PAGE_SIZE = 20
attr_reader :params
sort_columns :teacher_increase_count, :student_increase_count,
:course_increase_count, :shixun_increase_count, :uniq_active_user_count,
:shixun_homework_count, :shixun_evaluate_count,
default_by: :teacher_increase_count, default_direction: :desc
def initialize(params)
@params = params
end
def call
reports = School.where(nil)
reports = search_filter(reports)
count = reports.count
subquery = SchoolDailyActiveUser.select('COUNT(distinct(user_id))').joins(:school_daily_report)
.where(date_condition_sql).where("school_id is not null and school_id = schools.id").to_sql
reports = reports.joins("LEFT JOIN school_daily_reports sdr ON sdr.school_id = schools.id AND #{date_condition_sql}")
reports = reports.select(
'schools.id school_id, schools.name school_name,'\
'SUM(teacher_increase_count) teacher_increase_count,'\
'SUM(student_increase_count) student_increase_count,'\
'SUM(course_increase_count) course_increase_count,'\
'SUM(shixun_increase_count) shixun_increase_count,'\
'SUM(shixun_homework_count) shixun_homework_count,'\
'SUM(shixun_evaluate_count) shixun_evaluate_count,'\
"(#{subquery}) uniq_active_user_count,"\
'SUM(active_user_count) active_user_count').group('schools.id')
reports = custom_sort(reports, params[:sort_by], params[:sort_direction])
reports = reports.order('school_id asc').limit(PAGE_SIZE).offset(offset)
[count, reports]
end
def grow_summary
@_grow_summary ||= begin
reports = School.joins("LEFT JOIN school_daily_reports sdr ON sdr.school_id = schools.id")
.where(date_condition_sql)
subquery = SchoolDailyActiveUser.select('COUNT(distinct user_id)')
.joins('LEFT JOIN school_daily_reports sdr ON sdr.id = school_daily_active_users.school_daily_report_id')
.where(date_condition_sql).to_sql
reports = search_filter(reports)
reports.select(
'SUM(teacher_increase_count) teacher_increase_count,'\
'SUM(student_increase_count) student_increase_count,'\
'SUM(course_increase_count) course_increase_count,'\
'SUM(shixun_increase_count) shixun_increase_count,'\
'SUM(shixun_homework_count) shixun_homework_count,'\
'SUM(shixun_evaluate_count) shixun_evaluate_count,'\
"(#{subquery}) uniq_active_user_count,"\
'SUM(active_user_count) active_user_count'
).first
end
end
private
def search_filter(relations)
keyword = params[:keyword].try(:to_s).try(:strip)
if keyword.present?
relations = relations.where("schools.name LIKE :keyword OR schools.id LIKE :keyword", keyword: "%#{keyword}%")
end
relations
end
def date_condition_sql
date = query_date
if date.is_a?(Range)
"date BETWEEN '#{date.min.strftime('%Y-%m-%d')}' AND '#{date.max.strftime('%Y-%m-%d')}'"
else
"date = '#{date.strftime('%Y-%m-%d')}'"
end
end
def query_date
if params[:grow_begin_date].present?
begin_time = Time.zone.parse(params[:grow_begin_date])
end_date = if params[:grow_end_date].present?
Time.zone.parse(params[:grow_end_date])
end
end_date.blank? || end_date == begin_time ? begin_time : begin_time..end_date
else
yesterday
end
end
def yesterday
# 每日凌晨5点为节点, 25日凌晨4点、3点、2点等等未到更新数据时间点看到的数据是23日-24日的统计数据
(Time.zone.now - 5.hours).beginning_of_day - 1.days
end
def offset
(params[:page].to_i.zero? ? 0 : params[:page].to_i - 1) * PAGE_SIZE
end
end

View File

@@ -0,0 +1,30 @@
class Admins::SubjectAuths::AgreeApplyService < ApplicationService
attr_reader :apply, :user, :subject
def initialize(apply, user)
@apply = apply
@user = user
@subject = Subject.find(apply.container_id)
end
def call
ActiveRecord::Base.transaction do
apply.update!(status: 1, dealer_id: user.id)
subject.update!(public: 2, publish_time: Time.now)
deal_tiding!
end
end
private
def deal_tiding!
apply.tidings.where(tiding_type: 'Apply', status: 0).update_all(status: 1)
Tiding.create!(user_id: apply.user_id, trigger_user_id: 0,
container_id: apply.id, container_type: 'ApplyAction',
parent_container_id: apply.container_id, parent_container_type: apply.container_type,
belong_container_id: apply.container_id, belong_container_type: 'Subject',
status: 1, tiding_type: 'System')
end
end

View File

@@ -0,0 +1,35 @@
class Admins::SubjectAuths::RefuseApplyService < ApplicationService
attr_reader :apply, :user, :subject, :params
def initialize(apply, user, params)
@apply = apply
@user = user
@subject = Subject.find(apply.container_id)
@params = params
end
def call
ActiveRecord::Base.transaction do
subject.update!(public: 0)
apply.update!(status: 2, reason: reason, dealer_id: user.id)
deal_tiding!
end
end
private
def reason
params[:reason].to_s.strip
end
def deal_tiding!
apply.tidings.where(tiding_type: 'Apply', status: 0).update_all(status: 1)
Tiding.create!(user_id: apply.user_id, trigger_user_id: 0,
container_id: apply.id, container_type: 'ApplyAction',
parent_container_id: apply.container_id, parent_container_type: apply.container_type,
belong_container_id: apply.container_id, belong_container_type: 'Subject',
status: 2, tiding_type: 'System')
end
end

View File

@@ -0,0 +1,55 @@
class Admins::UpdateUserService < ApplicationService
Error = Class.new(StandardError)
attr_reader :user, :params
def initialize(user, params)
@user = user
@params = params
end
def call
user.assign_attributes(user_attributes)
user.mail = params[:mail].to_s.presence
user.phone = params[:phone].to_s.presence
user.firstname = ''
user.password = params[:password] if params[:password].present?
if params[:identity].to_s == 'student'
params[:technical_title] = nil
else
params[:student_id] = nil
end
user.user_extension.assign_attributes(user_extension_attributes)
ActiveRecord::Base.transaction do
user.save!
user.user_extension.save!
user.update!(is_shixun_marker: true) if user.is_certification_teacher
update_gitlab_password if params[:password].present?
end
user
end
private
def user_attributes
params.slice(*%i[lastname nickname mail phone admin business is_test
professional_certification authentication is_shixun_marker])
end
def user_extension_attributes
params.slice(*%i[gender identity technical_title student_id location location_city school_id department_id])
end
def update_gitlab_password
return if user.gid.blank?
# 同步修改gitlab密码
Gitlab.client.edit_user(user.gid, password: params[:password])
rescue Exception => ex
Util.logger_error(ex)
raise Error, '保存失败'
end
end