| @@ -8,9 +8,9 @@ import jakarta.validation.constraints.Size | |||||
| @Table(name = "equipment") | @Table(name = "equipment") | ||||
| @Entity | @Entity | ||||
| open class Equipment : BaseEntity<Long>() { | open class Equipment : BaseEntity<Long>() { | ||||
| @Size(max = 30) | |||||
| @Size(max = 255) | |||||
| @NotNull | @NotNull | ||||
| @Column(name = "code", nullable = false, length = 30) | |||||
| @Column(name = "code", nullable = false, length = 255) | |||||
| open var code: String? = null | open var code: String? = null | ||||
| @Size(max = 30) | @Size(max = 30) | ||||
| @@ -29,14 +29,14 @@ open class EquipmentDetail : BaseEntity<Long>() { | |||||
| @Column(name = "repairAndMaintenanceRemarks", nullable = true, length = 255) | @Column(name = "repairAndMaintenanceRemarks", nullable = true, length = 255) | ||||
| open var repairAndMaintenanceRemarks: String? = null | open var repairAndMaintenanceRemarks: String? = null | ||||
| @Size(max = 30) | |||||
| @Size(max = 255) | |||||
| @NotNull | @NotNull | ||||
| @Column(name = "code", nullable = false, length = 30) | |||||
| @Column(name = "code", nullable = false, length = 255) | |||||
| open var code: String? = null | open var code: String? = null | ||||
| @Size(max = 30) | |||||
| @Size(max = 255) | |||||
| @NotNull | @NotNull | ||||
| @Column(name = "name", nullable = false, length = 30) | |||||
| @Column(name = "name", nullable = false, length = 255) | |||||
| open var name: String? = null | open var name: String? = null | ||||
| @Size(max = 500) | @Size(max = 500) | ||||
| @@ -9,6 +9,7 @@ interface EquipmentDetailRepository : AbstractRepository<EquipmentDetail, Long> | |||||
| fun findByCode(code: String): EquipmentDetail? | fun findByCode(code: String): EquipmentDetail? | ||||
| fun findByIdAndDeletedFalse(id: Long): EquipmentDetail?; | fun findByIdAndDeletedFalse(id: Long): EquipmentDetail?; | ||||
| fun findByNameAndDeletedIsFalse(name: String): EquipmentDetail?; | fun findByNameAndDeletedIsFalse(name: String): EquipmentDetail?; | ||||
| fun findByCodeAndDeletedIsFalse(code: String): EquipmentDetail?; | |||||
| fun findByDescriptionAndDeletedIsFalse(description: String): EquipmentDetail?; | fun findByDescriptionAndDeletedIsFalse(description: String): EquipmentDetail?; | ||||
| fun findByEquipmentTypeIdAndDeletedFalse(equipmentTypeId: Long): List<EquipmentDetail>; | fun findByEquipmentTypeIdAndDeletedFalse(equipmentTypeId: Long): List<EquipmentDetail>; | ||||
| @@ -36,42 +36,94 @@ open class EquipmentDetailService( | |||||
| e.lastRepairAndMaintenanceDate AS lastRepairAndMaintenanceDate, | e.lastRepairAndMaintenanceDate AS lastRepairAndMaintenanceDate, | ||||
| e.repairAndMaintenanceRemarks AS repairAndMaintenanceRemarks | e.repairAndMaintenanceRemarks AS repairAndMaintenanceRemarks | ||||
| FROM equipment_detail e | FROM equipment_detail e | ||||
| WHERE e.deleted = FALSE | |||||
| LEFT JOIN equipment eq ON e.equipmentTypeId = eq.id | |||||
| """ | """ | ||||
| ) | ) | ||||
| val whereConditions = mutableListOf<String>() | |||||
| // Handle combined search for code and equipmentCode (OR logic) | |||||
| whereConditions.add("e.deleted = FALSE") | |||||
| whereConditions.add("eq.deleted = FALSE") | |||||
| val searchTerm = args["equipmentCode"] as? String | val searchTerm = args["equipmentCode"] as? String | ||||
| val codeTerm = args["code"] as? String | val codeTerm = args["code"] as? String | ||||
| if (searchTerm != null && codeTerm != null && searchTerm == codeTerm) { | if (searchTerm != null && codeTerm != null && searchTerm == codeTerm) { | ||||
| // When both are provided with the same value, search using OR | |||||
| sql.append(" AND (LOWER(e.code) LIKE LOWER(:equipmentCode) OR LOWER(e.equipmentCode) LIKE LOWER(:equipmentCode)) ") | |||||
| whereConditions.add("(LOWER(e.code) LIKE LOWER(:equipmentCode) OR LOWER(e.equipmentCode) LIKE LOWER(:equipmentCode))") | |||||
| } else { | } else { | ||||
| // Otherwise, use individual conditions | |||||
| if (codeTerm != null && (searchTerm == null || searchTerm != codeTerm)) { | if (codeTerm != null && (searchTerm == null || searchTerm != codeTerm)) { | ||||
| sql.append(" AND LOWER(e.code) LIKE LOWER(:code) ") | |||||
| whereConditions.add("LOWER(e.code) LIKE LOWER(:code)") | |||||
| } | } | ||||
| if (searchTerm != null && (codeTerm == null || searchTerm != codeTerm)) { | if (searchTerm != null && (codeTerm == null || searchTerm != codeTerm)) { | ||||
| sql.append(" AND LOWER(e.equipmentCode) LIKE LOWER(:equipmentCode) ") | |||||
| whereConditions.add("LOWER(e.equipmentCode) LIKE LOWER(:equipmentCode)") | |||||
| } | } | ||||
| } | } | ||||
| if (args.containsKey("id")) { | if (args.containsKey("id")) { | ||||
| sql.append(" AND e.id like :id ") | |||||
| whereConditions.add("e.id like :id") | |||||
| } | } | ||||
| if (args.containsKey("name")) { | if (args.containsKey("name")) { | ||||
| sql.append(" AND LOWER(e.name) LIKE LOWER(:name) ") | |||||
| whereConditions.add("LOWER(e.name) LIKE LOWER(:name)") | |||||
| } | } | ||||
| if (args.containsKey("description")) { | if (args.containsKey("description")) { | ||||
| sql.append(" AND e.description like :description ") | |||||
| whereConditions.add("e.description = :description") | |||||
| } | } | ||||
| if (args.containsKey("repairAndMaintenanceStatus")) { | if (args.containsKey("repairAndMaintenanceStatus")) { | ||||
| sql.append(" AND e.repairAndMaintenanceStatus = :repairAndMaintenanceStatus ") | |||||
| whereConditions.add("e.repairAndMaintenanceStatus = :repairAndMaintenanceStatus") | |||||
| } | |||||
| if (whereConditions.isNotEmpty()) { | |||||
| sql.append("WHERE ${whereConditions.joinToString(" AND ")}") | |||||
| } | } | ||||
| return jdbcDao.queryForList(sql.toString(), args) | return jdbcDao.queryForList(sql.toString(), args) | ||||
| } | } | ||||
| open fun getEquipmentDetailsByEquipmentId(equipmentId: Long): List<Map<String, Any>> { | |||||
| val sql = """ | |||||
| SELECT | |||||
| ed.id AS id, | |||||
| ed.code AS code, | |||||
| ed.name AS name, | |||||
| ed.description AS description, | |||||
| ed.equipmentCode AS equipmentCode, | |||||
| ed.repairAndMaintenanceStatus AS repairAndMaintenanceStatus, | |||||
| ed.latestRepairAndMaintenanceDate AS latestRepairAndMaintenanceDate, | |||||
| ed.lastRepairAndMaintenanceDate AS lastRepairAndMaintenanceDate, | |||||
| ed.repairAndMaintenanceRemarks AS repairAndMaintenanceRemarks | |||||
| FROM equipment_detail ed | |||||
| LEFT JOIN equipment e ON ed.equipmentTypeId = e.id | |||||
| WHERE ed.deleted = FALSE | |||||
| AND e.id = :equipmentId | |||||
| AND e.deleted = FALSE | |||||
| """ | |||||
| val args = mapOf("equipmentId" to equipmentId) | |||||
| return jdbcDao.queryForList(sql, args) | |||||
| } | |||||
| open fun getEquipmentDetailsByDescriptionIncludingDeleted(description: String): List<Map<String, Any>> { | |||||
| val sql = """ | |||||
| SELECT | |||||
| e.id AS id, | |||||
| e.code AS code, | |||||
| e.name AS name, | |||||
| e.description AS description, | |||||
| e.equipmentCode AS equipmentCode, | |||||
| e.repairAndMaintenanceStatus AS repairAndMaintenanceStatus, | |||||
| e.latestRepairAndMaintenanceDate AS latestRepairAndMaintenanceDate, | |||||
| e.lastRepairAndMaintenanceDate AS lastRepairAndMaintenanceDate, | |||||
| e.repairAndMaintenanceRemarks AS repairAndMaintenanceRemarks | |||||
| FROM equipment_detail e | |||||
| WHERE e.description = :description | |||||
| """ | |||||
| val args = mapOf("description" to description) | |||||
| return jdbcDao.queryForList(sql, args) | |||||
| } | |||||
| open fun findById(id: Long): EquipmentDetail? { | open fun findById(id: Long): EquipmentDetail? { | ||||
| return equipmentDetailRepository.findByIdAndDeletedFalse(id) | return equipmentDetailRepository.findByIdAndDeletedFalse(id) | ||||
| } | } | ||||
| @@ -96,61 +148,52 @@ open class EquipmentDetailService( | |||||
| val equipmentDetail = findById(id) | val equipmentDetail = findById(id) | ||||
| ?: throw IllegalArgumentException("Equipment detail not found with id: $id") | ?: throw IllegalArgumentException("Equipment detail not found with id: $id") | ||||
| // Store the previous status and latest date before updating | |||||
| val previousStatus = equipmentDetail.repairAndMaintenanceStatus | val previousStatus = equipmentDetail.repairAndMaintenanceStatus | ||||
| val previousLatestDate = equipmentDetail.latestRepairAndMaintenanceDate | val previousLatestDate = equipmentDetail.latestRepairAndMaintenanceDate | ||||
| // Update status and remarks | |||||
| equipmentDetail.repairAndMaintenanceStatus = request.repairAndMaintenanceStatus | equipmentDetail.repairAndMaintenanceStatus = request.repairAndMaintenanceStatus | ||||
| equipmentDetail.repairAndMaintenanceRemarks = request.repairAndMaintenanceRemarks | equipmentDetail.repairAndMaintenanceRemarks = request.repairAndMaintenanceRemarks | ||||
| // Handle date updates based on status change | |||||
| when { | when { | ||||
| // Changing from "是" (true) to "否" (false) | |||||
| previousStatus == true && request.repairAndMaintenanceStatus == false -> { | previousStatus == true && request.repairAndMaintenanceStatus == false -> { | ||||
| // Save current latestRepairAndMaintenanceDate to lastRepairAndMaintenanceDate | |||||
| equipmentDetail.lastRepairAndMaintenanceDate = previousLatestDate | equipmentDetail.lastRepairAndMaintenanceDate = previousLatestDate | ||||
| // Update latestRepairAndMaintenanceDate to current time | |||||
| equipmentDetail.latestRepairAndMaintenanceDate = LocalDateTime.now() | equipmentDetail.latestRepairAndMaintenanceDate = LocalDateTime.now() | ||||
| } | } | ||||
| // Changing from "否" (false) to "是" (true) | |||||
| // Keep dates unchanged - no action needed | |||||
| previousStatus == false && request.repairAndMaintenanceStatus == true -> { | previousStatus == false && request.repairAndMaintenanceStatus == true -> { | ||||
| // Dates remain unchanged | |||||
| } | } | ||||
| // Other cases (null to true/false, or same status) - no date changes | |||||
| } | } | ||||
| return equipmentDetailRepository.saveAndFlush(equipmentDetail) | return equipmentDetailRepository.saveAndFlush(equipmentDetail) | ||||
| } | } | ||||
| /* | |||||
| @Transactional | @Transactional | ||||
| open fun saveEquipmentDetail(request: NewEquipmentDetailRequest): EquipmentDetail { | open fun saveEquipmentDetail(request: NewEquipmentDetailRequest): EquipmentDetail { | ||||
| if (request.code.isNullOrBlank()) { | if (request.code.isNullOrBlank()) { | ||||
| throw IllegalArgumentException("Equipment detail code cannot be null or blank") | throw IllegalArgumentException("Equipment detail code cannot be null or blank") | ||||
| } | } | ||||
| val duplicated = equipmentDetailRepository.findByCodeAndDeletedIsFalse(request.code!!) | |||||
| if (duplicated != null && duplicated.id != request.id) { | |||||
| throw IllegalArgumentException("Equipment detail code already exists") | |||||
| if (request.id != null && request.id > 0) { | |||||
| val duplicated = equipmentDetailRepository.findByCodeAndDeletedIsFalse(request.code!!) | |||||
| if (duplicated != null && duplicated.id != request.id) { | |||||
| throw IllegalArgumentException("Equipment detail code already exists") | |||||
| } | |||||
| } | } | ||||
| val entity = if (request.id != null && request.id > 0) { | val entity = if (request.id != null && request.id > 0) { | ||||
| equipmentDetailRepository.findByIdAndDeletedFalse(request.id) ?: EquipmentDetail() | equipmentDetailRepository.findByIdAndDeletedFalse(request.id) ?: EquipmentDetail() | ||||
| } else { | } else { | ||||
| EquipmentDetail() | EquipmentDetail() | ||||
| } | } | ||||
| entity.code = request.code | entity.code = request.code | ||||
| entity.name = request.name | entity.name = request.name | ||||
| entity.description = request.description | entity.description = request.description | ||||
| entity.equipmentTypeId = request.equipmentTypeId | |||||
| entity.equipmentCode = request.equipmentCode | |||||
| entity.repairAndMaintenanceStatus = request.repairAndMaintenanceStatus ?: false | |||||
| return equipmentDetailRepository.saveAndFlush(entity) | return equipmentDetailRepository.saveAndFlush(entity) | ||||
| } | } | ||||
| */ | |||||
| @Transactional | @Transactional | ||||
| open fun deleteEquipmentDetail(id: Long) { | open fun deleteEquipmentDetail(id: Long) { | ||||
| val equipmentDetail = equipmentDetailRepository.findByIdAndDeletedFalse(id) | val equipmentDetail = equipmentDetailRepository.findByIdAndDeletedFalse(id) | ||||
| @@ -0,0 +1,86 @@ | |||||
| package com.ffii.fpsms.modules.master.service | |||||
| import com.ffii.core.utils.PdfUtils | |||||
| import com.ffii.core.utils.QrCodeUtil | |||||
| import com.ffii.fpsms.modules.master.entity.EquipmentDetailRepository | |||||
| import com.ffii.fpsms.modules.master.web.ExportEquipmentQrCodeRequest | |||||
| import net.sf.jasperreports.engine.JasperCompileManager | |||||
| import net.sf.jasperreports.engine.JasperPrint | |||||
| import org.springframework.core.io.ClassPathResource | |||||
| import org.springframework.stereotype.Service | |||||
| import java.io.FileNotFoundException | |||||
| import java.awt.GraphicsEnvironment | |||||
| import kotlinx.serialization.json.Json | |||||
| import kotlinx.serialization.encodeToString | |||||
| @Service | |||||
| class EquipmentQrCodeService( | |||||
| private val equipmentDetailRepository: EquipmentDetailRepository | |||||
| ) { | |||||
| fun exportEquipmentQrCode(request: ExportEquipmentQrCodeRequest): Map<String, Any> { | |||||
| val QRCODE_HANDLE_PDF = "qrCodeHandle/equipment_QrHandle.jrxml" | |||||
| val resource = ClassPathResource(QRCODE_HANDLE_PDF) | |||||
| if (!resource.exists()) { | |||||
| throw FileNotFoundException("Report file not found: $QRCODE_HANDLE_PDF") | |||||
| } | |||||
| val inputStream = resource.inputStream | |||||
| val qrCodeHandleReport = JasperCompileManager.compileReport(inputStream) | |||||
| val equipmentDetails = equipmentDetailRepository.findAllById(request.equipmentDetailIds) | |||||
| if (equipmentDetails.isEmpty()) { | |||||
| throw IllegalArgumentException("No equipment details found for the provided equipment detail IDs: ${request.equipmentDetailIds}") | |||||
| } | |||||
| val fields = mutableListOf<MutableMap<String, Any>>() | |||||
| for (equipmentDetail in equipmentDetails) { | |||||
| val field = mutableMapOf<String, Any>() | |||||
| val code = equipmentDetail.code ?: "" | |||||
| val equipmentCodeFromDetail = equipmentDetail.equipmentCode ?: "" | |||||
| if (code.isBlank() && equipmentCodeFromDetail.isBlank()) { | |||||
| continue | |||||
| } | |||||
| val qrContentMap = mapOf("equipmentCode" to equipmentCodeFromDetail) | |||||
| val qrCodeContent = Json.encodeToString(qrContentMap) | |||||
| val qrCodeImage = QrCodeUtil.generateQRCodeImage(qrCodeContent) | |||||
| field["username"] = code | |||||
| field["staffNo"] = code | |||||
| field["qrCode"] = qrCodeImage | |||||
| field["code"] = code | |||||
| fields.add(field) | |||||
| } | |||||
| if (fields.isEmpty()) { | |||||
| throw IllegalArgumentException("No valid equipment details found for the provided equipment detail IDs: ${request.equipmentDetailIds}") | |||||
| } | |||||
| val params: MutableMap<String, Any> = mutableMapOf() | |||||
| val availableFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().availableFontFamilyNames | |||||
| val chineseFont = availableFonts.find { | |||||
| it.contains("SimSun", ignoreCase = true) || | |||||
| it.contains("Microsoft YaHei", ignoreCase = true) || | |||||
| it.contains("STSong", ignoreCase = true) || | |||||
| it.contains("SimHei", ignoreCase = true) | |||||
| } ?: "Arial Unicode MS" | |||||
| params["net.sf.jasperreports.default.pdf.encoding"] = "Identity-H" | |||||
| params["net.sf.jasperreports.default.pdf.embedded"] = true | |||||
| params["net.sf.jasperreports.default.pdf.font.name"] = chineseFont | |||||
| val firstEquipmentDetail = equipmentDetails.firstOrNull() | |||||
| return mapOf( | |||||
| "report" to PdfUtils.fillReport(qrCodeHandleReport, fields, params), | |||||
| "fileName" to (firstEquipmentDetail?.code ?: "equipment_qrcode") | |||||
| ) | |||||
| } | |||||
| } | |||||
| @@ -7,6 +7,7 @@ import com.ffii.fpsms.modules.master.entity.EquipmentRepository | |||||
| import org.springframework.stereotype.Service | import org.springframework.stereotype.Service | ||||
| import org.springframework.transaction.annotation.Transactional | import org.springframework.transaction.annotation.Transactional | ||||
| import com.ffii.fpsms.modules.master.web.models.NewEquipmentRequest | import com.ffii.fpsms.modules.master.web.models.NewEquipmentRequest | ||||
| @Service | @Service | ||||
| open class EquipmentService( | open class EquipmentService( | ||||
| private val jdbcDao: JdbcDao, | private val jdbcDao: JdbcDao, | ||||
| @@ -18,40 +19,40 @@ open class EquipmentService( | |||||
| } | } | ||||
| open fun getEquipmentsByPage(args: Map<String, Any>): List<Map<String, Any>> { | open fun getEquipmentsByPage(args: Map<String, Any>): List<Map<String, Any>> { | ||||
| val sql = StringBuilder( | |||||
| """ | |||||
| SELECT | |||||
| e.id AS id, | |||||
| e.code AS code, | |||||
| e.name AS name, | |||||
| e.description AS description, | |||||
| e.equipmentTypeId AS equipmentTypeId, | |||||
| ed.repairAndMaintenanceStatus AS repairAndMaintenanceStatus, | |||||
| ed.latestRepairAndMaintenanceDate AS latestRepairAndMaintenanceDate, | |||||
| ed.lastRepairAndMaintenanceDate AS lastRepairAndMaintenanceDate, | |||||
| ed.repairAndMaintenanceRemarks AS repairAndMaintenanceRemarks | |||||
| FROM equipment e | |||||
| LEFT JOIN equipment_detail ed ON e.code = ed.equipmentCode | |||||
| WHERE e.deleted = FALSE | |||||
| """ | |||||
| ) | |||||
| if (args.containsKey("code")) { | |||||
| sql.append(" AND e.code like :code ") | |||||
| } | |||||
| if (args.containsKey("id")) { | |||||
| sql.append(" AND e.id like :id ") | |||||
| } | |||||
| if (args.containsKey("name")) { | |||||
| sql.append(" AND e.name like :name ") | |||||
| } | |||||
| if (args.containsKey("description")) { | |||||
| sql.append(" AND e.description like :description ") | |||||
| } | |||||
| if (args.containsKey("equipmentTypeId")) { | |||||
| sql.append(" AND e.equipmentTypeId like :equipmentTypeId ") | |||||
| val sql = StringBuilder( | |||||
| """ | |||||
| SELECT | |||||
| e.id AS id, | |||||
| e.code AS code, | |||||
| e.name AS name, | |||||
| e.description AS description, | |||||
| e.equipmentTypeId AS equipmentTypeId, | |||||
| ed.repairAndMaintenanceStatus AS repairAndMaintenanceStatus, | |||||
| ed.latestRepairAndMaintenanceDate AS latestRepairAndMaintenanceDate, | |||||
| ed.lastRepairAndMaintenanceDate AS lastRepairAndMaintenanceDate, | |||||
| ed.repairAndMaintenanceRemarks AS repairAndMaintenanceRemarks | |||||
| FROM equipment e | |||||
| LEFT JOIN equipment_detail ed ON e.code = ed.equipmentCode | |||||
| WHERE e.deleted = FALSE | |||||
| """ | |||||
| ) | |||||
| if (args.containsKey("code")) { | |||||
| sql.append(" AND e.code like :code ") | |||||
| } | |||||
| if (args.containsKey("id")) { | |||||
| sql.append(" AND e.id like :id ") | |||||
| } | |||||
| if (args.containsKey("name")) { | |||||
| sql.append(" AND e.name like :name ") | |||||
| } | |||||
| if (args.containsKey("description")) { | |||||
| sql.append(" AND e.description like :description ") | |||||
| } | |||||
| if (args.containsKey("equipmentTypeId")) { | |||||
| sql.append(" AND e.equipmentTypeId like :equipmentTypeId ") | |||||
| } | |||||
| return jdbcDao.queryForList(sql.toString(), args) | |||||
| } | } | ||||
| return jdbcDao.queryForList(sql.toString(), args) | |||||
| } | |||||
| open fun findById(id: Long): Equipment? { | open fun findById(id: Long): Equipment? { | ||||
| return equipmentRepository.findByIdAndDeletedFalse(id) | return equipmentRepository.findByIdAndDeletedFalse(id) | ||||
| @@ -69,10 +70,8 @@ open class EquipmentService( | |||||
| return equipmentRepository.findByDescriptionAndDeletedIsFalse(description) | return equipmentRepository.findByDescriptionAndDeletedIsFalse(description) | ||||
| } | } | ||||
| @Transactional | @Transactional | ||||
| open fun saveEquipment(request: NewEquipmentRequest): Equipment { | open fun saveEquipment(request: NewEquipmentRequest): Equipment { | ||||
| if (request.code.isNullOrBlank()) { | if (request.code.isNullOrBlank()) { | ||||
| throw IllegalArgumentException("Equipment type code cannot be null or blank") | throw IllegalArgumentException("Equipment type code cannot be null or blank") | ||||
| } | } | ||||
| @@ -81,26 +80,23 @@ open class EquipmentService( | |||||
| throw IllegalArgumentException("Equipment type code already exists") | throw IllegalArgumentException("Equipment type code already exists") | ||||
| } | } | ||||
| val entity = if (request.id != null && request.id > 0) { | val entity = if (request.id != null && request.id > 0) { | ||||
| equipmentRepository.findByIdAndDeletedFalse(request.id) ?: Equipment() | equipmentRepository.findByIdAndDeletedFalse(request.id) ?: Equipment() | ||||
| } else { | } else { | ||||
| Equipment() | Equipment() | ||||
| } | } | ||||
| entity.code = request.code | entity.code = request.code | ||||
| entity.name = request.name | entity.name = request.name | ||||
| entity.description = request.description | entity.description = request.description | ||||
| entity.EquipmentDetail= request.equipmentType | |||||
| entity.EquipmentDetail = request.equipmentType | |||||
| return equipmentRepository.saveAndFlush(entity) | return equipmentRepository.saveAndFlush(entity) | ||||
| } | } | ||||
| @Transactional | @Transactional | ||||
| open fun deleteEquipment(id: Long) { | open fun deleteEquipment(id: Long) { | ||||
| val Equipment = equipmentRepository.findByIdAndDeletedFalse(id) | |||||
| Equipment?.let { et -> | |||||
| val equipment = equipmentRepository.findByIdAndDeletedFalse(id) | |||||
| equipment?.let { et -> | |||||
| et.deleted = true | et.deleted = true | ||||
| equipmentRepository.saveAndFlush(et) | equipmentRepository.saveAndFlush(et) | ||||
| } | } | ||||
| @@ -5,15 +5,22 @@ import com.ffii.core.utils.CriteriaArgsBuilder | |||||
| import com.ffii.core.utils.PagingUtils | import com.ffii.core.utils.PagingUtils | ||||
| import com.ffii.fpsms.modules.master.entity.Equipment | import com.ffii.fpsms.modules.master.entity.Equipment | ||||
| import com.ffii.fpsms.modules.master.service.EquipmentService | import com.ffii.fpsms.modules.master.service.EquipmentService | ||||
| import com.ffii.fpsms.modules.master.service.EquipmentQrCodeService | |||||
| import jakarta.servlet.http.HttpServletRequest | import jakarta.servlet.http.HttpServletRequest | ||||
| import jakarta.servlet.http.HttpServletResponse | |||||
| import jakarta.validation.Valid | import jakarta.validation.Valid | ||||
| import org.springframework.web.bind.annotation.* | import org.springframework.web.bind.annotation.* | ||||
| import java.util.Collections.emptyList | import java.util.Collections.emptyList | ||||
| import com.ffii.fpsms.modules.master.web.models.NewEquipmentRequest | import com.ffii.fpsms.modules.master.web.models.NewEquipmentRequest | ||||
| import net.sf.jasperreports.engine.JasperExportManager | |||||
| import net.sf.jasperreports.engine.JasperPrint | |||||
| import java.io.OutputStream | |||||
| @RestController | @RestController | ||||
| @RequestMapping("/Equipment") | @RequestMapping("/Equipment") | ||||
| class EquipmentController( | class EquipmentController( | ||||
| private val equipmentService: EquipmentService | |||||
| private val equipmentService: EquipmentService, | |||||
| private val equipmentQrCodeService: EquipmentQrCodeService | |||||
| ) { | ) { | ||||
| @GetMapping | @GetMapping | ||||
| fun allEquipment(): List<Equipment> { | fun allEquipment(): List<Equipment> { | ||||
| @@ -73,4 +80,17 @@ fun getAllEquipmentByPage( | |||||
| equipmentService.deleteEquipment(id) | equipmentService.deleteEquipment(id) | ||||
| } | } | ||||
| @PostMapping("/export-qrcode") | |||||
| fun exportQrCode(@Valid @RequestBody request: ExportEquipmentQrCodeRequest, response: HttpServletResponse) { | |||||
| response.characterEncoding = "utf-8" | |||||
| response.contentType = "application/pdf" | |||||
| val out: OutputStream = response.outputStream | |||||
| val pdf = equipmentQrCodeService.exportEquipmentQrCode(request) | |||||
| val jasperPrint = pdf["report"] as JasperPrint | |||||
| val fileName = pdf["fileName"] as String | |||||
| response.addHeader("Content-Disposition", "attachment; filename=\"${fileName}_qrcode.pdf\"") | |||||
| out.write(JasperExportManager.exportReportToPdf(jasperPrint)) | |||||
| out.flush() | |||||
| } | |||||
| } | } | ||||
| @@ -63,6 +63,18 @@ fun getAllEquipmentDetailByPage( | |||||
| return equipmentDetailService.findById(id) | return equipmentDetailService.findById(id) | ||||
| } | } | ||||
| @GetMapping("/byEquipmentId/{equipmentId}") | |||||
| fun getEquipmentDetailsByEquipmentId(@PathVariable equipmentId: Long): RecordsRes<Map<String, Any>> { | |||||
| val fullList = equipmentDetailService.getEquipmentDetailsByEquipmentId(equipmentId) ?: emptyList() | |||||
| return RecordsRes(fullList as List<Map<String, Any>>, fullList.size) | |||||
| } | |||||
| @GetMapping("/byDescriptionIncludingDeleted/{description}") | |||||
| fun getEquipmentDetailsByDescriptionIncludingDeleted(@PathVariable description: String): RecordsRes<Map<String, Any>> { | |||||
| val fullList = equipmentDetailService.getEquipmentDetailsByDescriptionIncludingDeleted(description) ?: emptyList() | |||||
| return RecordsRes(fullList as List<Map<String, Any>>, fullList.size) | |||||
| } | |||||
| @PutMapping("/update/{id}") | @PutMapping("/update/{id}") | ||||
| fun updateMaintenanceAndRepair( | fun updateMaintenanceAndRepair( | ||||
| @PathVariable id: Long, | @PathVariable id: Long, | ||||
| @@ -70,12 +82,10 @@ fun getAllEquipmentDetailByPage( | |||||
| ): EquipmentDetail { | ): EquipmentDetail { | ||||
| return equipmentDetailService.updateMaintenanceAndRepair(id, request) | return equipmentDetailService.updateMaintenanceAndRepair(id, request) | ||||
| } | } | ||||
| /* | |||||
| @PostMapping("/save") | @PostMapping("/save") | ||||
| fun saveEquipmentDetail(@Valid @RequestBody equipmentDetail: NewEquipmentDetailRequest): EquipmentDetail { | fun saveEquipmentDetail(@Valid @RequestBody equipmentDetail: NewEquipmentDetailRequest): EquipmentDetail { | ||||
| return equipmentDetailService.saveEquipmentDetail(equipmentDetail) | return equipmentDetailService.saveEquipmentDetail(equipmentDetail) | ||||
| } | } | ||||
| */ | |||||
| @DeleteMapping("/delete/{id}") | @DeleteMapping("/delete/{id}") | ||||
| fun deleteEquipmentDetail(@PathVariable id: Long) { | fun deleteEquipmentDetail(@PathVariable id: Long) { | ||||
| @@ -0,0 +1,5 @@ | |||||
| package com.ffii.fpsms.modules.master.web | |||||
| data class ExportEquipmentQrCodeRequest( | |||||
| val equipmentDetailIds: List<Long> | |||||
| ) | |||||
| @@ -19,6 +19,9 @@ data class NewEquipmentDetailRequest( | |||||
| val id: Long?, | val id: Long?, | ||||
| val description: String?, | val description: String?, | ||||
| val equipmentTypeId: Long?, | |||||
| val equipmentCode: String?, | |||||
| val repairAndMaintenanceStatus: Boolean?, | |||||
| // val type: List<NewTypeRequest>?, | // val type: List<NewTypeRequest>?, | ||||
| // val uom: List<NewUomRequest>?, | // val uom: List<NewUomRequest>?, | ||||
| // val weightUnit: List<NewWeightUnitRequest>?, | // val weightUnit: List<NewWeightUnitRequest>?, | ||||
| @@ -0,0 +1,43 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <!-- Created with Jaspersoft Studio version 6.21.3.final using JasperReports Library version 6.21.3-4a3078d20785ebe464f18037d738d12fc98c13cf --> | |||||
| <jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="qrCodeHandle" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="80" bottomMargin="20" uuid="c2f7cd27-3725-47ce-ac85-d8a38dc906fa"> | |||||
| <property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/> | |||||
| <property name="com.jaspersoft.studio.unit." value="pixel"/> | |||||
| <property name="com.jaspersoft.studio.unit.pageHeight" value="pixel"/> | |||||
| <property name="com.jaspersoft.studio.unit.pageWidth" value="pixel"/> | |||||
| <property name="com.jaspersoft.studio.unit.topMargin" value="pixel"/> | |||||
| <property name="com.jaspersoft.studio.unit.bottomMargin" value="pixel"/> | |||||
| <property name="com.jaspersoft.studio.unit.leftMargin" value="pixel"/> | |||||
| <property name="com.jaspersoft.studio.unit.rightMargin" value="pixel"/> | |||||
| <property name="com.jaspersoft.studio.unit.columnWidth" value="pixel"/> | |||||
| <property name="com.jaspersoft.studio.unit.columnSpacing" value="pixel"/> | |||||
| <queryString> | |||||
| <![CDATA[]]> | |||||
| </queryString> | |||||
| <field name="username" class="java.lang.String"/> | |||||
| <field name="staffNo" class="java.lang.String"/> | |||||
| <field name="qrCode" class="java.awt.Image"/> | |||||
| <field name="code" class="java.lang.String"/> | |||||
| <background> | |||||
| <band splitType="Stretch"/> | |||||
| </background> | |||||
| <detail> | |||||
| <band height="670" splitType="Stretch"> | |||||
| <textField isStretchWithOverflow="true" isBlankWhenNull="false"> | |||||
| <reportElement stretchType="RelativeToTallestObject" x="37" y="0" width="480" height="120" uuid="e3faf8de-84ba-423f-b6cf-84ba21598686"> | |||||
| <property name="com.jaspersoft.studio.unit.x" value="px"/> | |||||
| <property name="com.jaspersoft.studio.unit.width" value="px"/> | |||||
| <property name="com.jaspersoft.studio.unit.height" value="px"/> | |||||
| </reportElement> | |||||
| <textElement textAlignment="Center" verticalAlignment="Middle"> | |||||
| <font size="34" isBold="true" fontName="微軟正黑體" pdfEncoding="Identity-H" isPdfEmbedded="true"/> | |||||
| </textElement> | |||||
| <textFieldExpression><![CDATA[$F{code}]]></textFieldExpression> | |||||
| </textField> | |||||
| <image> | |||||
| <reportElement x="27" y="120" width="500" height="500" uuid="b1a8ee23-9f0f-4014-9996-e0025222dcd2"/> | |||||
| <imageExpression><![CDATA[$F{qrCode}]]></imageExpression> | |||||
| </image> | |||||
| </band> | |||||
| </detail> | |||||
| </jasperReport> | |||||