diff --git a/build.gradle b/build.gradle index 472eea9..4300c01 100644 --- a/build.gradle +++ b/build.gradle @@ -4,6 +4,7 @@ plugins { id 'io.spring.dependency-management' version '1.1.0' id 'org.jetbrains.kotlin.jvm' id 'org.jetbrains.kotlin.plugin.serialization' version '1.8.0' + } group = 'com.ffii' diff --git a/src/main/java/com/ffii/fpsms/FpsmsApplication.java b/src/main/java/com/ffii/fpsms/FpsmsApplication.java index 30f021e..b79d428 100644 --- a/src/main/java/com/ffii/fpsms/FpsmsApplication.java +++ b/src/main/java/com/ffii/fpsms/FpsmsApplication.java @@ -2,8 +2,10 @@ package com.ffii.fpsms; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; @SpringBootApplication +@ComponentScan(basePackages = {"com.ffii.fpsms", "com.ffii.core"}) public class FpsmsApplication { public static void main(String[] args) { diff --git a/src/main/java/com/ffii/fpsms/modules/master/entity/EquipmentRepository.kt b/src/main/java/com/ffii/fpsms/modules/master/entity/EquipmentRepository.kt index 53ba008..ff005da 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/entity/EquipmentRepository.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/entity/EquipmentRepository.kt @@ -6,6 +6,13 @@ import java.util.Optional @Repository interface EquipmentRepository : AbstractRepository { - fun findByNameAndDeletedIsFalse(name: String): Equipment? - fun findByCodeAndDeletedIsFalse(code: String): Equipment? + fun findAllByDeletedFalse(): List; + fun findByCodeAndDeletedFalse(code: String): Equipment? + fun findByIdAndDeletedFalse(id: Long): Equipment?; + + fun findByCodeAndDeletedIsFalse(code: String): Equipment?; + + fun findByNameAndDeletedIsFalse(name: String): Equipment?; + + fun findByDescriptionAndDeletedIsFalse(description: String): Equipment?; } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/entity/EquipmentType.kt b/src/main/java/com/ffii/fpsms/modules/master/entity/EquipmentType.kt index d7b4c2b..a1c0f31 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/entity/EquipmentType.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/entity/EquipmentType.kt @@ -24,4 +24,6 @@ open class EquipmentType : BaseEntity() { @NotNull @Column(name = "description", nullable = false, length = 500) open var description: String? = null + + } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/entity/EquipmentTypeRepository.kt b/src/main/java/com/ffii/fpsms/modules/master/entity/EquipmentTypeRepository.kt index 7dbd64c..e9fcf8c 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/entity/EquipmentTypeRepository.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/entity/EquipmentTypeRepository.kt @@ -5,4 +5,13 @@ import org.springframework.stereotype.Repository @Repository interface EquipmentTypeRepository : AbstractRepository { + fun findAllByDeletedFalse(): List; + fun findByCodeAndDeletedFalse(code: String): EquipmentType? + fun findByIdAndDeletedFalse(id: Long): EquipmentType?; + + fun findByCodeAndDeletedIsFalse(code: String): EquipmentType?; + + fun findByNameAndDeletedIsFalse(name: String): EquipmentType?; + + fun findByDescriptionAndDeletedIsFalse(description: String): EquipmentType?; } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/service/EquipmentService.kt b/src/main/java/com/ffii/fpsms/modules/master/service/EquipmentService.kt new file mode 100644 index 0000000..742b727 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/master/service/EquipmentService.kt @@ -0,0 +1,94 @@ +package com.ffii.fpsms.modules.master.service + +import com.ffii.core.support.AbstractBaseEntityService +import com.ffii.core.support.JdbcDao +import com.ffii.fpsms.modules.master.entity.Equipment +import com.ffii.fpsms.modules.master.entity.EquipmentRepository +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import com.ffii.fpsms.modules.master.web.models.NewEquipmentRequest +@Service +open class EquipmentService( + private val jdbcDao: JdbcDao, + private val equipmentRepository: EquipmentRepository, +) : AbstractBaseEntityService(jdbcDao, equipmentRepository) { + + open fun allEquipments(): List { + return equipmentRepository.findAll() + } + + open fun getEquipmentsByPage(args: Map): List> { + val sql = StringBuilder( + "SELECT e.id, e.code, e.name, e.description, e.equipmentTypeId FROM equipment e 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) + } + + open fun findById(id: Long): Equipment? { + return equipmentRepository.findByIdAndDeletedFalse(id) + } + + open fun findByCode(code: String): Equipment? { + return equipmentRepository.findByCodeAndDeletedIsFalse(code) + } + + open fun findByName(name: String): Equipment? { + return equipmentRepository.findByNameAndDeletedIsFalse(name) + } + + open fun findByDescription(description: String): Equipment? { + return equipmentRepository.findByDescriptionAndDeletedIsFalse(description) + } + + + @Transactional + open fun saveEquipment(request: NewEquipmentRequest): Equipment { + + if (request.code.isNullOrBlank()) { + throw IllegalArgumentException("Equipment type code cannot be null or blank") + } + val duplicated = equipmentRepository.findByCodeAndDeletedFalse(request.code!!) + if (duplicated != null && duplicated.id != request.id) { + throw IllegalArgumentException("Equipment type code already exists") + } + + + val entity = if (request.id != null && request.id > 0) { + + equipmentRepository.findByIdAndDeletedFalse(request.id) ?: Equipment() + } else { + Equipment() + } + + + entity.code = request.code + entity.name = request.name + entity.description = request.description + entity.equipmentType= request.equipmentType + return equipmentRepository.saveAndFlush(entity) + } + + @Transactional + open fun deleteEquipment(id: Long) { + val Equipment = equipmentRepository.findByIdAndDeletedFalse(id) + Equipment?.let { et -> + et.deleted = true + equipmentRepository.saveAndFlush(et) + } + } +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/service/EquipmentTypeService.kt b/src/main/java/com/ffii/fpsms/modules/master/service/EquipmentTypeService.kt new file mode 100644 index 0000000..234db2f --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/master/service/EquipmentTypeService.kt @@ -0,0 +1,90 @@ +package com.ffii.fpsms.modules.master.service + +import com.ffii.core.support.AbstractBaseEntityService +import com.ffii.core.support.JdbcDao +import com.ffii.fpsms.modules.master.entity.EquipmentType +import com.ffii.fpsms.modules.master.entity.EquipmentTypeRepository +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import com.ffii.fpsms.modules.master.web.models.NewEquipmentTypeRequest +@Service +open class EquipmentTypeService( + private val jdbcDao: JdbcDao, + private val equipmentTypeRepository: EquipmentTypeRepository, +) : AbstractBaseEntityService(jdbcDao, equipmentTypeRepository) { + + open fun allEquipmentTypes(): List { + return equipmentTypeRepository.findAll() + } + + open fun getEquipmentTypesByPage(args: Map): List> { + val sql = StringBuilder( + "SELECT e.id, e.code, e.name, e.description FROM equipment_type e 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 ") + } + return jdbcDao.queryForList(sql.toString(), args) + } + + open fun findById(id: Long): EquipmentType? { + return equipmentTypeRepository.findByIdAndDeletedFalse(id) + } + + open fun findByCode(code: String): EquipmentType? { + return equipmentTypeRepository.findByCodeAndDeletedIsFalse(code) + } + + open fun findByName(name: String): EquipmentType? { + return equipmentTypeRepository.findByNameAndDeletedIsFalse(name) + } + + open fun findByDescription(description: String): EquipmentType? { + return equipmentTypeRepository.findByDescriptionAndDeletedIsFalse(description) + } + + @Transactional + open fun saveEquipmentType(request: NewEquipmentTypeRequest): EquipmentType { + + if (request.code.isNullOrBlank()) { + throw IllegalArgumentException("Equipment type code cannot be null or blank") + } + val duplicated = equipmentTypeRepository.findByCodeAndDeletedFalse(request.code!!) + if (duplicated != null && duplicated.id != request.id) { + throw IllegalArgumentException("Equipment type code already exists") + } + + + val entity = if (request.id != null && request.id > 0) { + + equipmentTypeRepository.findByIdAndDeletedFalse(request.id) ?: EquipmentType() + } else { + EquipmentType() + } + + + entity.code = request.code + entity.name = request.name + entity.description = request.description + + return equipmentTypeRepository.saveAndFlush(entity) + } + + @Transactional + open fun deleteEquipmentType(id: Long) { + val equipmentType = equipmentTypeRepository.findByIdAndDeletedFalse(id) + equipmentType?.let { et -> + et.deleted = true + equipmentTypeRepository.saveAndFlush(et) + } + } +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/web/EquipmentController.kt b/src/main/java/com/ffii/fpsms/modules/master/web/EquipmentController.kt new file mode 100644 index 0000000..b9021ab --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/master/web/EquipmentController.kt @@ -0,0 +1,76 @@ +package com.ffii.fpsms.modules.master.web + +import com.ffii.core.response.RecordsRes +import com.ffii.core.utils.CriteriaArgsBuilder +import com.ffii.core.utils.PagingUtils +import com.ffii.fpsms.modules.master.entity.Equipment +import com.ffii.fpsms.modules.master.service.EquipmentService +import jakarta.servlet.http.HttpServletRequest +import jakarta.validation.Valid +import org.springframework.web.bind.annotation.* +import java.util.Collections.emptyList +import com.ffii.fpsms.modules.master.web.models.NewEquipmentRequest +@RestController +@RequestMapping("/Equipment") +class EquipmentController( + private val equipmentService: EquipmentService +) { + @GetMapping + fun allEquipment(): List { + return equipmentService.allEquipments() + } + +// @GetMapping("/getRecordByPage") +// fun getAllItemsByPage(@RequestBody filterRequest: HttpServletRequest): RecordsRes> { +// val pageSize = filterRequest.getParameter("pageSize").toString().toInt(); // Default to 10 if not provided +// val pageNumber = filterRequest.getParameter("pageNum").toString().toInt(); // Default to 0 if not provided +// val criteriaArgs = CriteriaArgsBuilder.withRequest(filterRequest) +// .addStringLike("name") +// .build(); +// +// val fullList = itemsService.getItemsByPage(criteriaArgs)?.subList(pageSize*pageNumber+1, pageSize*pageNumber+pageSize) +// val outputList = fullList?.subList(pageSize*pageNumber+1, pageSize*pageNumber+pageSize) +// +// return RecordsRes(outputList as List>?, fullList?.size) +// } + +@GetMapping("/getRecordByPage") +fun getAllEquipmentByPage( + request: HttpServletRequest +): RecordsRes> { + val criteriaArgs = CriteriaArgsBuilder.withRequest(request) + .addStringLike("name") + .addStringLike("code") + .addStringLike("description") + .addStringLike("id") + .build() + + val pageSize = request.getParameter("pageSize")?.toIntOrNull() ?: 10 + val pageNum = request.getParameter("pageNum")?.toIntOrNull() ?: 1 + + // 方法名和变量名都要和 Service 保持一致 + val fullList = equipmentService.getEquipmentsByPage(criteriaArgs) ?: emptyList() + val paginatedList = PagingUtils.getPaginatedList(fullList, pageSize, pageNum) + + return RecordsRes(paginatedList as List>, fullList.size) +} + + // 详情 + @GetMapping("/details/{id}") + fun getEquipment(@PathVariable id: Long): Equipment? { + return equipmentService.findById(id) + } + + // 新增/编辑 + @PostMapping("/save") + fun saveEquipment(@Valid @RequestBody equipment: NewEquipmentRequest): Equipment { + return equipmentService.saveEquipment(equipment) + } + + // 逻辑删除 + @DeleteMapping("/delete/{id}") + fun deleteEquipment(@PathVariable id: Long) { + equipmentService.deleteEquipment(id) + } + +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/web/EquipmentTypeController.kt b/src/main/java/com/ffii/fpsms/modules/master/web/EquipmentTypeController.kt new file mode 100644 index 0000000..9a68fb2 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/master/web/EquipmentTypeController.kt @@ -0,0 +1,76 @@ +package com.ffii.fpsms.modules.master.web + +import com.ffii.core.response.RecordsRes +import com.ffii.core.utils.CriteriaArgsBuilder +import com.ffii.core.utils.PagingUtils +import com.ffii.fpsms.modules.master.entity.EquipmentType +import com.ffii.fpsms.modules.master.service.EquipmentTypeService +import jakarta.servlet.http.HttpServletRequest +import jakarta.validation.Valid +import org.springframework.web.bind.annotation.* +import java.util.Collections.emptyList +import com.ffii.fpsms.modules.master.web.models.NewEquipmentTypeRequest +@RestController +@RequestMapping("/EquipmentType") +class EquipmentTypeController( + private val equipmentTypeService: EquipmentTypeService +) { + @GetMapping + fun allEquipmentType(): List { + return equipmentTypeService.allEquipmentTypes() + } + +// @GetMapping("/getRecordByPage") +// fun getAllItemsByPage(@RequestBody filterRequest: HttpServletRequest): RecordsRes> { +// val pageSize = filterRequest.getParameter("pageSize").toString().toInt(); // Default to 10 if not provided +// val pageNumber = filterRequest.getParameter("pageNum").toString().toInt(); // Default to 0 if not provided +// val criteriaArgs = CriteriaArgsBuilder.withRequest(filterRequest) +// .addStringLike("name") +// .build(); +// +// val fullList = itemsService.getItemsByPage(criteriaArgs)?.subList(pageSize*pageNumber+1, pageSize*pageNumber+pageSize) +// val outputList = fullList?.subList(pageSize*pageNumber+1, pageSize*pageNumber+pageSize) +// +// return RecordsRes(outputList as List>?, fullList?.size) +// } + +@GetMapping("/getRecordByPage") +fun getAllEquipmentTypeByPage( + request: HttpServletRequest +): RecordsRes> { + val criteriaArgs = CriteriaArgsBuilder.withRequest(request) + .addStringLike("name") + .addStringLike("code") + .addStringLike("description") + .addStringLike("id") + .build() + + val pageSize = request.getParameter("pageSize")?.toIntOrNull() ?: 10 + val pageNum = request.getParameter("pageNum")?.toIntOrNull() ?: 1 + + // 方法名和变量名都要和 Service 保持一致 + val fullList = equipmentTypeService.getEquipmentTypesByPage(criteriaArgs) ?: emptyList() + val paginatedList = PagingUtils.getPaginatedList(fullList, pageSize, pageNum) + + return RecordsRes(paginatedList as List>, fullList.size) +} + + // 详情 + @GetMapping("/details/{id}") + fun getEquipmentType(@PathVariable id: Long): EquipmentType? { + return equipmentTypeService.findById(id) + } + + // 新增/编辑 + @PostMapping("/save") + fun saveEquipmentType(@Valid @RequestBody equipmentType: NewEquipmentTypeRequest): EquipmentType { + return equipmentTypeService.saveEquipmentType(equipmentType) + } + + // 逻辑删除 + @DeleteMapping("/delete/{id}") + fun deleteEquipmentType(@PathVariable id: Long) { + equipmentTypeService.deleteEquipmentType(id) + } + +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/web/models/NewEquipmentRequest.kt b/src/main/java/com/ffii/fpsms/modules/master/web/models/NewEquipmentRequest.kt new file mode 100644 index 0000000..a8c04f3 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/master/web/models/NewEquipmentRequest.kt @@ -0,0 +1,28 @@ +package com.ffii.fpsms.modules.master.web.models + +import com.ffii.fpsms.modules.master.entity.EquipmentType +import jakarta.validation.constraints.NotBlank +import jakarta.validation.constraints.NotNull +import java.time.LocalDateTime +/* +enum class EquipmentType(val type: String) { + MATERIAL("mat"), + BY_PRODUCT("byp"), + PRODUCT("product"), + CONSUMABLE("consumables"), +} +*/ +data class NewEquipmentRequest( + @field:NotBlank(message = "material code cannot be empty") + val code: String, + @field:NotBlank(message = "material name cannot be empty") + val name: String, + + val id: Long?, + val description: String?, + val equipmentType: EquipmentType?, +// val type: List?, +// val uom: List?, +// val weightUnit: List?, +) + diff --git a/src/main/java/com/ffii/fpsms/modules/master/web/models/NewEquipmentTypeRequest.kt b/src/main/java/com/ffii/fpsms/modules/master/web/models/NewEquipmentTypeRequest.kt new file mode 100644 index 0000000..5556a7d --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/master/web/models/NewEquipmentTypeRequest.kt @@ -0,0 +1,26 @@ +package com.ffii.fpsms.modules.master.web.models + +import jakarta.validation.constraints.NotBlank +import jakarta.validation.constraints.NotNull +import java.time.LocalDateTime +/* +enum class EquipmentType(val type: String) { + MATERIAL("mat"), + BY_PRODUCT("byp"), + PRODUCT("product"), + CONSUMABLE("consumables"), +} +*/ +data class NewEquipmentTypeRequest( + @field:NotBlank(message = "material code cannot be empty") + val code: String, + @field:NotBlank(message = "material name cannot be empty") + val name: String, + + val id: Long?, + val description: String?, +// val type: List?, +// val uom: List?, +// val weightUnit: List?, +) + diff --git a/src/main/java/com/ffii/fpsms/modules/purchaseOrder/web/PurchaseOrderController.kt b/src/main/java/com/ffii/fpsms/modules/purchaseOrder/web/PurchaseOrderController.kt index 5f1f59d..bd5d685 100644 --- a/src/main/java/com/ffii/fpsms/modules/purchaseOrder/web/PurchaseOrderController.kt +++ b/src/main/java/com/ffii/fpsms/modules/purchaseOrder/web/PurchaseOrderController.kt @@ -69,4 +69,5 @@ class PurchaseOrderController( fun checkPolAndCompletePo(@PathVariable id: Long): MessageResponse { return purchaseOrderService.checkPolAndCompletePo(id) } + } \ No newline at end of file diff --git a/src/main/resources/application-db-local.yml b/src/main/resources/application-db-local.yml index 4fa8584..a9c01bf 100644 --- a/src/main/resources/application-db-local.yml +++ b/src/main/resources/application-db-local.yml @@ -1,5 +1,5 @@ spring: datasource: - jdbc-url: jdbc:mysql://127.0.0.1:3306/fpsmsdb?useUnicode=true&characterEncoding=UTF8&serverTimezone=GMT%2B8 + jdbc-url: jdbc:mysql://127.0.0.1:3308/fpsmsdb?useUnicode=true&characterEncoding=UTF8&serverTimezone=GMT%2B8 username: root password: secret \ No newline at end of file diff --git a/src/main/resources/db/changelog/changes/20250627_01_enson/01_add_EquipmentType_column.sql b/src/main/resources/db/changelog/changes/20250627_01_enson/01_add_EquipmentType_column.sql new file mode 100644 index 0000000..7ee7ce2 --- /dev/null +++ b/src/main/resources/db/changelog/changes/20250627_01_enson/01_add_EquipmentType_column.sql @@ -0,0 +1,10 @@ +-- liquibase formatted sql +-- changeset enson:add_EquipmentType_column +ALTER TABLE `equipment_type` + ADD COLUMN `equipmentTypeID` VARCHAR(30) NULL AFTER `description`, + ADD COLUMN `equipmentTypeCapacity` INT(11) NULL AFTER `EquipmentTypeID`, + ADD COLUMN `equipmentTypeUom` VARCHAR(30) NULL AFTER `equipmentTypeCapacity` + + + +; \ No newline at end of file diff --git a/src/main/resources/log4j2.yml b/src/main/resources/log4j2.yml index 1d9a0cd..e3b20ff 100644 --- a/src/main/resources/log4j2.yml +++ b/src/main/resources/log4j2.yml @@ -14,4 +14,5 @@ Configutation: Root: level: info AppenderRef: - - ref: Console_Appender \ No newline at end of file + - ref: Console_Appender + \ No newline at end of file