package cn.flightfeather.supervision.common.autoledger
|
|
import cn.flightfeather.supervision.common.pdf.PdfUtil
|
import cn.flightfeather.supervision.domain.entity.LedgerSubType
|
import cn.flightfeather.supervision.domain.entity.PracticalOperation
|
import cn.flightfeather.supervision.domain.entity.Userinfo
|
import cn.flightfeather.supervision.domain.repository.LedgerRep
|
import cn.flightfeather.supervision.domain.repository.PracticalOperationRep
|
import cn.flightfeather.supervision.infrastructure.utils.DateUtil
|
import cn.flightfeather.supervision.lightshare.service.LedgerService
|
import cn.flightfeather.supervision.lightshare.vo.LedgerVo
|
import org.springframework.stereotype.Component
|
import org.thymeleaf.context.Context
|
import org.thymeleaf.spring5.SpringTemplateEngine
|
import java.time.LocalDate
|
import java.time.LocalDateTime
|
import java.time.ZoneId
|
import java.time.ZoneOffset
|
import java.time.format.DateTimeFormatter
|
import java.util.*
|
|
/**
|
* 台账自动生成
|
*/
|
@Component
|
class AutoLedger(
|
private val springTemplateEngine: SpringTemplateEngine,
|
private val ledgerRep: LedgerRep,
|
private val practicalOperationRep: PracticalOperationRep,
|
private val ledgerService: LedgerService,
|
) {
|
|
/**
|
* 根据实操事务的配置,生成对应的台账记录
|
* 当月的台账记录应该由上个月的实操记录作为内容进行生成
|
* @param userInfo 生成台账对应的用户信息
|
* @param operations 实操事务
|
* @param year 生成的台账所在年份
|
* @param month 生成的台账所在月份
|
*/
|
fun create(userInfo: Userinfo?, operations: List<PracticalOperation?>, year: Int, month: Int) {
|
if (userInfo == null || operations.isEmpty()) {
|
return
|
}
|
// 台账的时间范围
|
val thisMonth = LocalDateTime.of(year, month, 1, 0, 0)
|
val sT = thisMonth.minusMonths(1)
|
val eT = thisMonth.minusSeconds(1)
|
|
val ledger = ledgerRep.selectLedger(operations[0]?.poLedgerTypeId)
|
|
val map = hashMapOf<String, Any>()
|
map["info"] = getBaseInfo(ledger, userInfo, operations)
|
val records = getRecords(userInfo, operations, sT, eT)
|
// 当用户没有操作记录时,不生成对应台账
|
if (records.isEmpty()) return
|
map["table"] = records
|
|
val context = Context()
|
context.setVariables(map)
|
val content = springTemplateEngine.process("ledger-3206", context)
|
val pdf = PdfUtil.htmlToPdf(content)
|
val pics = PdfUtil.pdfToPic(pdf)
|
val files = pics.map { Pair(it, "jpg") }
|
|
// 生成的台账时间为传入的时间
|
val ledgerVo = LedgerVo.fromLedgerSubtype(ledger).apply {
|
updateDate = Date.from(thisMonth.atZone(ZoneId.systemDefault()).toInstant())
|
}
|
ledgerService.uploadLedger(userInfo.guid!!, ledgerVo, files)
|
}
|
|
/**
|
*
|
*/
|
private fun getBaseInfo(ledger: LedgerSubType?, userInfo: Userinfo, operations: List<PracticalOperation?>):
|
UserBaseInfo {
|
val title = operations[0]?.poLedgerTypeName ?: ""
|
val stateRange = operations[0]?.poStateRange?.split(";")
|
val stateNames = getStateNames(stateRange)
|
val now = LocalDate.now().format(DateTimeFormatter.ofPattern("YYYY年MM月"))
|
return UserBaseInfo(title, userInfo.realname ?: "", now, stateNames)
|
}
|
|
/**
|
* 获取状态标题
|
*/
|
private fun getStateNames(stateRange: List<String>?): List<String> {
|
stateRange ?: return emptyList()
|
val res = mutableListOf<String>()
|
res.addAll(stateRange.subList(1, stateRange.size))
|
res.add(stateRange[0])
|
return res
|
}
|
|
/**
|
*
|
*/
|
private fun getRecords(
|
userInfo: Userinfo,
|
operations: List<PracticalOperation?>,
|
sT: LocalDateTime,
|
eT: LocalDateTime,
|
): List<Record> {
|
val userId = userInfo.guid
|
val records = mutableListOf<Record>()
|
operations.forEach {
|
val deviceName = it?.poSubTypeName + it?.poDeviceCode
|
val stateRange = it?.poStateRangeId?.split(";") ?: return@forEach
|
// 状态最少有两种,否则应该是配置错误
|
if (stateRange.size < 2) return@forEach
|
val opRecords = practicalOperationRep.getRecords(userId, listOf(it.poId), sT, eT, true)
|
|
// 判断事务的状态规则是否为依次变换型
|
if (it.poStateRule == 0) {
|
// 该规则下的台账记录会将一组完整的状态变换记为一条记录,
|
// 通常首个状态含义为关闭,所以一般从第二个状态开始
|
opRecords.forEach { r ->
|
val time = LocalDateTime.ofInstant(r?.prTime?.toInstant(), ZoneId.systemDefault())
|
val date = time.format(DateTimeFormatter.ofPattern("MM月dd日"))
|
val stateTimes = MutableList<String?>(stateRange.size) { "" }
|
// 当状态不是关闭时,表示这一组状态还未完成,因此添加到上一条记录中
|
// 如果没有上一条记录,或者状态为除了关闭的第一个状态,则新增记录
|
val record = if (records.isEmpty() || r?.prStateId == stateRange[1]) {
|
val r = Record(deviceName, date, stateTimes)
|
records.add(r)
|
r
|
} else {
|
val last = records.last()
|
// 判断当前记录和上一条记录是否在同一天
|
if (last.date == date) {
|
last
|
} else {
|
val r1 = Record(deviceName, date, stateTimes)
|
records.add(r1)
|
r1
|
}
|
}
|
var index = stateRange.indexOf(r?.prStateId)
|
if (index != -1) {
|
index -= 1
|
if (index == -1) index = stateRange.lastIndex
|
record.stateTimes[index] = DateUtil.DateToString(r?.prTime, DateUtil.DateStyle.HH_MM_SS)
|
}
|
}
|
} else if (it.poStateRule == 1) {
|
// TODO: 2024/3/8
|
}
|
}
|
return records
|
}
|
|
/**
|
* 用户基本信息
|
*/
|
inner class UserBaseInfo(
|
val title: String?,
|
val userName: String?,
|
val timeStamp: String?,
|
val stateNames: List<String>,
|
)
|
|
/**
|
* 台账记录
|
*/
|
inner class Record(
|
val deviceName: String?,
|
val date: String?,
|
val stateTimes: MutableList<String?>,
|
)
|
|
}
|