@@ -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' | |||
@@ -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) { | |||
@@ -6,6 +6,13 @@ import java.util.Optional | |||
@Repository | |||
interface EquipmentRepository : AbstractRepository<Equipment, Long> { | |||
fun findByNameAndDeletedIsFalse(name: String): Equipment? | |||
fun findByCodeAndDeletedIsFalse(code: String): Equipment? | |||
fun findAllByDeletedFalse(): List<Equipment>; | |||
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?; | |||
} |
@@ -24,4 +24,6 @@ open class EquipmentType : BaseEntity<Long>() { | |||
@NotNull | |||
@Column(name = "description", nullable = false, length = 500) | |||
open var description: String? = null | |||
} |
@@ -5,4 +5,13 @@ import org.springframework.stereotype.Repository | |||
@Repository | |||
interface EquipmentTypeRepository : AbstractRepository<EquipmentType, Long> { | |||
fun findAllByDeletedFalse(): List<EquipmentType>; | |||
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?; | |||
} |
@@ -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<Equipment, Long, EquipmentRepository>(jdbcDao, equipmentRepository) { | |||
open fun allEquipments(): List<Equipment> { | |||
return equipmentRepository.findAll() | |||
} | |||
open fun getEquipmentsByPage(args: Map<String, Any>): List<Map<String, Any>> { | |||
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) | |||
} | |||
} | |||
} |
@@ -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<EquipmentType, Long, EquipmentTypeRepository>(jdbcDao, equipmentTypeRepository) { | |||
open fun allEquipmentTypes(): List<EquipmentType> { | |||
return equipmentTypeRepository.findAll() | |||
} | |||
open fun getEquipmentTypesByPage(args: Map<String, Any>): List<Map<String, Any>> { | |||
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) | |||
} | |||
} | |||
} |
@@ -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<Equipment> { | |||
return equipmentService.allEquipments() | |||
} | |||
// @GetMapping("/getRecordByPage") | |||
// fun getAllItemsByPage(@RequestBody filterRequest: HttpServletRequest): RecordsRes<Map<String, Any>> { | |||
// 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<Map<String, Any>>?, fullList?.size) | |||
// } | |||
@GetMapping("/getRecordByPage") | |||
fun getAllEquipmentByPage( | |||
request: HttpServletRequest | |||
): RecordsRes<Map<String, Any>> { | |||
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<Map<String, Any>>, 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) | |||
} | |||
} |
@@ -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<EquipmentType> { | |||
return equipmentTypeService.allEquipmentTypes() | |||
} | |||
// @GetMapping("/getRecordByPage") | |||
// fun getAllItemsByPage(@RequestBody filterRequest: HttpServletRequest): RecordsRes<Map<String, Any>> { | |||
// 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<Map<String, Any>>?, fullList?.size) | |||
// } | |||
@GetMapping("/getRecordByPage") | |||
fun getAllEquipmentTypeByPage( | |||
request: HttpServletRequest | |||
): RecordsRes<Map<String, Any>> { | |||
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<Map<String, Any>>, 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) | |||
} | |||
} |
@@ -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<NewTypeRequest>?, | |||
// val uom: List<NewUomRequest>?, | |||
// val weightUnit: List<NewWeightUnitRequest>?, | |||
) | |||
@@ -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<NewTypeRequest>?, | |||
// val uom: List<NewUomRequest>?, | |||
// val weightUnit: List<NewWeightUnitRequest>?, | |||
) | |||
@@ -69,4 +69,5 @@ class PurchaseOrderController( | |||
fun checkPolAndCompletePo(@PathVariable id: Long): MessageResponse { | |||
return purchaseOrderService.checkPolAndCompletePo(id) | |||
} | |||
} |
@@ -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 |
@@ -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` | |||
; |
@@ -14,4 +14,5 @@ Configutation: | |||
Root: | |||
level: info | |||
AppenderRef: | |||
- ref: Console_Appender | |||
- ref: Console_Appender | |||