Explorar el Código

update qcitemAll

master
CANCERYS\kw093 hace 2 semanas
padre
commit
2090dd1ab2
Se han modificado 12 ficheros con 519 adiciones y 1 borrados
  1. +26
    -0
      src/main/java/com/ffii/fpsms/modules/master/entity/ItemsQcCategoryMappingRepository.kt
  2. +1
    -0
      src/main/java/com/ffii/fpsms/modules/master/entity/QcCategory.kt
  3. +2
    -1
      src/main/java/com/ffii/fpsms/modules/master/entity/QcItemCategory.kt
  4. +2
    -0
      src/main/java/com/ffii/fpsms/modules/master/entity/QcItemCategoryRepository.kt
  5. +301
    -0
      src/main/java/com/ffii/fpsms/modules/master/service/QcItemAllService.kt
  6. +134
    -0
      src/main/java/com/ffii/fpsms/modules/master/web/QcItemAllController.kt
  7. +8
    -0
      src/main/java/com/ffii/fpsms/modules/master/web/models/DeleteResponse.kt
  8. +13
    -0
      src/main/java/com/ffii/fpsms/modules/master/web/models/ItemQcCategoryMappingInfo.kt
  9. +10
    -0
      src/main/java/com/ffii/fpsms/modules/master/web/models/QcCategoryWithItemCount.kt
  10. +10
    -0
      src/main/java/com/ffii/fpsms/modules/master/web/models/QcCategoryWithQcItemCount.kt
  11. +5
    -0
      src/main/resources/db/changelog/changes/20260115_01_Enson/02_alter_table.sql
  12. +7
    -0
      src/main/resources/db/changelog/changes/20260115_01_Enson/03_alter_table.sql

+ 26
- 0
src/main/java/com/ffii/fpsms/modules/master/entity/ItemsQcCategoryMappingRepository.kt Ver fichero

@@ -0,0 +1,26 @@
package com.ffii.fpsms.modules.master.entity

import com.ffii.core.support.AbstractRepository
import org.springframework.data.jpa.repository.Query
import org.springframework.stereotype.Repository

@Repository
interface ItemsQcCategoryMappingRepository : AbstractRepository<ItemsQcCategoryMapping, Long> {
fun countByQcCategoryId(qcCategoryId: Long): Long
fun findAllByQcCategoryId(qcCategoryId: Long): List<ItemsQcCategoryMapping>
fun findAllByItemId(itemId: Long): List<ItemsQcCategoryMapping>
fun findByItemIdAndQcCategoryIdAndType(itemId: Long, qcCategoryId: Long, type: String): ItemsQcCategoryMapping?
@Query(
"""
SELECT map FROM ItemsQcCategoryMapping map
WHERE (:qcCategoryId IS NULL OR map.qcCategoryId = :qcCategoryId)
AND (:itemId IS NULL OR map.itemId = :itemId)
"""
)
fun findMappings(qcCategoryId: Long?, itemId: Long?): List<ItemsQcCategoryMapping>
}


+ 1
- 0
src/main/java/com/ffii/fpsms/modules/master/entity/QcCategory.kt Ver fichero

@@ -36,6 +36,7 @@ open class QcCategory : BaseEntity<Long>() {

@JsonManagedReference
@OneToMany(mappedBy = "qcCategory", cascade = [CascadeType.ALL], orphanRemoval = true)
@com.fasterxml.jackson.annotation.JsonIgnore
open var qcItemCategory: MutableList<QcItemCategory> = mutableListOf()
}



+ 2
- 1
src/main/java/com/ffii/fpsms/modules/master/entity/QcItemCategory.kt Ver fichero

