答辩预览版

master
pan 3 years ago
parent 7e43a143a5
commit 99b2545925
  1. 144
      module/src/main/kotlin/com/gyf/csams/module/ShareVo.kt
  2. 6
      src/main/kotlin/com/gyf/csams/Application.kt
  3. 77
      src/main/kotlin/com/gyf/csams/Controller.kt
  4. 67
      src/main/kotlin/com/gyf/csams/Dao.kt
  5. 3
      src/main/kotlin/com/gyf/csams/MySQL.kt
  6. 385
      src/main/kotlin/com/gyf/csams/Service.kt
  7. 19
      test/ApplicationTest.kt

@ -1,7 +1,5 @@
package com.gyf.csams.module package com.gyf.csams.module
import java.util.*
data class ApiResponse<T>(val code: Int = 200, val message: String, val body: T? = null) data class ApiResponse<T>(val code: Int = 200, val message: String, val body: T? = null)
class Simple { class Simple {
@ -183,8 +181,6 @@ data class UserLoginVo(
override val clientType: ClientType = ClientType.Foreground override val clientType: ClientType = ClientType.Foreground
) : BaseLoginVo() ) : BaseLoginVo()
data class UserResDto(val password: String)
data class ManagerLoginVo( data class ManagerLoginVo(
val account: String, val account: String,
override val password: String, override val device: String override val password: String, override val device: String
@ -262,55 +258,6 @@ data class SendBBSVo(val content:String,
*/ */
data class SearchCommentVo(val activityId: Int) data class SearchCommentVo(val activityId: Int)
/**
* 题型
*
*/
enum class ExamType(val type: String) {
//选择题
CQ("选择题"),
//开放题
OQ("开放题")
}
abstract class Exam {
abstract val examType: ExamType
//**TODO 题目反序列化
abstract val question:String
// abstract val question: StringForm
}
/**
* 选择题
*
* @property examType 题型描述
* @property answers 答案
* @property rightAnswer 正确答案
* @property question 问题
* TODO 题目反序列化
*/
data class ChoiceQuestionVo(
override val examType: ExamType = ExamType.CQ,
// val answers: List<StringForm>,
val answers: List<String>,
val rightAnswer: Int,
override val question: String
) : Exam()
/**
* 开放题
*
* @property examType 题型描述
* @property question 问题
* TODO 题目反序列化
*/
data class OpenQuestionsVo(
override val examType: ExamType = ExamType.OQ, override val question: String
) : Exam()
data class LeaveMessageFormatVo(val message: String, val user: UserInfoVo) data class LeaveMessageFormatVo(val message: String, val user: UserInfoVo)
@ -393,6 +340,15 @@ data class AssociationMainVo(
val photos: List<AssociationActPhotoVo>? = null val photos: List<AssociationActPhotoVo>? = null
) )
/**
* 通用审核进度
*
* @property checkStatus
* @property applyTime
* @property firstCause
* @property lastCause
* @property result
*/
data class AuditCheckVo( data class AuditCheckVo(
val checkStatus: CheckStatus, val checkStatus: CheckStatus,
val applyTime: Long, val applyTime: Long,
@ -435,8 +391,10 @@ abstract class AuditVo {
* *
*/ */
data class AuditAssociationVo( data class AuditAssociationVo(
val name: String, val desc: String, val name: String,
val logo: String, override val audit: AuditLoggingVo val desc: String,
val logo: String,
override val audit: AuditLoggingVo
) : AuditVo() ) : AuditVo()
/** /**
@ -510,7 +468,6 @@ data class ActivityApplyVo(
* *
*/ */
data class AuditActVo( data class AuditActVo(
val auditId: Int,
val activityVo: ActivityVo, val activityVo: ActivityVo,
override val audit: AuditLoggingVo override val audit: AuditLoggingVo
) : AuditVo() ) : AuditVo()
@ -522,7 +479,6 @@ data class AuditActVo(
* @property auditCheckVo * @property auditCheckVo
*/ */
data class ActivityCheckVo( data class ActivityCheckVo(
val activityId:Int,
val activityVo: ActivityVo, val activityVo: ActivityVo,
val auditCheckVo: AuditCheckVo val auditCheckVo: AuditCheckVo
) )
@ -591,24 +547,80 @@ data class ManagerActVo(
data class AllOfficerVo( data class AllOfficerVo(
val secretariat: MutableList<ManagerInfoVo>, val secretariat: List<ManagerInfoVo>,
val propaganda: MutableList<ManagerInfoVo>, val propaganda: List<ManagerInfoVo>,
val publicRelationsDepartment: MutableList<ManagerInfoVo> val publicRelationsDepartment: List<ManagerInfoVo>
) )
/** /**
* 换名申请表 * 换名申请表
* *
* @property studentId 学号
* @property oldName 社团原名
* @property newName 社团新名 * @property newName 社团新名
* @property reason 申请理由 * @property cause 申请理由
*/ */
data class RenameVo( data class RenameVo(
val studentId: String, val renameId:Int?=null,
val oldName: String,
val newName: String, val newName: String,
val reason: String val cause: String
) )
/**
* 前台申请换名
*
* @property rename
*/
data class RenameApplyVo(
val associationId: Int,
val rename:RenameVo,
override val token: Token,
override val clientType: ClientType = ClientType.Foreground
):ClientBaseVo()
/**
* 社团命名审核记录
*
* @property renameVo
* @property audit
*/
data class AuditRenameVo(
val associationVo: AssociationVo,
val renameVo: RenameVo,
override val audit: AuditLoggingVo
):AuditVo()
/**
* 重命名审核进度
*
* @property renameVo
* @property auditCheckVo
*/
data class RenameCheckVo(
val renameVo: RenameVo,
val auditCheckVo: AuditCheckVo
)
/**
* 主页轮播
*
* @property url
*/
data class MainActivityPhotoVo(val url:String, val activityVo: ActivityVo,val associationVo: AssociationVo)
/**
* 更新社团
*
* @property associationVo
* @property token
* @property clientType
*/
data class UpdateAssociationVo(val associationVo: AssociationVo,
override val token: Token,
override val clientType: ClientType
):ClientBaseVo()
data class ManagerDutyVo(val manager: ManagerInfoVo,val people:Int)
data class ManagerDutySumVo(val secretariat:ManagerDutyVo,
val propaganda:ManagerDutyVo,
val publicRelationsDepartment:ManagerDutyVo)

@ -7,8 +7,6 @@ import io.ktor.http.*
fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args) fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)
@Suppress("unused") // Referenced in application.conf
@kotlin.jvm.JvmOverloads
fun Application.module() { fun Application.module() {
install(CORS) { install(CORS) {
method(HttpMethod.Options) method(HttpMethod.Options)
@ -41,7 +39,9 @@ fun Application.Controller() {
/** /**
* 初始化log * 初始化log
*/ */
listOf(MainService,AccountService,FileService,AssociationService,BackgroundService,NotificationService,ActivityService).forEach { listOf(MainService,AccountService,FileService,AssociationService,
BackgroundService,NotificationService,ActivityService,
RenameService).forEach {
it.init(environment) it.init(environment)
} }

@ -144,6 +144,18 @@ fun Application.AccountController() {
} }
} }
route("/load/manager"){
post{
call.withToken<OnlyToken> {
call.respond(ApiResponse(message = "部门概况信息加载成功",body=BackgroundService.load()))
}
}
post("/detail"){
call.withToken<OnlyToken> {
call.respond(ApiResponse(message = "部门详情加载成功",body=BackgroundService.loadDetail()))
}
}
}
post(path = "/logout") { post(path = "/logout") {
@ -178,6 +190,13 @@ fun Application.MainController() {
call.respond(ApiResponse(message = "留言获取成功", body = s)) call.respond(ApiResponse(message = "留言获取成功", body = s))
} }
} }
post("/hotActivity"){
call.withToken<OnlyToken> {
call.respond(ApiResponse(message = "活动轮播图获取成功",
body=ActivityService.random()))
}
}
} }
} }
} }
@ -319,6 +338,7 @@ object AuditController{
/** /**
* 社团接口 * 社团接口
* *
*/ */
fun Application.AssociationController() { fun Application.AssociationController() {
routing { routing {
@ -330,6 +350,23 @@ fun Application.AssociationController() {
check(AssociationService) check(AssociationService)
read(AssociationService,Associations) read(AssociationService,Associations)
route("/rename"){
register(RenameService)
accept(RenameService)
audit(RenameService)
check(RenameService)
read(RenameService,Renames)
}
post("/update"){
call.withToken<UpdateAssociationVo> {
AssociationService.update(vo=it.associationVo)
call.respond(ApiResponse(message = "社团更新成功",body = true))
}
}
post("/uploadLogo") { post("/uploadLogo") {
log.info("开始上传logo") log.info("开始上传logo")
@ -349,19 +386,35 @@ fun Application.AssociationController() {
log.info("----end-----") log.info("----end-----")
} }
post("/list"){ route("/list"){
log.info("开始查询社团") post{
call.withToken<SearchAssociationVo>{ log.info("开始查询社团")
try { call.withToken<SearchAssociationVo>{
call.respond(ApiResponse(message = "社团列表检索完成",body=AssociationService.load(vo=it))) try {
} catch (e: Exception) { call.respond(ApiResponse(message = "社团列表检索完成",body=AssociationService.load(vo=it)))
log.error(e) } catch (e: Exception) {
call.respond(ApiResponse(message = "社团列表检索失败",body=null)) log.error(e)
call.respond(ApiResponse(message = "社团列表检索失败",body=null))
}
} }
log.info("----end-----")
}
post("/all"){
log.info("获取所有社团")
call.withToken<OnlyToken>{
try {
call.respond(ApiResponse(message = "社团列表检索完成",body=AssociationService.loadAll()))
} catch (e: Exception) {
log.error(e)
call.respond(ApiResponse(message = "社团列表检索失败",body=null))
}
}
log.info("----end-----")
} }
log.info("----end-----")
} }
route("/load"){ route("/load"){
post{ post{
log.info("社团id查询") log.info("社团id查询")
@ -404,6 +457,12 @@ fun Application.ActivityController(){
check(ActivityService) check(ActivityService)
read(ActivityService,Activities) read(ActivityService,Activities)
post("/list/all"){
call.withToken<OnlyToken> {
call.respond(ApiResponse(message = "活动信息加载",body = ActivityService.listAll()))
}
}
post("/load"){ post("/load"){
val searchActivityVo=call.receive<SearchActivityVo>() val searchActivityVo=call.receive<SearchActivityVo>()
call.respond(ApiResponse(message = "活动列表加载成功",body = ActivityService.load(vo=searchActivityVo))) call.respond(ApiResponse(message = "活动列表加载成功",body = ActivityService.load(vo=searchActivityVo)))

@ -184,7 +184,7 @@ class Association(id:EntityID<Int>):AbstractAudit(id){
var name by Associations.name var name by Associations.name
var desc by Associations.desc var desc by Associations.desc
var logo by ImageFile referencedOn Associations.logo var logo by ImageFile referencedOn Associations.logo
val level by Associations.level var level by Associations.level
var faculty by Associations.faculty var faculty by Associations.faculty
override var audit by AuditLogging referencedOn Associations.auditId override var audit by AuditLogging referencedOn Associations.auditId
@ -367,4 +367,69 @@ class ActivityComment(id:EntityID<Int>):IntEntity(id){
var createTime by ActivityComments.createTime var createTime by ActivityComments.createTime
var user by User referencedOn ActivityComments.userId var user by User referencedOn ActivityComments.userId
var activity by Activity referencedOn ActivityComments.activityId var activity by Activity referencedOn ActivityComments.activityId
}
@TableComment("社团重命名记录")
object Renames:AbstractAudits(){
@TableComment("新名称")
val newName:Column<String> = varchar("new_name",length = 10)
@TableComment("换名理由")
val cause:Column<String> = varchar("cause",length = 30)
@TableComment("重命名社团")
val associationId:Column<EntityID<Int>> = reference("association_id",Associations)
@TableComment("审核信息")
override val auditId:Column<EntityID<Int>> = reference("audit_id",AuditLeggings)
}
class Rename(id:EntityID<Int>):AbstractAudit(id){
companion object:IntEntityClass<Rename>(Renames)
var newName by Renames.newName
var cause by Renames.cause
var association by Association referencedOn Renames.associationId
override var audit by AuditLogging referencedOn Renames.auditId
override fun notificationName(): String {
return "${association.name} -> $newName"
}
}
@TableComment("题库")
object Questions:IntIdTable(){
@TableComment("问题")
val question:Column<String> = varchar("question",30)
@TableComment("选项A")
val optionsA:Column<String> = varchar("optionsA",15)
@TableComment("选项B")
val optionsB:Column<String> = varchar("optionsB",15)
@TableComment("选项C")
val optionsC:Column<String> = varchar("optionsC",15)
@TableComment("选项D")
val optionsD:Column<String> = varchar("optionsD",15)
@TableComment("所属社团")
val associationId:Column<EntityID<Int>> = reference("association_id",Associations)
}
class Question(id:EntityID<Int>):IntEntity(id){
companion object:IntEntityClass<Question>(Questions)
var question by Questions.question
var optionsA by Questions.optionsA
var optionsB by Questions.optionsB
var optionsC by Questions.optionsC
var optionsD by Questions.optionsD
}
@TableComment("试卷")
object TestPapers:IntIdTable(){
@TableComment("问题")
val questionId:Column<EntityID<Int>> = reference("question_id",Questions)
} }

@ -41,7 +41,8 @@ fun Application.MySQL() {
fun initTable(){ fun initTable(){
transaction { transaction {
val tableList= arrayOf(Users,UserTokens,Managers,ManagerTokens,AuditLeggings,LeaveMessages, val tableList= arrayOf(Users,UserTokens,Managers,ManagerTokens,AuditLeggings,LeaveMessages,
ImageFiles,Associations,AssociationMembers,Notifications,Activities,PhotoAlbums,ActivityComments) ImageFiles,Associations,AssociationMembers,Notifications,Activities,PhotoAlbums,ActivityComments,
Renames)
SchemaUtils.createMissingTablesAndColumns(*tableList) SchemaUtils.createMissingTablesAndColumns(*tableList)
updateComment(*tableList) updateComment(*tableList)

@ -6,6 +6,7 @@ import com.gyf.csams.module.*
import io.ktor.application.* import io.ktor.application.*
import io.ktor.http.content.* import io.ktor.http.content.*
import io.ktor.util.* import io.ktor.util.*
import org.jetbrains.exposed.dao.IntEntityClass
import org.jetbrains.exposed.dao.id.EntityID import org.jetbrains.exposed.dao.id.EntityID
import org.jetbrains.exposed.dao.id.IntIdTable import org.jetbrains.exposed.dao.id.IntIdTable
import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.*
@ -46,16 +47,16 @@ object AccountService : AbstractService() {
/** /**
* 注册 * 注册
*/ */
fun register(userVo: UserRegVo): UserResDto? { fun register(userVo: UserRegVo): String? {
try { try {
return transaction { return transaction {
val originPassword = if (environment.developmentMode) "12345678" else randomNum(8) val originPassword = randomNum(8)
User.new { User.new {
studentId = userVo.studentId studentId = userVo.studentId
name = userVo.name name = userVo.name
password = originPassword.md5() password = originPassword.md5()
} }
return@transaction UserResDto(password = originPassword) return@transaction originPassword
} }
} catch (e: Exception) { } catch (e: Exception) {
log.error("注册失败,发生异常:$e") log.error("注册失败,发生异常:$e")
@ -248,10 +249,10 @@ object AccountService : AbstractService() {
} }
fun <T : ClientBaseVo> validToken(vo: T): Boolean { fun <T : ClientBaseVo> validToken(vo: T): Boolean {
return if (vo.clientType == ClientType.Foreground) { return when(vo.clientType){
validUserToken(vo.token) ClientType.Foreground->validUserToken(vo.token)
} else { ClientType.Background-> validManagerToken(vo.token)
validManagerToken(vo.token) else->throw IllegalArgumentException("不清楚是来自哪个平台的token信息")
} }
} }
@ -438,7 +439,7 @@ abstract class AuditService<T, E, F> : AbstractService() {
* @param receiverId * @param receiverId
* @param content * @param content
*/ */
protected fun foreground(receiverId: Int, content: String) { private fun foreground(receiverId: Int, content: String) {
Notification.new { Notification.new {
this.title = dataType this.title = dataType
this.content = content this.content = content
@ -454,7 +455,7 @@ abstract class AuditService<T, E, F> : AbstractService() {
* 前台任务通知管理员处理 * 前台任务通知管理员处理
* *
*/ */
protected fun background(content: String, duty: Duty) { private fun background(content: String, duty: Duty) {
Manager.find { Managers.duty eq duty.name }.apply { Manager.find { Managers.duty eq duty.name }.apply {
if (count() == 0L) { if (count() == 0L) {
log.warn("找不到适当的${duty.desc}处理此任务") log.warn("找不到适当的${duty.desc}处理此任务")
@ -481,6 +482,10 @@ abstract class AuditService<T, E, F> : AbstractService() {
*/ */
abstract fun findEntity(auditId: Int): AbstractAudit abstract fun findEntity(auditId: Int): AbstractAudit
protected inline fun <reified E:AbstractAudit,reified Row:IntEntityClass<E>,reified Table:AbstractAudits> testFind(table:Table,row:Row,auditId: Int): E {
return row.find { table.auditId eq auditId } .firstOrNull() ?: throw AuditIdError(auditId)
}
/** /**
* 更新审核结果 * 更新审核结果
* *
@ -508,7 +513,7 @@ abstract class AuditService<T, E, F> : AbstractService() {
* 通过审核后 * 通过审核后
* *
*/ */
protected abstract fun afterAudit(entity: AbstractAudit) protected open fun afterAudit(entity: AbstractAudit){}
/** /**
* 资料受理 * 资料受理
@ -602,19 +607,36 @@ abstract class AuditService<T, E, F> : AbstractService() {
} }
} }
//过滤完成的审核记录?(可多次提交的资料)
open val isFilter:Boolean=true
/** /**
* 审核进度查询 * TODO 审核进度查询
* *
*/ */
open fun read(vo: OnlyToken, table: IntIdTable): F? { fun read(vo: OnlyToken, table: IntIdTable): F? {
return transaction { return transaction {
table.innerJoin(AuditLeggings).innerJoin(Users) if(isFilter){
.slice(listOf(table.id)) val nextAudit = AuditLeggings.alias("nextAudit")
.select {Users.id eq vo.token.id} table.innerJoin(AuditLeggings)
.firstOrNull() .innerJoin(nextAudit, { AuditLeggings.nextAudit }, { nextAudit[AuditLeggings.id] })
?.let { it -> .innerJoin(Users)
getCheckVo(id = it[table.id]) .slice(listOf(table.id))
} .select {Users.id eq vo.token.id and (nextAudit[AuditLeggings.result] neq true)}
.firstOrNull()
?.let { it ->
getCheckVo(id = it[table.id])
}
}else {
table.innerJoin(AuditLeggings).innerJoin(Users)
.slice(listOf(table.id))
.select { Users.id eq vo.token.id }
.firstOrNull()
?.let { it ->
getCheckVo(id = it[table.id])
}
}
} }
} }
@ -625,7 +647,7 @@ abstract class AuditService<T, E, F> : AbstractService() {
return AuditCheckVo( return AuditCheckVo(
checkStatus = when { checkStatus = when {
audit.nextAudit == null && audit.manager == null -> CheckStatus.WaitFirst audit.nextAudit == null && audit.manager == null -> CheckStatus.WaitFirst
audit.nextAudit == null && audit.manager != null -> CheckStatus.AcceptFirst audit.nextAudit == null && audit.manager != null && audit.result==null -> CheckStatus.AcceptFirst
audit.nextAudit != null && audit.nextAudit?.manager == null -> CheckStatus.WaitLast audit.nextAudit != null && audit.nextAudit?.manager == null -> CheckStatus.WaitLast
audit.nextAudit != null && audit.nextAudit?.result == null -> CheckStatus.AcceptLast audit.nextAudit != null && audit.nextAudit?.result == null -> CheckStatus.AcceptLast
else -> CheckStatus.Finish else -> CheckStatus.Finish
@ -647,6 +669,19 @@ abstract class AuditService<T, E, F> : AbstractService() {
abstract fun audit(vo: OnlyToken): List<E> abstract fun audit(vo: OnlyToken): List<E>
protected fun <T : AbstractAudit> createSortedBy(table: IntEntityClass<T>): List<T> {
return table.all().sortedBy {
//按初审受理>等待复审>复审受理>完成审核 排序
when {
it.audit.nextAudit == null && it.audit.manager == null -> 1
it.audit.nextAudit == null && it.audit.manager != null -> 2
it.audit.nextAudit != null && it.audit.nextAudit?.manager == null -> 3
it.audit.nextAudit != null && it.audit.nextAudit?.result == null -> 4
else -> 5
}
}
}
protected fun toAuditLoggingVo(it: AuditLogging?): AuditLoggingVo? { protected fun toAuditLoggingVo(it: AuditLogging?): AuditLoggingVo? {
return it?.let { logging -> return it?.let { logging ->
val auditLogging = AuditLoggingVo( val auditLogging = AuditLoggingVo(
@ -671,6 +706,17 @@ abstract class AuditService<T, E, F> : AbstractService() {
auditLogging auditLogging
} }
} }
protected fun createNotifications(vo:ClientBaseVo,user:User){
foreground(
receiverId = vo.token.id,
content = "您成功提交了一份${dataType},请耐心等待后台受理"
)
background(
content = "用户${user.name}提交了一份${dataType}需要您进行受理",
duty = Duty.PamphaBhusal
)
}
} }
/** /**
@ -681,11 +727,12 @@ object AssociationService : AuditService<AssociationRegVo, AuditAssociationVo, A
override val dataType: String = "社团注册资料" override val dataType: String = "社团注册资料"
override fun findEntity(auditId: Int): AbstractAudit { override fun findEntity(auditId: Int): AbstractAudit {
return Association.find { Associations.auditId eq auditId }.firstOrNull() ?: throw AuditIdError(auditId) return testFind(Associations,Association,auditId)
} }
override fun afterAudit(entity: AbstractAudit) { override val isFilter: Boolean = false
override fun afterAudit(entity: AbstractAudit) {
AssociationMember.new { AssociationMember.new {
user = entity.audit.user user = entity.audit.user
this.association = Association.find { Associations.auditId eq entity.audit.id }.firstOrNull() this.association = Association.find { Associations.auditId eq entity.audit.id }.firstOrNull()
@ -696,6 +743,35 @@ object AssociationService : AuditService<AssociationRegVo, AuditAssociationVo, A
} }
} }
fun Association.set(vo:AssociationRegVo,user:User){
name = vo.name
desc = vo.desc
logo = ImageFile.findById(vo.fileId) ?: throw FileIdError(vo.fileId)
this.audit = AuditLogging.new {
this.user = user
}
}
fun loadAll():List<AssociationVo>{
return transaction {
Association.all().map {
toAssociationVo(it)
}
}
}
fun update(vo:AssociationVo){
transaction {
Association.findById(vo.associationId).let {
if(it==null){
throw AssociationIdError(vo.associationId)
}else{
it.level=vo.level?.name
}
}
}
}
/** /**
* 注册社团 * 注册社团
* *
@ -708,15 +784,8 @@ object AssociationService : AuditService<AssociationRegVo, AuditAssociationVo, A
val user = User.findById(vo.token.id) ?: throw UserIdError(vo.token.id) val user = User.findById(vo.token.id) ?: throw UserIdError(vo.token.id)
if (vo.associationId != null) { if (vo.associationId != null) {
log.info("再次提交【${vo.name}】注册资料") log.info("再次提交【${vo.name}】注册资料")
val association = Association.findById(vo.associationId!!) ?: throw AuditIdError(vo.associationId!!) (Association.findById(vo.associationId!!) ?: throw AuditIdError(vo.associationId!!))
association.apply { .set(vo=vo,user=user)
name = vo.name
desc = vo.desc
logo = ImageFile.findById(vo.fileId) ?: throw FileIdError(vo.fileId)
this.audit = AuditLogging.new {
this.user = user
}
}
} else { } else {
val associationMember = AssociationMember.find { AssociationMembers.userId eq user.id }.firstOrNull() val associationMember = AssociationMember.find { AssociationMembers.userId eq user.id }.firstOrNull()
val association: Association? = associationMember?.association val association: Association? = associationMember?.association
@ -725,12 +794,7 @@ object AssociationService : AuditService<AssociationRegVo, AuditAssociationVo, A
association != null && association.audit.result == null -> throw IllegalArgumentException("您已经提交过${dataType},请耐心等待后台管理员处理") association != null && association.audit.result == null -> throw IllegalArgumentException("您已经提交过${dataType},请耐心等待后台管理员处理")
association == null -> { association == null -> {
Association.new { Association.new {
name = vo.name set(vo=vo,user=user)
desc = vo.desc
logo = ImageFile.findById(vo.fileId) ?: throw FileIdError(vo.fileId)
this.audit = AuditLogging.new {
this.user = user
}
faculty = faculty(user.studentId).name faculty = faculty(user.studentId).name
} }
@ -738,9 +802,7 @@ object AssociationService : AuditService<AssociationRegVo, AuditAssociationVo, A
} }
} }
foreground(receiverId = vo.token.id, content = "您成功提交了一份${dataType},请耐心等待后台受理") createNotifications(vo=vo,user=user)
background(content = "用户${user.name}提交了一份${dataType}需要您进行受理", duty = Duty.PamphaBhusal)
log.info("未审核社团:${vo.name}创建成功") log.info("未审核社团:${vo.name}创建成功")
} }
} }
@ -777,7 +839,8 @@ object AssociationService : AuditService<AssociationRegVo, AuditAssociationVo, A
return (Association.findById(id) ?: throw AssociationIdError(id.value)).let { return (Association.findById(id) ?: throw AssociationIdError(id.value)).let {
AssociationCheckVo( AssociationCheckVo(
associationVo = toAssociationVo(it), associationVo = toAssociationVo(it),
auditCheckVo = toCheckVo(it.audit), fileId = it.logo.id.value auditCheckVo = toCheckVo(it.audit),
fileId = it.logo.id.value
) )
} }
} }
@ -790,16 +853,7 @@ object AssociationService : AuditService<AssociationRegVo, AuditAssociationVo, A
*/ */
override fun audit(vo: OnlyToken): List<AuditAssociationVo> { override fun audit(vo: OnlyToken): List<AuditAssociationVo> {
return transaction { return transaction {
return@transaction Association.all().sortedBy { return@transaction createSortedBy(Association).map {
//按初审受理>等待复审>复审受理>完成审核 排序
when {
it.audit.nextAudit == null && it.audit.manager == null -> 1
it.audit.nextAudit == null && it.audit.manager != null -> 2
it.audit.nextAudit != null && it.audit.nextAudit?.manager == null -> 3
it.audit.nextAudit != null && it.audit.nextAudit?.result == null -> 4
else -> 5
}
}.map {
val audit = toAuditLoggingVo(it.audit) ?: throw IllegalArgumentException("转换审核记录出错!!!!") val audit = toAuditLoggingVo(it.audit) ?: throw IllegalArgumentException("转换审核记录出错!!!!")
AuditAssociationVo(name = it.name, desc = it.desc, logo = it.logo.filepath, audit = audit) AuditAssociationVo(name = it.name, desc = it.desc, logo = it.logo.filepath, audit = audit)
}.apply { }.apply {
@ -872,17 +926,44 @@ object AssociationService : AuditService<AssociationRegVo, AuditAssociationVo, A
} }
} }
/**
* 活动服务
*/
object ActivityService : AuditService<ActivityApplyVo, AuditActVo,ActivityCheckVo>() { object ActivityService : AuditService<ActivityApplyVo, AuditActVo,ActivityCheckVo>() {
override val dataType: String = "活动申请书" override val dataType: String = "活动申请书"
override fun findEntity(auditId: Int): AbstractAudit { override fun findEntity(auditId: Int): AbstractAudit {
return Activity.find { Activities.auditId eq auditId }.firstOrNull() ?: throw AuditIdError(auditId) return testFind(Activities,Activity,auditId)
} }
override fun afterAudit(entity: AbstractAudit) { /**
* 查看活动信息
*
*/
fun listAll():List<ManagerActVo>{
return transaction {
Activity.all().map {
ManagerActVo(association = AssociationService.toAssociationVo(it.association),
score = (1..5).random(),activityVo = toActivityVo(it))
}
}
}
/**
* 主页活动图片
*
* @return
*/
fun random():List<MainActivityPhotoVo>{
return transaction {
PhotoAlbum.all().shuffled().map {
MainActivityPhotoVo(url=it.photo.filepath,
activityVo = toActivityVo(it.activity),
associationVo = AssociationService.toAssociationVo(it.activity.association))
}
}
} }
/** /**
@ -989,18 +1070,16 @@ object ActivityService : AuditService<ActivityApplyVo, AuditActVo,ActivityCheckV
} }
} }
override fun read(vo: OnlyToken, table: IntIdTable): ActivityCheckVo? {
val nextAudit = AuditLeggings.alias("nextAudit")
return transaction { fun Activity.set(activityVo:ActivityVo,user:User){
table.innerJoin(AuditLeggings) activityName = activityVo.activityName
.innerJoin(nextAudit, { AuditLeggings.nextAudit }, { nextAudit[AuditLeggings.id] }) activityTime = activityVo.activityTime.toLocalDateTime()
.innerJoin(Users) activityAddress = activityVo.activityAddress
.slice(listOf(table.id)) activityDesc = activityVo.activityDesc
.select {Users.id eq vo.token.id and (nextAudit[AuditLeggings.result] neq true)} activitySize = activityVo.activitySize
.firstOrNull() audit = AuditLogging.new {
?.let { it -> this.user = user
getCheckVo(id = it[table.id])
}
} }
} }
@ -1015,43 +1094,25 @@ object ActivityService : AuditService<ActivityApplyVo, AuditActVo,ActivityCheckV
if (vo.activityVo.activityId != null) { if (vo.activityVo.activityId != null) {
//再次提交 //再次提交
log.info("再次提交【${vo.activityVo.activityName}${dataType}") log.info("再次提交【${vo.activityVo.activityName}${dataType}")
val activity = Activity.findById(vo.activityVo.activityId!!) ?: throw ActivityIdError(vo.activityVo.activityId!!) (Activity.findById(vo.activityVo.activityId!!) ?: throw ActivityIdError(vo.activityVo.activityId!!))
activity.apply { .set(activityVo = vo.activityVo,user=user)
activityName = vo.activityVo.activityName
activityTime = vo.activityVo.activityTime.toLocalDateTime()
activityAddress = vo.activityVo.activityAddress
activityDesc = vo.activityVo.activityDesc
activitySize = vo.activityVo.activitySize
this.audit = AuditLogging.new {
this.user = user
}
}
} else { } else {
//首次提交 //首次提交
//申请活动的限制 //申请活动的限制
val activityMember = AssociationMember.find { AssociationMembers.userId eq user.id }.firstOrNull() val activityMember = AssociationMember.find { AssociationMembers.userId eq user.id }.firstOrNull()
when { when {
activityMember == null -> throw IllegalArgumentException("非社团成员无法申请活动") activityMember == null -> throw IllegalArgumentException("非社团成员无法申请活动")
!activityMember.isHead -> throw java.lang.IllegalArgumentException("不是社团团长无法申请活动") !activityMember.isHead -> throw IllegalArgumentException("不是社团团长无法申请活动")
else -> { else -> {
Activity.new { Activity.new {
activityName = vo.activityVo.activityName set(vo.activityVo,user=user)
activityTime = vo.activityVo.activityTime.toLocalDateTime() association = Association.findById(vo.associationId) ?: throw AssociationIdError(vo.associationId)
activityAddress = vo.activityVo.activityAddress
activityDesc = vo.activityVo.activityDesc
activitySize = vo.activityVo.activitySize
association =
Association.findById(vo.associationId) ?: throw AssociationIdError(vo.associationId)
audit = AuditLogging.new {
this.user = user
}
} }
} }
} }
} }
foreground(receiverId = vo.token.id, content = "您成功提交了一份${dataType},请耐心等待后台受理") createNotifications(vo=vo,user=user)
background(content = "用户${user.name}提交了一份${dataType}需要您进行受理", duty = Duty.PamphaBhusal)
} }
} }
@ -1066,21 +1127,9 @@ object ActivityService : AuditService<ActivityApplyVo, AuditActVo,ActivityCheckV
override fun audit(vo: OnlyToken): List<AuditActVo> { override fun audit(vo: OnlyToken): List<AuditActVo> {
return transaction { return transaction {
//TODO sortedBy这一段需要封装 return@transaction createSortedBy(Activity).map {
return@transaction Activity.all().sortedBy {
//按初审受理>等待复审>复审受理>完成审核 排序
when {
it.audit.nextAudit == null && it.audit.manager == null -> 1
it.audit.nextAudit == null && it.audit.manager != null -> 2
it.audit.nextAudit != null && it.audit.nextAudit?.manager == null -> 3
it.audit.nextAudit != null && it.audit.nextAudit?.result == null -> 4
else -> 5
}
}.map {
val audit = toAuditLoggingVo(it.audit) ?: throw IllegalArgumentException("转换审核记录出错!!!!") val audit = toAuditLoggingVo(it.audit) ?: throw IllegalArgumentException("转换审核记录出错!!!!")
AuditActVo( AuditActVo(activityVo = toActivityVo(activity = it), audit = audit)
activityVo = toActivityVo(activity = it), audit = audit, auditId = it.id.value
)
}.apply { }.apply {
log.info("找到${this.size}${dataType}") log.info("找到${this.size}${dataType}")
} }
@ -1091,13 +1140,93 @@ object ActivityService : AuditService<ActivityApplyVo, AuditActVo,ActivityCheckV
return (Activity.findById(id) ?: throw ActivityIdError(id.value)).let { return (Activity.findById(id) ?: throw ActivityIdError(id.value)).let {
ActivityCheckVo( ActivityCheckVo(
activityVo = toActivityVo(activity = it), activityVo = toActivityVo(activity = it),
auditCheckVo = toCheckVo(it.audit), auditCheckVo = toCheckVo(it.audit)
activityId = it.id.value
) )
} }
} }
} }
/**
* 重命名服务
*/
object RenameService : AuditService<RenameApplyVo,AuditRenameVo,RenameCheckVo>(){
override val dataType: String = "换名申请表"
fun Rename.set(vo:RenameVo,user:User){
newName=vo.newName
cause=vo.cause
audit=AuditLogging.new {
this.user = user
}
}
//TODO 类型自动转换
override fun afterAudit(entity: AbstractAudit) {
if(entity is Rename){
entity.association.name=entity.newName
}
}
override fun register(vo: RenameApplyVo) {
transaction {
vo.rename.renameId.also {
val user = User.findById(vo.token.id) ?: throw UserIdError(vo.token.id)
if (it != null) {
//再次提交
(Rename.findById(it) ?: throw IllegalArgumentException("无法根据[id=${it}]找到${dataType}")).set(
vo = vo.rename,
user = user
)
} else {
//重新提交
val activityMember = AssociationMember.find { AssociationMembers.userId eq user.id }.firstOrNull()
when {
activityMember == null -> throw IllegalArgumentException("非社团成员无法申请社团换名")
!activityMember.isHead -> throw IllegalArgumentException("非社团团长无法申请社团换名")
else -> {
Rename.new {
set(vo = vo.rename, user = user)
association =
Association.findById(vo.associationId) ?: throw AssociationIdError(vo.associationId)
}
}
}
}
createNotifications(vo = vo, user = user)
}
}
}
override fun findEntity(auditId: Int): AbstractAudit {
return testFind(Renames,Rename,auditId)
}
private fun toRenameVo(rename: Rename):RenameVo{
return RenameVo(renameId = rename.id.value,newName = rename.newName,cause = rename.cause)
}
override fun getCheckVo(id: EntityID<Int>): RenameCheckVo {
return (Rename.findById(id)?:throw IllegalArgumentException("找不到[id=${id}]${dataType}")).let {
RenameCheckVo(renameVo = toRenameVo(it),auditCheckVo = toCheckVo(it.audit))
}
}
override fun audit(vo: OnlyToken): List<AuditRenameVo> {
return transaction {
return@transaction createSortedBy(Rename).map {
val audit = toAuditLoggingVo(it.audit) ?: throw IllegalArgumentException("转换审核记录出错!!!!")
AuditRenameVo(renameVo = toRenameVo(rename = it),audit = audit,associationVo = AssociationService.toAssociationVo(it.association))
}.apply {
log.info("找到${this.size}${ActivityService.dataType}")
}
}
}
}
/** /**
* 通知服务 * 通知服务
*/ */
@ -1180,6 +1309,52 @@ object BackgroundService : AbstractService() {
} }
fun toManagerVo(manager: Manager):ManagerInfoVo{
return ManagerInfoVo(duty = manager.duty.let { Duty.valueOf(it) },name=manager.name,
headImg = manager.headImg?.filepath,desc = manager.desc)
}
/**
* 加载部门部长和总人数
*
*/
fun load():ManagerDutySumVo{
return transaction {
val secretariat=Manager.find { Managers.duty eq Duty.SecretaryOfTheMinister.name }.first()
val secretariatCount=Manager.find{ Managers.duty eq Duty.SecretaryDepartmentOfficer.name }.count()
val propaganda=Manager.find {Managers.duty eq Duty.PropagandaDepartment.name }.first()
val propagandaCount=Manager.find{ Managers.duty eq Duty.PublicityDepartmentOfficer.name }.count()
val publicRelationsDepartment=Manager.find{ Managers.duty eq Duty.LiaisonMinister.name }.first()
val publicRelationsDepartmentCount=Manager.find{ Managers.duty eq Duty.LiaisonOfficer.name }.count()
ManagerDutySumVo(secretariat = ManagerDutyVo(manager = toManagerVo(secretariat),people = secretariatCount.toInt()),
propaganda = ManagerDutyVo(manager = toManagerVo(propaganda),people = propagandaCount.toInt()),
publicRelationsDepartment = ManagerDutyVo(manager = toManagerVo(publicRelationsDepartment),
people=publicRelationsDepartmentCount.toInt()))
}
}
/**
* 加载部门详细信息
*
* @return
*/
fun loadDetail():AllOfficerVo{
return transaction {
val secretariat=Manager.find{ Managers.duty eq Duty.SecretaryDepartmentOfficer.name }.map {
toManagerVo(it)
}
val propaganda=Manager.find {Managers.duty eq Duty.PublicityDepartmentOfficer.name }.map {
toManagerVo(it)
}
val publicRelationsDepartment=Manager.find { Managers.duty eq Duty.LiaisonOfficer.name }.map {
toManagerVo(it)
}
AllOfficerVo(secretariat=secretariat,propaganda = propaganda,publicRelationsDepartment=publicRelationsDepartment)
}
}
private fun createManager(duty: Duty, num: Int = 1): MutableList<InitManagerDto> { private fun createManager(duty: Duty, num: Int = 1): MutableList<InitManagerDto> {
val managerList = mutableListOf<InitManagerDto>() val managerList = mutableListOf<InitManagerDto>()
repeat(num) { repeat(num) {

@ -12,7 +12,12 @@ import com.gyf.csams.module.UserRegVo
import io.ktor.config.* import io.ktor.config.*
import io.ktor.http.* import io.ktor.http.*
import io.ktor.server.testing.* import io.ktor.server.testing.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.SqlExpressionBuilder.neq
import org.jetbrains.exposed.sql.alias
import org.jetbrains.exposed.sql.and import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.innerJoin
import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import java.io.File import java.io.File
import java.time.LocalDateTime import java.time.LocalDateTime
@ -84,9 +89,17 @@ class ApplicationTest {
@Test @Test
fun testEntryId() { fun testEntryId() {
initApp { initApp {
transaction { transaction {
val c= updateComment(UserTokens) val nextAudit = AuditLeggings.alias("nextAudit")
println(c) Activities.innerJoin(AuditLeggings)
.innerJoin(nextAudit, { AuditLeggings.nextAudit }, { nextAudit[AuditLeggings.id] })
.innerJoin(Users)
.slice(listOf(Activities.id))
.select {Users.id eq 1 and (nextAudit[AuditLeggings.result] neq true)}
.firstOrNull()
?.let { it ->
ActivityService.getCheckVo(id = it[Activities.id])
}.let { println(it) }
} }
} }
} }

Loading…
Cancel
Save