@@ -17,13 +17,14 @@ open class QcItemCategory : IdEntity<Long>() {
@JoinColumn(name = "qcCategoryId")
open var qcCategory: QcCategory? = null

@com.fasterxml.jackson.annotation.JsonIgnoreProperties("qcItemCategory")
@NotNull
@ManyToOne
@JoinColumn(name = "qcItemId")
open var qcItem: QcItem? = null

@NotNull
@Column(name = "order")
@Column(name = "`order`")
open var order: Int = 0

@Size(max = 1000)


+ 2
- 0
src/main/java/com/ffii/fpsms/modules/master/entity/QcItemCategoryRepository.kt Ver fichero

@@ -8,4 +8,6 @@ import org.springframework.stereotype.Repository
@Repository
interface QcItemCategoryRepository : AbstractRepository<QcItemCategory, Long> {
fun findAllByQcCategoryId(qcCategoryId : Long): List<QcItemInfo>
fun countByQcItemId(qcItemId: Long): Long
}

+ 301
- 0
src/main/java/com/ffii/fpsms/modules/master/service/QcItemAllService.kt Ver fichero

@@ -0,0 +1,301 @@
package com.ffii.fpsms.modules.master.service

import com.ffii.core.exception.NotFoundException
import com.ffii.fpsms.modules.master.entity.*
import com.ffii.fpsms.modules.master.web.models.*
import com.ffii.fpsms.modules.qc.entity.projection.QcItemInfo
import jakarta.validation.Valid
import org.springframework.stereotype.Service
import org.springframework.web.bind.annotation.RequestBody

@Service
open class QcItemAllService(
private val qcCategoryRepository: QcCategoryRepository,
private val qcItemRepository: QcItemRepository,
private val qcItemCategoryRepository: QcItemCategoryRepository,
private val itemsQcCategoryMappingRepository: ItemsQcCategoryMappingRepository,
private val itemsRepository: ItemsRepository
) {
// Get item count by qc category
open fun getItemCountByQcCategory(qcCategoryId: Long): Long {
return itemsQcCategoryMappingRepository.countByQcCategoryId(qcCategoryId)
}
// Get qc item count by qc category
open fun getQcItemCountByQcCategory(qcCategoryId: Long): Long {
return qcItemCategoryRepository.findAllByQcCategoryId(qcCategoryId).size.toLong()
}
// Get all qc categories with item counts (batch operation for performance)
open fun getAllQcCategoriesWithItemCounts(): List<QcCategoryWithItemCount> {
val categories = qcCategoryRepository.findAllByDeletedIsFalse()
val allMappings = itemsQcCategoryMappingRepository.findAll()
// Group mappings by qcCategoryId and count
val countMap = allMappings
.filter { it.qcCategoryId != null }
.groupBy { it.qcCategoryId!! }
.mapValues { it.value.size.toLong() }
return categories.map { category ->
QcCategoryWithItemCount(
id = category.id!!,
code = category.code,
name = category.name,
description = category.description,
itemCount = countMap[category.id] ?: 0L
)
}
}
// Get all qc categories with qc item counts (batch operation for performance)
open fun getAllQcCategoriesWithQcItemCounts(): List<QcCategoryWithQcItemCount> {
val categories = qcCategoryRepository.findAllByDeletedIsFalse()
val allMappings = qcItemCategoryRepository.findAll()
// Group mappings by qcCategoryId and count
val countMap = allMappings
.filter { it.qcCategory?.id != null }
.groupBy { it.qcCategory!!.id!! }
.mapValues { it.value.size.toLong() }
return categories.map { category ->
QcCategoryWithQcItemCount(
id = category.id!!,
code = category.code,
name = category.name,
description = category.description,
qcItemCount = countMap[category.id] ?: 0L
)
}
}
// Check if can delete qc category
open fun canDeleteQcCategory(id: Long): Boolean {
val itemCount = getItemCountByQcCategory(id)
val qcItemCount = getQcItemCountByQcCategory(id)
return itemCount == 0L && qcItemCount == 0L
}
// Check if can delete qc item
open fun canDeleteQcItem(id: Long): Boolean {
// Check if this qc item is linked to any qc category
val count = qcItemCategoryRepository.countByQcItemId(id)
return count == 0L
}
// Get item and qc category mappings
open fun getItemQcCategoryMappings(qcCategoryId: Long?, itemId: Long?): List<ItemQcCategoryMappingInfo> {
val mappings = itemsQcCategoryMappingRepository.findMappings(qcCategoryId, itemId)
return mappings.map { mapping ->
val item = if (mapping.itemId != null) itemsRepository.findById(mapping.itemId!!).orElse(null) else null
val qcCategory = if (mapping.qcCategoryId != null) qcCategoryRepository.findById(mapping.qcCategoryId!!).orElse(null) else null
ItemQcCategoryMappingInfo(
id = mapping.id!!,
itemId = mapping.itemId ?: 0L,
itemCode = item?.code,
itemName = item?.name,
qcCategoryId = mapping.qcCategoryId ?: 0L,
qcCategoryCode = qcCategory?.code,
qcCategoryName = qcCategory?.name,
type = mapping.type
)
}
}
// Save item and qc category mapping
open fun saveItemQcCategoryMapping(itemId: Long, qcCategoryId: Long, type: String): ItemQcCategoryMappingInfo {
// Check if mapping already exists
val existing = itemsQcCategoryMappingRepository.findByItemIdAndQcCategoryIdAndType(itemId, qcCategoryId, type)
val mapping = existing ?: ItemsQcCategoryMapping()
mapping.itemId = itemId
mapping.qcCategoryId = qcCategoryId
mapping.type = type
val saved = itemsQcCategoryMappingRepository.save(mapping)
val item = itemsRepository.findById(itemId).orElseThrow { NotFoundException() }
val qcCategory = qcCategoryRepository.findById(qcCategoryId).orElseThrow { NotFoundException() }
return ItemQcCategoryMappingInfo(
id = saved.id!!,
itemId = saved.itemId ?: 0L,
itemCode = item.code,
itemName = item.name,
qcCategoryId = saved.qcCategoryId ?: 0L,
qcCategoryCode = qcCategory.code,
qcCategoryName = qcCategory.name,
type = saved.type
)
}
// Delete item and qc category mapping
open fun deleteItemQcCategoryMapping(mappingId: Long) {
itemsQcCategoryMappingRepository.deleteById(mappingId)
}
// Get qc category and qc item mappings
open fun getQcCategoryQcItemMappings(qcCategoryId: Long): List<QcItemInfo> {
return qcItemCategoryRepository.findAllByQcCategoryId(qcCategoryId)
}
// Save qc category and qc item mapping
open fun saveQcCategoryQcItemMapping(
qcCategoryId: Long,
qcItemId: Long,
order: Int,
description: String?
): QcItemCategory {
val qcCategory = qcCategoryRepository.findById(qcCategoryId).orElseThrow { NotFoundException() }
val qcItem = qcItemRepository.findById(qcItemId).orElseThrow { NotFoundException() }
// Check if mapping already exists
val existing = qcCategory.qcItemCategory.firstOrNull { it.qcItem?.id == qcItemId }
val mapping = existing ?: QcItemCategory()
mapping.qcCategory = qcCategory
mapping.qcItem = qcItem
mapping.order = order
// Description is optional - use qcItem's description if not provided
mapping.description = description ?: qcItem.description
if (existing == null) {
qcCategory.qcItemCategory.add(mapping)
}
val savedCategory = qcCategoryRepository.save(qcCategory)
// Return the saved mapping from the saved category to avoid lazy loading issues
return savedCategory.qcItemCategory.firstOrNull { it.qcItem?.id == qcItemId } ?: mapping
}
// Delete qc category and qc item mapping
open fun deleteQcCategoryQcItemMapping(mappingId: Long) {
val mapping = qcItemCategoryRepository.findById(mappingId).orElseThrow { NotFoundException() }
val qcCategory = mapping.qcCategory
if (qcCategory != null) {
qcCategory.qcItemCategory.remove(mapping)
qcCategoryRepository.save(qcCategory)
}
qcItemCategoryRepository.delete(mapping)
}
// Save qc category with validation
open fun saveQcCategoryWithValidation(@Valid @RequestBody request: SaveQcCategoryRequest): SaveQcCategoryResponse {
val errors = mutableMapOf<String, String>()
val id = request.id
val qcCategory = if (id != null) qcCategoryRepository.findById(id).orElseThrow() else QcCategory()
if (errors.isNotEmpty()) {
return SaveQcCategoryResponse(
id = request.id,
code = request.code,
name = request.name,
description = request.description,
errors = errors
)
}
qcCategory.apply {
code = request.code
name = request.name
description = request.description
}
val savedQcCategory = qcCategoryRepository.save(qcCategory)
return SaveQcCategoryResponse(
id = savedQcCategory.id,
code = savedQcCategory.code,
name = savedQcCategory.name,
description = savedQcCategory.description,
errors = null
)
}
// Delete qc category with validation
open fun deleteQcCategoryWithValidation(id: Long): DeleteResponse {
if (!canDeleteQcCategory(id)) {
val itemCount = getItemCountByQcCategory(id)
val qcItemCount = getQcItemCountByQcCategory(id)
return DeleteResponse(
success = false,
canDelete = false,
message = "Cannot delete QcCategory. It has $itemCount item(s) and $qcItemCount qc item(s) linked to it."
)
}
val qcCategory = qcCategoryRepository.findById(id).orElseThrow { NotFoundException() }
qcCategory.deleted = true
qcCategoryRepository.save(qcCategory)
return DeleteResponse(
success = true,
canDelete = true,
message = "QcCategory deleted successfully"
)
}
// Save qc item with validation
open fun saveQcItemWithValidation(@Valid @RequestBody request: SaveQcItemRequest): SaveQcItemResponse {
val errors = mutableMapOf<String, String>()
val id = request.id
val qcItem = if (id != null) qcItemRepository.findById(id).orElseThrow() else QcItem()
if (errors.isNotEmpty()) {
return SaveQcItemResponse(
id = request.id,
code = request.code,
name = request.name,
description = request.description,
errors = errors
)
}
qcItem.apply {
code = request.code
name = request.name
description = request.description
}
val savedQcItem = qcItemRepository.save(qcItem)
return SaveQcItemResponse(
id = savedQcItem.id,
code = savedQcItem.code,
name = savedQcItem.name,
description = savedQcItem.description,
errors = null
)
}
// Delete qc item with validation
open fun deleteQcItemWithValidation(id: Long): DeleteResponse {
if (!canDeleteQcItem(id)) {
return DeleteResponse(
success = false,
canDelete = false,
message = "Cannot delete QcItem. It is linked to one or more QcCategories."
)
}
val qcItem = qcItemRepository.findById(id).orElseThrow { NotFoundException() }
qcItem.deleted = true
qcItemRepository.save(qcItem)
return DeleteResponse(
success = true,
canDelete = true,
message = "QcItem deleted successfully"
)
}
// Get item by code (for Tab 0 - validate item code input)
open fun getItemByCode(code: String): Items? {
return itemsRepository.findByCodeAndDeletedFalse(code)
}
}


+ 134
- 0
src/main/java/com/ffii/fpsms/modules/master/web/QcItemAllController.kt Ver fichero

@@ -0,0 +1,134 @@
package com.ffii.fpsms.modules.master.web

import com.ffii.core.exception.NotFoundException
import com.ffii.fpsms.modules.master.entity.Items
import com.ffii.fpsms.modules.master.service.QcItemAllService
import com.ffii.fpsms.modules.master.web.models.*
import com.ffii.fpsms.modules.qc.entity.projection.QcItemInfo
import jakarta.validation.Valid
import org.springframework.web.bind.annotation.*

@RestController
@RequestMapping("/qcItemAll")
class QcItemAllController(
private val qcItemAllService: QcItemAllService
) {
// Get item count by qc category
@GetMapping("/itemCount/{qcCategoryId}")
fun getItemCountByQcCategory(@PathVariable qcCategoryId: Long): Long {
return qcItemAllService.getItemCountByQcCategory(qcCategoryId)
}
// Get qc item count by qc category
@GetMapping("/qcItemCount/{qcCategoryId}")
fun getQcItemCountByQcCategory(@PathVariable qcCategoryId: Long): Long {
return qcItemAllService.getQcItemCountByQcCategory(qcCategoryId)
}
// Get all qc categories with item counts (batch operation for performance)
@GetMapping("/categoriesWithItemCounts")
fun getAllQcCategoriesWithItemCounts(): List<QcCategoryWithItemCount> {
return qcItemAllService.getAllQcCategoriesWithItemCounts()
}
// Get all qc categories with qc item counts (batch operation for performance)
@GetMapping("/categoriesWithQcItemCounts")
fun getAllQcCategoriesWithQcItemCounts(): List<QcCategoryWithQcItemCount> {
return qcItemAllService.getAllQcCategoriesWithQcItemCounts()
}
// Check if can delete qc category
@GetMapping("/canDeleteQcCategory/{id}")
fun canDeleteQcCategory(@PathVariable id: Long): Boolean {
return qcItemAllService.canDeleteQcCategory(id)
}
// Check if can delete qc item
@GetMapping("/canDeleteQcItem/{id}")
fun canDeleteQcItem(@PathVariable id: Long): Boolean {
return qcItemAllService.canDeleteQcItem(id)
}
// Get item and qc category mappings
@GetMapping("/itemMappings")
fun getItemQcCategoryMappings(
@RequestParam(required = false) qcCategoryId: Long?,
@RequestParam(required = false) itemId: Long?
): List<ItemQcCategoryMappingInfo> {
return qcItemAllService.getItemQcCategoryMappings(qcCategoryId, itemId)
}
// Save item and qc category mapping
@PostMapping("/itemMapping")
fun saveItemQcCategoryMapping(
@RequestParam itemId: Long,
@RequestParam qcCategoryId: Long,
@RequestParam type: String
): ItemQcCategoryMappingInfo {
return qcItemAllService.saveItemQcCategoryMapping(itemId, qcCategoryId, type)
}
// Delete item and qc category mapping
@DeleteMapping("/itemMapping/{mappingId}")
fun deleteItemQcCategoryMapping(@PathVariable mappingId: Long) {
qcItemAllService.deleteItemQcCategoryMapping(mappingId)
}
// Get qc category and qc item mappings
@GetMapping("/qcItemMappings/{qcCategoryId}")
fun getQcCategoryQcItemMappings(@PathVariable qcCategoryId: Long): List<QcItemInfo> {
return qcItemAllService.getQcCategoryQcItemMappings(qcCategoryId)
}
// Save qc category and qc item mapping
@PostMapping("/qcItemMapping")
fun saveQcCategoryQcItemMapping(
@RequestParam qcCategoryId: Long,
@RequestParam qcItemId: Long,
@RequestParam order: Int,
@RequestParam(required = false) description: String?
): QcItemInfo {
qcItemAllService.saveQcCategoryQcItemMapping(qcCategoryId, qcItemId, order, description)
// Reload to get the projection (avoids circular reference issues)
val mappings = qcItemAllService.getQcCategoryQcItemMappings(qcCategoryId)
return mappings.firstOrNull { it.qcItemId == qcItemId } ?: throw NotFoundException()
}
// Delete qc category and qc item mapping
@DeleteMapping("/qcItemMapping/{mappingId}")
fun deleteQcCategoryQcItemMapping(@PathVariable mappingId: Long) {
qcItemAllService.deleteQcCategoryQcItemMapping(mappingId)
}
// Save qc category with validation
@PostMapping("/saveQcCategory")
fun saveQcCategoryWithValidation(@Valid @RequestBody request: SaveQcCategoryRequest): SaveQcCategoryResponse {
return qcItemAllService.saveQcCategoryWithValidation(request)
}
// Delete qc category with validation
@DeleteMapping("/deleteQcCategory/{id}")
fun deleteQcCategoryWithValidation(@PathVariable id: Long): DeleteResponse {
return qcItemAllService.deleteQcCategoryWithValidation(id)
}
// Save qc item with validation
@PostMapping("/saveQcItem")
fun saveQcItemWithValidation(@Valid @RequestBody request: SaveQcItemRequest): SaveQcItemResponse {
return qcItemAllService.saveQcItemWithValidation(request)
}
// Delete qc item with validation
@DeleteMapping("/deleteQcItem/{id}")
fun deleteQcItemWithValidation(@PathVariable id: Long): DeleteResponse {
return qcItemAllService.deleteQcItemWithValidation(id)
}
// Get item by code (for Tab 0 - validate item code input)
@GetMapping("/itemByCode/{code}")
fun getItemByCode(@PathVariable code: String): Items? {
return qcItemAllService.getItemByCode(code)
}
}


+ 8
- 0
src/main/java/com/ffii/fpsms/modules/master/web/models/DeleteResponse.kt Ver fichero

@@ -0,0 +1,8 @@
package com.ffii.fpsms.modules.master.web.models

data class DeleteResponse(
val success: Boolean,
val message: String?,
val canDelete: Boolean = true
)


+ 13
- 0
src/main/java/com/ffii/fpsms/modules/master/web/models/ItemQcCategoryMappingInfo.kt Ver fichero

@@ -0,0 +1,13 @@
package com.ffii.fpsms.modules.master.web.models

data class ItemQcCategoryMappingInfo(
val id: Long,
val itemId: Long,
val itemCode: String?,
val itemName: String?,
val qcCategoryId: Long,
val qcCategoryCode: String?,
val qcCategoryName: String?,
val type: String?
)


+ 10
- 0
src/main/java/com/ffii/fpsms/modules/master/web/models/QcCategoryWithItemCount.kt Ver fichero

@@ -0,0 +1,10 @@
package com.ffii.fpsms.modules.master.web.models

data class QcCategoryWithItemCount(
val id: Long,
val code: String?,
val name: String?,
val description: String?,
val itemCount: Long
)


+ 10
- 0
src/main/java/com/ffii/fpsms/modules/master/web/models/QcCategoryWithQcItemCount.kt Ver fichero

@@ -0,0 +1,10 @@
package com.ffii.fpsms.modules.master.web.models

data class QcCategoryWithQcItemCount(
val id: Long,
val code: String?,
val name: String?,
val description: String?,
val qcItemCount: Long
)


+ 5
- 0
src/main/resources/db/changelog/changes/20260115_01_Enson/02_alter_table.sql Ver fichero

@@ -0,0 +1,5 @@
--liquibase formatted sql
--changeset author:add_type_and_item_id_to_stock_ledger

ALTER TABLE `fpsmsdb`.`pick_execution_issue`
add column `is_original` tinyint(1) default 0;

+ 7
- 0
src/main/resources/db/changelog/changes/20260115_01_Enson/03_alter_table.sql Ver fichero

@@ -0,0 +1,7 @@
--liquibase formatted sql
--changeset author:add_type_and_item_id_to_stock_ledger

ALTER TABLE `fpsmsdb`.`productprocessline`
add column `is_original` tinyint(1) default 0;
ALTER TABLE `fpsmsdb`.`pick_execution_issue`
drop column `is_original`;

Cargando…
Cancelar
Guardar