@@ -3,8 +3,4 @@ package com.ffii.fpsms.enums | |||
enum class Status(val value: Int) { | |||
PENDING(1), | |||
COMPLETE(2) | |||
} | |||
enum class RelationColumnType(val col: String) { | |||
MATERIAL("materialId"), | |||
PRODUCT("productId") | |||
} |
@@ -0,0 +1,15 @@ | |||
package com.ffii.fpsms.modules.master.entity | |||
import com.fasterxml.jackson.annotation.JsonBackReference | |||
import com.ffii.core.entity.IdEntity | |||
import jakarta.persistence.* | |||
import jakarta.validation.constraints.NotNull | |||
@Entity | |||
@Table(name = "item_type") | |||
open class ItemType: IdEntity<Long>() { | |||
@NotNull | |||
@Column(name = "name") | |||
open var name: String? = null | |||
} |
@@ -0,0 +1,10 @@ | |||
package com.ffii.fpsms.modules.master.entity | |||
import com.ffii.core.support.AbstractRepository | |||
import org.springframework.stereotype.Repository | |||
import org.springframework.transaction.annotation.Transactional | |||
@Repository | |||
interface ItemTypeRepository : AbstractRepository<ItemType, Long> { | |||
} |
@@ -7,8 +7,8 @@ import jakarta.persistence.* | |||
import jakarta.validation.constraints.NotNull | |||
@Entity | |||
@Table(name = "product") | |||
open class Product : BaseEntity<Long>() { | |||
@Table(name = "items") | |||
open class Items : BaseEntity<Long>() { | |||
@NotNull | |||
@Column(name = "code") | |||
open var code: String? = null | |||
@@ -23,20 +23,10 @@ open class Product : BaseEntity<Long>() { | |||
@Column(name = "remarks") | |||
open var remarks: String? = null | |||
@OneToMany(mappedBy = "product", cascade = [CascadeType.ALL], orphanRemoval = true) | |||
@JsonManagedReference("product-weight-unit") | |||
@JsonInclude(JsonInclude.Include.NON_NULL) | |||
private val weightUnit: Set<ProductMaterialWeightUnit> = HashSet() | |||
@OneToMany(mappedBy = "product", cascade = [CascadeType.ALL], orphanRemoval = true) | |||
@JsonManagedReference("product-uom") | |||
@JsonInclude(JsonInclude.Include.NON_NULL) | |||
private val uom: Set<ProductMaterialWeightUnit> = HashSet() | |||
@OneToMany(mappedBy = "product", cascade = [CascadeType.ALL], orphanRemoval = true) | |||
@JsonManagedReference("product-uom") | |||
@JsonInclude(JsonInclude.Include.NON_NULL) | |||
private val type: Set<ProductMaterialType> = HashSet() | |||
// (mappedBy = "items", cascade = [CascadeType.ALL], orphanRemoval = true) | |||
@OneToOne | |||
@JoinColumn(name = "typeId", referencedColumnName = "id") | |||
open var type: ItemType? = null | |||
@Column(name = "shelfLife") | |||
open var shelfLife: Double? = null |
@@ -0,0 +1,11 @@ | |||
package com.ffii.fpsms.modules.master.entity | |||
import com.ffii.core.support.AbstractRepository | |||
import org.springframework.stereotype.Repository | |||
@Repository | |||
interface ItemsRepository : AbstractRepository<Items, Long> { | |||
fun findAllByDeletedFalse(): List<Items>; | |||
fun findByIdAndTypeIdAndDeletedFalse(id: Long, typeId: Long): Items; | |||
fun findByCodeAndTypeIdAndDeletedFalse(code: String, typeId: Long): Items?; | |||
} |
@@ -1,71 +0,0 @@ | |||
package com.ffii.fpsms.modules.master.entity | |||
import com.fasterxml.jackson.annotation.JsonInclude | |||
import com.fasterxml.jackson.annotation.JsonManagedReference | |||
import com.ffii.core.entity.BaseEntity | |||
import jakarta.persistence.* | |||
import jakarta.validation.constraints.NotNull | |||
@Entity | |||
@Table(name = "material") | |||
open class Material : BaseEntity<Long>() { | |||
@NotNull | |||
@Column(name = "code") | |||
open var code: String? = null | |||
@NotNull | |||
@Column(name = "name") | |||
open var name: String? = null | |||
@Column(name = "description") | |||
open var description: String? = null | |||
@Column(name = "remarks") | |||
open var remarks: String? = null | |||
@NotNull | |||
@Column(name = "isConsumables") | |||
open var isConsumables: Boolean? = null | |||
@OneToMany(mappedBy = "material", cascade = [CascadeType.ALL], orphanRemoval = true) | |||
@JsonManagedReference("material-weight-unit") | |||
@JsonInclude(JsonInclude.Include.NON_NULL) | |||
private val weightUnit: Set<ProductMaterialWeightUnit> = HashSet() | |||
@OneToMany(mappedBy = "material", cascade = [CascadeType.ALL], orphanRemoval = true) | |||
@JsonManagedReference("material-uom") | |||
@JsonInclude(JsonInclude.Include.NON_NULL) | |||
private val uom: Set<ProductMaterialUom> = HashSet() | |||
@OneToMany(mappedBy = "material", cascade = [CascadeType.ALL], orphanRemoval = true) | |||
@JsonManagedReference("material-type") | |||
@JsonInclude(JsonInclude.Include.NON_NULL) | |||
private val type: Set<ProductMaterialType> = HashSet() | |||
@Column(name = "shelfLife") | |||
open var shelfLife: Double? = null | |||
@Column(name = "countryOfOrigin") | |||
open var countryOfOrigin: String? = null | |||
@Column(name = "minHumid") | |||
open var minHumid: Double? = null | |||
@Column(name = "maxHumid") | |||
open var maxHumid: Double? = null | |||
@Column(name = "minTemp") | |||
open var minTemp: Double? = null | |||
@Column(name = "maxTemp") | |||
open var maxTemp: Double? = null | |||
@Column(name = "sampleRate") | |||
open var sampleRate: Double? = null | |||
@Column(name = "passingRate") | |||
open var passingRate: Double? = null | |||
@Column(name = "netWeight") | |||
open var netWeight: Double? = null | |||
} |
@@ -1,12 +0,0 @@ | |||
package com.ffii.fpsms.modules.master.entity | |||
import com.ffii.core.support.AbstractRepository | |||
import org.springframework.stereotype.Repository | |||
import java.util.Optional | |||
@Repository | |||
interface MaterialRepository : AbstractRepository<Material, Long> { | |||
fun findAllByDeletedFalse(): List<Material>; | |||
fun findByIdAndDeletedFalse(id: Long): Material; | |||
fun findByCodeAndDeletedIsFalse(code: String): Material?; | |||
} |
@@ -1,25 +0,0 @@ | |||
package com.ffii.fpsms.modules.master.entity | |||
import com.fasterxml.jackson.annotation.JsonBackReference | |||
import com.ffii.core.entity.IdEntity | |||
import jakarta.persistence.* | |||
import jakarta.validation.constraints.NotNull | |||
@Entity | |||
@Table(name = "product_material_type") | |||
open class ProductMaterialType: IdEntity<Long>() { | |||
@ManyToOne | |||
@JoinColumn(name = "productId") | |||
@JsonBackReference | |||
open var product: Product? = null | |||
@ManyToOne | |||
@JoinColumn(name = "materialId") | |||
@JsonBackReference | |||
open var material: Material? = null | |||
@NotNull | |||
@Column(name = "type") | |||
open var type: String? = null | |||
} |
@@ -1,14 +0,0 @@ | |||
package com.ffii.fpsms.modules.master.entity | |||
import com.ffii.core.support.AbstractRepository | |||
import org.springframework.stereotype.Repository | |||
import org.springframework.transaction.annotation.Transactional | |||
import java.util.Optional | |||
@Repository | |||
interface ProductMaterialTypeRepository : AbstractRepository<ProductMaterialType, Long> { | |||
@Transactional | |||
fun deleteAllByMaterialId(id: Long) | |||
@Transactional | |||
fun deleteAllByProductId(id: Long) | |||
} |
@@ -1,24 +0,0 @@ | |||
package com.ffii.fpsms.modules.master.entity | |||
import com.fasterxml.jackson.annotation.JsonBackReference | |||
import com.ffii.core.entity.IdEntity | |||
import jakarta.persistence.* | |||
import jakarta.validation.constraints.NotNull | |||
@Entity | |||
@Table(name = "product_material_uom") | |||
open class ProductMaterialUom: IdEntity<Long>() { | |||
@ManyToOne | |||
@JoinColumn(name = "productId") | |||
@JsonBackReference | |||
open var product: Product? = null | |||
@ManyToOne | |||
@JoinColumn(name = "materialId") | |||
@JsonBackReference | |||
open var material: Material? = null | |||
@NotNull | |||
@Column(name = "uom") | |||
open var uom: String? = null | |||
} |
@@ -1,17 +0,0 @@ | |||
package com.ffii.fpsms.modules.master.entity | |||
import com.ffii.core.support.AbstractRepository | |||
import org.springframework.data.jpa.repository.Modifying | |||
import org.springframework.data.jpa.repository.Query | |||
import org.springframework.stereotype.Repository | |||
import org.springframework.transaction.annotation.Transactional | |||
@Repository | |||
interface ProductMaterialUomRepository : AbstractRepository<ProductMaterialUom, Long> { | |||
@Transactional | |||
fun deleteAllByMaterialId(id: Long) | |||
@Transactional | |||
fun deleteAllByProductId(id: Long) | |||
} |
@@ -1,29 +0,0 @@ | |||
package com.ffii.fpsms.modules.master.entity | |||
import com.fasterxml.jackson.annotation.JsonBackReference | |||
import com.ffii.core.entity.IdEntity | |||
import jakarta.persistence.* | |||
import jakarta.validation.constraints.NotNull | |||
@Entity | |||
@Table(name = "product_material_weightUnit") | |||
open class ProductMaterialWeightUnit: IdEntity<Long>() { | |||
@ManyToOne | |||
@JoinColumn(name = "productId") | |||
@JsonBackReference | |||
open var product: Product? = null | |||
@ManyToOne | |||
@JoinColumn(name = "materialId") | |||
@JsonBackReference | |||
open var material: Material? = null | |||
@NotNull | |||
@Column(name = "weightUnit") | |||
open var weightUnit: String? = null | |||
@NotNull | |||
@Column(name = "conversion") | |||
open var conversion: Double? = null | |||
} |
@@ -1,12 +0,0 @@ | |||
package com.ffii.fpsms.modules.master.entity | |||
import com.ffii.core.support.AbstractRepository | |||
import org.springframework.stereotype.Repository | |||
import org.springframework.transaction.annotation.Transactional | |||
@Repository | |||
interface ProductMaterialWeightUnitRepository : AbstractRepository<ProductMaterialWeightUnit, Long> { | |||
@Transactional | |||
fun deleteAllByMaterialId(id: Long) | |||
@Transactional | |||
fun deleteAllByProductId(id: Long) | |||
} |
@@ -1,10 +0,0 @@ | |||
package com.ffii.fpsms.modules.master.entity | |||
import com.ffii.core.support.AbstractRepository | |||
interface ProductRepository: AbstractRepository<Product, Long> { | |||
fun findAllByDeletedFalse(): List<Product>; | |||
fun findByIdAndDeletedFalse(id: Long): Product; | |||
fun findByCodeAndDeletedIsFalse(code: String): Product?; | |||
} |
@@ -0,0 +1,17 @@ | |||
package com.ffii.fpsms.modules.master.service | |||
import com.ffii.core.support.AbstractBaseEntityService | |||
import com.ffii.core.support.AbstractIdEntityService | |||
import com.ffii.core.support.JdbcDao | |||
import com.ffii.fpsms.modules.master.entity.* | |||
import com.ffii.fpsms.modules.master.web.models.MessageResponse | |||
import org.springframework.stereotype.Service | |||
import org.springframework.transaction.annotation.Transactional | |||
@Service | |||
open class ItemTypeService( | |||
private val jdbcDao: JdbcDao, | |||
private val itemTypeRepository: ItemTypeRepository | |||
): AbstractIdEntityService<ItemType, Long, ItemTypeRepository>(jdbcDao, itemTypeRepository) { | |||
} |
@@ -0,0 +1,72 @@ | |||
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.ItemTypeRepository | |||
import com.ffii.fpsms.modules.master.entity.Items | |||
import com.ffii.fpsms.modules.master.entity.ItemsRepository | |||
import com.ffii.fpsms.modules.master.web.models.MessageResponse | |||
import com.ffii.fpsms.modules.master.web.models.NewItemRequest | |||
import org.springframework.stereotype.Service | |||
import org.springframework.transaction.annotation.Transactional | |||
import kotlin.jvm.optionals.getOrNull | |||
@Service | |||
open class ItemsService( | |||
private val jdbcDao: JdbcDao, | |||
private val itemsRepository: ItemsRepository, | |||
private val itemTypeRepository: ItemTypeRepository, | |||
): AbstractBaseEntityService<Items, Long, ItemsRepository>(jdbcDao, itemsRepository) { | |||
// do mapping with projection | |||
open fun allItems(): List<Items> { | |||
// TODO: Replace by actual logic | |||
val items = itemsRepository.findAll() | |||
return items | |||
} | |||
open fun getItem(id: Long): Items? { | |||
return itemsRepository.findById(id).getOrNull() | |||
} | |||
@Transactional | |||
open fun saveItem(request: NewItemRequest): MessageResponse { | |||
val type = itemTypeRepository.findById(request.typeId).get() | |||
val duplicatedItem = itemsRepository.findByCodeAndTypeIdAndDeletedFalse(request.code, request.typeId) | |||
if (duplicatedItem != null && duplicatedItem.id != request.id) { | |||
return MessageResponse( | |||
id = request.id, | |||
code = request.code, | |||
name = request.name, | |||
type = type.name, | |||
message = "The item code has already existed", | |||
errorPosition = "code" | |||
) | |||
} | |||
val item = if (request.id != null && request.id > 0) itemsRepository.findByIdAndTypeIdAndDeletedFalse(request.id, request.typeId) | |||
else Items() | |||
println(request.netWeight) | |||
item.apply { | |||
code = request.code | |||
name = request.name | |||
description = request.description | |||
remarks = request.remarks | |||
shelfLife = request.shelfLife | |||
countryOfOrigin = request.countryOfOrigin | |||
minHumid = request.minHumid | |||
maxHumid = request.maxHumid | |||
minTemp = request.minTemp | |||
maxTemp = request.maxTemp | |||
sampleRate = request.sampleRate | |||
passingRate = request.passingRate | |||
netWeight = request.netWeight | |||
this.type = type | |||
} | |||
val savedItem = itemsRepository.saveAndFlush(item) | |||
return MessageResponse( | |||
id = savedItem.id, | |||
name = savedItem.name, | |||
code = savedItem.code, | |||
type = type.name, | |||
message = "Item Save Success", | |||
errorPosition = null, | |||
) | |||
} | |||
} |
@@ -1,76 +0,0 @@ | |||
package com.ffii.fpsms.modules.master.service | |||
import com.ffii.core.support.AbstractBaseEntityService | |||
import com.ffii.core.support.JdbcDao | |||
import com.ffii.fpsms.enums.RelationColumnType | |||
import com.ffii.fpsms.modules.master.entity.Material | |||
import com.ffii.fpsms.modules.master.entity.MaterialRepository | |||
import com.ffii.fpsms.modules.master.web.models.NewMaterialRequest | |||
import com.ffii.fpsms.modules.master.web.models.NewMaterialResponse | |||
import org.springframework.stereotype.Service | |||
import org.springframework.transaction.annotation.Transactional | |||
import kotlin.jvm.optionals.getOrNull | |||
@Service | |||
open class MaterialService( | |||
private val jdbcDao: JdbcDao, | |||
private val materialRepository: MaterialRepository, | |||
private val uomService: ProductMaterialUomService, | |||
private val typeService: ProductMaterialTypeService, | |||
private val weightUnitService: ProductMaterialWeightUnitService, | |||
): AbstractBaseEntityService<Material, Long, MaterialRepository>(jdbcDao, materialRepository) { | |||
// do mapping with projection | |||
open fun allMaterials(): List<Material> { | |||
// TODO: Replace by actual logic | |||
val materials = materialRepository.findAll() | |||
return materials | |||
} | |||
open fun getMaterial(id: Long): Material? { | |||
return materialRepository.findById(id).getOrNull() | |||
} | |||
@Transactional | |||
open fun saveMaterial(request: NewMaterialRequest): NewMaterialResponse { | |||
val duplicateMaterial = materialRepository.findByCodeAndDeletedIsFalse(request.code) | |||
val material = | |||
if (request.id != null && request.id > 0) materialRepository.findByIdAndDeletedFalse(request.id) | |||
else Material() | |||
if (duplicateMaterial != null && duplicateMaterial.id != request.id) { | |||
return NewMaterialResponse( | |||
id = request.id, | |||
code = request.code, | |||
name = request.name, | |||
message = "The material code has already existed", | |||
errorPosition = "code" | |||
) | |||
} | |||
material.apply { | |||
code = request.code | |||
name = request.name | |||
isConsumables = request.isConsumables | |||
description = request.description | |||
remarks = request.remarks | |||
shelfLife = request.shelfLife | |||
countryOfOrigin = request.countryOfOrigin | |||
minHumid = request.minHumid | |||
maxHumid = request.maxHumid | |||
minTemp = request.minTemp | |||
maxTemp = request.maxTemp | |||
sampleRate = request.sampleRate | |||
passingRate = request.passingRate | |||
netWeight = request.netWeight | |||
} | |||
val savedMaterial = materialRepository.saveAndFlush(material) | |||
val columnName = RelationColumnType.MATERIAL | |||
if (!request.uom.isNullOrEmpty()) uomService.saveUom(savedMaterial.id!!, columnName, request.uom) | |||
if (!request.weightUnit.isNullOrEmpty()) weightUnitService.saveWeightUnit(savedMaterial.id!!, columnName, request.weightUnit) | |||
if (!request.type.isNullOrEmpty()) typeService.saveType(savedMaterial.id!!, columnName, request.type) | |||
return NewMaterialResponse( | |||
id = savedMaterial.id, | |||
name = savedMaterial.name, | |||
code = savedMaterial.code, | |||
message = "Material Save Success", | |||
errorPosition = null, | |||
) | |||
} | |||
} |
@@ -1,48 +0,0 @@ | |||
package com.ffii.fpsms.modules.master.service | |||
import com.ffii.core.support.JdbcDao | |||
import com.ffii.fpsms.enums.RelationColumnType | |||
import com.ffii.fpsms.modules.master.entity.* | |||
import com.ffii.fpsms.modules.master.web.models.MessageResponse | |||
import com.ffii.fpsms.modules.master.web.models.NewTypeRequest | |||
import com.ffii.fpsms.modules.master.web.models.NewWeightUnitRequest | |||
import org.springframework.stereotype.Service | |||
import org.springframework.transaction.annotation.Transactional | |||
@Service | |||
open class ProductMaterialTypeService( | |||
private val jdbcDao: JdbcDao, | |||
private val materialRepository: MaterialRepository, | |||
private val productRepository: ProductRepository, | |||
private val productMaterialTypeRepository: ProductMaterialTypeRepository | |||
) { | |||
@Transactional | |||
open fun saveType(id: Long, columnType: RelationColumnType, typeList: List<NewTypeRequest>): MessageResponse { | |||
var material: Material? = null | |||
var product: Product? = null | |||
when (columnType) { | |||
RelationColumnType.MATERIAL -> { | |||
productMaterialTypeRepository.deleteAllByMaterialId(id) | |||
material = materialRepository.findByIdAndDeletedFalse(id) | |||
} | |||
RelationColumnType.PRODUCT -> { | |||
productMaterialTypeRepository.deleteAllByProductId(id) | |||
product = productRepository.findByIdAndDeletedFalse(id) | |||
} | |||
} | |||
val entries = mutableListOf<ProductMaterialType>() | |||
for (entry in typeList) { | |||
entries += ProductMaterialType().apply { | |||
this.material = material | |||
this.product = product | |||
type = entry.type | |||
} | |||
} | |||
productMaterialTypeRepository.saveAll(entries) | |||
return MessageResponse( | |||
id = id, | |||
message = "Weight unit save success", | |||
errorPosition = null | |||
) | |||
} | |||
} |
@@ -1,48 +0,0 @@ | |||
package com.ffii.fpsms.modules.master.service | |||
import com.ffii.core.support.AbstractIdEntityService | |||
import com.ffii.core.support.JdbcDao | |||
import com.ffii.fpsms.enums.RelationColumnType | |||
import com.ffii.fpsms.modules.master.entity.* | |||
import com.ffii.fpsms.modules.master.web.models.MessageResponse | |||
import com.ffii.fpsms.modules.master.web.models.NewUomRequest | |||
import org.springframework.stereotype.Service | |||
import org.springframework.transaction.annotation.Transactional | |||
@Service | |||
open class ProductMaterialUomService( | |||
private val jdbcDao: JdbcDao, | |||
private val uomRepository: ProductMaterialUomRepository, | |||
private val materialRepository: MaterialRepository, | |||
private val productRepository: ProductRepository, | |||
): AbstractIdEntityService<ProductMaterialUom, Long, ProductMaterialUomRepository>(jdbcDao, uomRepository) { | |||
@Transactional | |||
open fun saveUom(id: Long, columnType: RelationColumnType, uomList: List<NewUomRequest>): MessageResponse { | |||
var material: Material? = null | |||
var product: Product? = null | |||
when (columnType) { | |||
RelationColumnType.MATERIAL -> { | |||
uomRepository.deleteAllByMaterialId(id) | |||
material = materialRepository.findByIdAndDeletedFalse(id) | |||
} | |||
RelationColumnType.PRODUCT -> { | |||
uomRepository.deleteAllByProductId(id) | |||
product = productRepository.findByIdAndDeletedFalse(id) | |||
} | |||
} | |||
val entries = mutableListOf<ProductMaterialUom>() | |||
for (entry in uomList) { | |||
entries += ProductMaterialUom().apply { | |||
this.material = material | |||
this.product = product | |||
uom = entry.uom | |||
} | |||
} | |||
uomRepository.saveAll(entries) | |||
return MessageResponse( | |||
id = id, | |||
message = "Uom save success", | |||
errorPosition = null | |||
) | |||
} | |||
} |
@@ -1,48 +0,0 @@ | |||
package com.ffii.fpsms.modules.master.service | |||
import com.ffii.core.support.JdbcDao | |||
import com.ffii.fpsms.enums.RelationColumnType | |||
import com.ffii.fpsms.modules.master.entity.* | |||
import com.ffii.fpsms.modules.master.web.models.MessageResponse | |||
import com.ffii.fpsms.modules.master.web.models.NewWeightUnitRequest | |||
import org.springframework.stereotype.Service | |||
import org.springframework.transaction.annotation.Transactional | |||
@Service | |||
open class ProductMaterialWeightUnitService( | |||
private val jdbcDao: JdbcDao, | |||
private val weightUnitRepository: ProductMaterialWeightUnitRepository, | |||
private val materialRepository: MaterialRepository, | |||
private val productRepository: ProductRepository, | |||
) { | |||
@Transactional | |||
open fun saveWeightUnit(id: Long, columnType: RelationColumnType, weightUnits: List<NewWeightUnitRequest>): MessageResponse { | |||
var material: Material? = null | |||
var product: Product? = null | |||
when (columnType) { | |||
RelationColumnType.MATERIAL -> { | |||
weightUnitRepository.deleteAllByMaterialId(id) | |||
material = materialRepository.findByIdAndDeletedFalse(id) | |||
} | |||
RelationColumnType.PRODUCT -> { | |||
weightUnitRepository.deleteAllByProductId(id) | |||
product = productRepository.findByIdAndDeletedFalse(id) | |||
} | |||
} | |||
val entries = mutableListOf<ProductMaterialWeightUnit>() | |||
for (entry in weightUnits) { | |||
entries += ProductMaterialWeightUnit().apply { | |||
this.material = material | |||
this.product = product | |||
weightUnit = entry.weightUnit | |||
conversion = entry.conversion | |||
} | |||
} | |||
weightUnitRepository.saveAll(entries) | |||
return MessageResponse( | |||
id = id, | |||
message = "Weight unit save success", | |||
errorPosition = null | |||
) | |||
} | |||
} |
@@ -1,75 +0,0 @@ | |||
package com.ffii.fpsms.modules.master.service | |||
import com.ffii.core.support.AbstractBaseEntityService | |||
import com.ffii.core.support.JdbcDao | |||
import com.ffii.fpsms.enums.RelationColumnType | |||
import com.ffii.fpsms.modules.master.entity.Product | |||
import com.ffii.fpsms.modules.master.entity.ProductRepository | |||
import com.ffii.fpsms.modules.master.web.models.NewProductRequest | |||
import com.ffii.fpsms.modules.master.web.models.NewProductResponse | |||
import org.springframework.stereotype.Service | |||
import org.springframework.transaction.annotation.Transactional | |||
import kotlin.jvm.optionals.getOrNull | |||
@Service | |||
open class ProductService( | |||
private val jdbcDao: JdbcDao, | |||
private val productRepository: ProductRepository, | |||
private val uomService: ProductMaterialUomService, | |||
private val typeService: ProductMaterialTypeService, | |||
private val weightUnitService: ProductMaterialWeightUnitService, | |||
): AbstractBaseEntityService<Product, Long, ProductRepository>(jdbcDao, productRepository) { | |||
// do mapping with projection | |||
open fun allProduct(): List<Product> { | |||
// TODO: Replace by actual logic | |||
val materials = productRepository.findAll() | |||
return materials | |||
} | |||
open fun getProduct(id: Long): Product? { | |||
return productRepository.findById(id).getOrNull() | |||
} | |||
@Transactional | |||
open fun saveProduct(request: NewProductRequest): NewProductResponse { | |||
val duplicateProduct = productRepository.findByCodeAndDeletedIsFalse(request.code) | |||
val product = | |||
if (request.id != null && request.id > 0) productRepository.findByIdAndDeletedFalse(request.id) | |||
else Product() | |||
if (duplicateProduct != null && duplicateProduct.id != request.id) { | |||
return NewProductResponse( | |||
id = request.id, | |||
code = request.code, | |||
name = request.name, | |||
message = "The product code has already existed", | |||
errorPosition = "code" | |||
) | |||
} | |||
product.apply { | |||
code = request.code | |||
name = request.name | |||
description = request.description | |||
remarks = request.remarks | |||
shelfLife = request.shelfLife | |||
countryOfOrigin = request.countryOfOrigin | |||
minHumid = request.minHumid | |||
maxHumid = request.maxHumid | |||
minTemp = request.minTemp | |||
maxTemp = request.maxTemp | |||
sampleRate = request.sampleRate | |||
passingRate = request.passingRate | |||
netWeight = request.netWeight | |||
} | |||
val savedProduct = productRepository.saveAndFlush(product) | |||
val columnName = RelationColumnType.PRODUCT | |||
if (!request.uom.isNullOrEmpty()) uomService.saveUom(savedProduct.id!!, columnName, request.uom) | |||
if (!request.weightUnit.isNullOrEmpty()) weightUnitService.saveWeightUnit(savedProduct.id!!, columnName, request.weightUnit) | |||
if (!request.type.isNullOrEmpty()) typeService.saveType(savedProduct.id!!, columnName, request.type) | |||
return NewProductResponse( | |||
id = savedProduct.id, | |||
name = savedProduct.name, | |||
code = savedProduct.code, | |||
message = "Product Save Success", | |||
errorPosition = null, | |||
) | |||
} | |||
} |
@@ -0,0 +1,28 @@ | |||
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.ItemsService | |||
import com.ffii.fpsms.modules.master.web.models.MessageResponse | |||
import com.ffii.fpsms.modules.master.web.models.NewItemRequest | |||
import jakarta.validation.Valid | |||
import org.springframework.web.bind.annotation.* | |||
@RestController | |||
@RequestMapping("/items") | |||
class ItemsController( | |||
private val materialService: ItemsService | |||
) { | |||
@GetMapping | |||
fun allItems(): List<Items> { | |||
return materialService.allItems() | |||
} | |||
@GetMapping("/details/{id}") | |||
fun getItems(@PathVariable id: Long): Items { | |||
return materialService.getItem(id) ?: throw NotFoundException() | |||
} | |||
@PostMapping("/new") | |||
fun saveItem(@Valid @RequestBody newItem: NewItemRequest): MessageResponse { | |||
return materialService.saveItem(newItem) | |||
} | |||
} |
@@ -1,28 +0,0 @@ | |||
package com.ffii.fpsms.modules.master.web | |||
import com.ffii.core.exception.NotFoundException | |||
import com.ffii.fpsms.modules.master.entity.Material | |||
import com.ffii.fpsms.modules.master.service.MaterialService | |||
import com.ffii.fpsms.modules.master.web.models.NewMaterialRequest | |||
import com.ffii.fpsms.modules.master.web.models.NewMaterialResponse | |||
import jakarta.validation.Valid | |||
import org.springframework.web.bind.annotation.* | |||
@RestController | |||
@RequestMapping("/material") | |||
class MaterialController( | |||
private val materialService: MaterialService | |||
) { | |||
@GetMapping | |||
fun allMaterial(): List<Material> { | |||
return materialService.allMaterials() | |||
} | |||
@GetMapping("/details/{id}") | |||
fun getMaterial(@PathVariable id: Long): Material { | |||
return materialService.getMaterial(id) ?: throw NotFoundException() | |||
} | |||
@PostMapping("/new") | |||
fun saveMaterial(@Valid @RequestBody newMaterial: NewMaterialRequest): NewMaterialResponse { | |||
return materialService.saveMaterial(newMaterial) | |||
} | |||
} |
@@ -1,28 +0,0 @@ | |||
package com.ffii.fpsms.modules.master.web | |||
import com.ffii.core.exception.NotFoundException | |||
import com.ffii.fpsms.modules.master.entity.Product | |||
import com.ffii.fpsms.modules.master.service.ProductService | |||
import com.ffii.fpsms.modules.master.web.models.NewProductRequest | |||
import com.ffii.fpsms.modules.master.web.models.NewProductResponse | |||
import jakarta.validation.Valid | |||
import org.springframework.web.bind.annotation.* | |||
@RestController | |||
@RequestMapping("/product") | |||
class ProductController( | |||
private val productService: ProductService | |||
) { | |||
@GetMapping | |||
fun allProduct(): List<Product> { | |||
return productService.allProduct() | |||
} | |||
@GetMapping("/details/{id}") | |||
fun getProduct(@PathVariable id: Long): Product { | |||
return productService.getProduct(id) ?: throw NotFoundException() | |||
} | |||
@PostMapping("/new") | |||
fun saveProduct(@Valid @RequestBody newProduct: NewProductRequest): NewProductResponse { | |||
return productService.saveProduct(newProduct) | |||
} | |||
} |
@@ -1,9 +0,0 @@ | |||
package com.ffii.fpsms.modules.master.web.models | |||
data class NewMaterialResponse( | |||
val id: Long?, | |||
val name: String?, | |||
val code: String?, | |||
val message: String?, // e.g. duplicated code | |||
val errorPosition: String?, //error field | |||
) |
@@ -2,6 +2,9 @@ package com.ffii.fpsms.modules.master.web.models | |||
data class MessageResponse( | |||
val id: Long?, | |||
val name: String?, | |||
val code: String?, | |||
val type: String?, | |||
val message: String?, | |||
val errorPosition: String?, // e.g. duplicated code | |||
) |
@@ -3,13 +3,13 @@ package com.ffii.fpsms.modules.master.web.models | |||
import jakarta.validation.constraints.NotBlank | |||
import jakarta.validation.constraints.NotNull | |||
data class NewMaterialRequest( | |||
data class NewItemRequest( | |||
@field:NotBlank(message = "material code cannot be empty") | |||
val code: String, | |||
@field:NotBlank(message = "material name cannot be empty") | |||
val name: String, | |||
@field:NotNull(message = "isConsumables cannot be null") | |||
val isConsumables: Boolean, | |||
@field:NotNull(message = "typeId cannot be null") | |||
val typeId: Long, | |||
val id: Long?, | |||
val description: String?, | |||
@@ -23,18 +23,8 @@ data class NewMaterialRequest( | |||
val sampleRate: Double?, | |||
val passingRate: Double?, | |||
val netWeight: Double?, | |||
val type: List<NewTypeRequest>?, | |||
val uom: List<NewUomRequest>?, | |||
val weightUnit: List<NewWeightUnitRequest>?, | |||
// val type: List<NewTypeRequest>?, | |||
// val uom: List<NewUomRequest>?, | |||
// val weightUnit: List<NewWeightUnitRequest>?, | |||
) | |||
data class NewUomRequest( | |||
val uom: String | |||
) | |||
data class NewTypeRequest( | |||
val type: String, | |||
) | |||
data class NewWeightUnitRequest( | |||
val conversion: Double?, | |||
val weightUnit: String, | |||
) |
@@ -1,30 +0,0 @@ | |||
package com.ffii.fpsms.modules.master.web.models | |||
import jakarta.validation.constraints.NotBlank | |||
import jakarta.validation.constraints.NotNull | |||
data class NewProductRequest( | |||
@field:NotBlank(message = "product name cannot be empty") | |||
val code: String, | |||
@field:NotBlank(message = "product name cannot be empty") | |||
val name: String, | |||
@field:NotNull(message = "isConsumables cannot be empty") | |||
val isConsumables: Boolean, | |||
val id: Long?, | |||
val description: String?, | |||
val remarks: String?, | |||
val shelfLife: Double?, | |||
val countryOfOrigin: String?, | |||
val minHumid: Double?, | |||
val maxHumid: Double?, | |||
val minTemp: Double?, | |||
val maxTemp: Double?, | |||
val sampleRate: Double?, | |||
val passingRate: Double?, | |||
val netWeight: Double?, | |||
val type: List<NewTypeRequest>?, | |||
val uom: List<NewUomRequest>?, | |||
val weightUnit: List<NewWeightUnitRequest>?, | |||
) |
@@ -1,9 +0,0 @@ | |||
package com.ffii.fpsms.modules.master.web.models | |||
data class NewProductResponse( | |||
val id: Long?, | |||
val name: String?, | |||
val code: String?, | |||
val message: String?, | |||
val errorPosition: String?, // e.g. duplicated code | |||
) |
@@ -1,77 +0,0 @@ | |||
CREATE TABLE material ( | |||
id INT NOT NULL AUTO_INCREMENT, | |||
version INT NOT NULL DEFAULT '0', | |||
created datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | |||
createdBy VARCHAR(30) NULL, | |||
modified datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | |||
modifiedBy VARCHAR(30) NULL, | |||
deleted TINYINT(1) NOT NULL DEFAULT '0', | |||
`code` VARCHAR(50) NOT NULL, | |||
`name` VARCHAR(50) NOT NULL, | |||
description VARCHAR(100) NULL, | |||
remarks varchar(500) NULL, | |||
isConsumables TINYINT(1) NOT NULL default 0, | |||
shelfLife INT(11) NULL, | |||
countryOfOrigin varchar(50) NULL, | |||
minHumid DECIMAL(16,2) NULL, | |||
maxHumid DECIMAL(16,2) NULL, | |||
minTemp DECIMAL(16,2) NULL, | |||
maxTemp DECIMAL(16,2) NULL, | |||
sampleRate DECIMAL(16,2) NULL, | |||
passingRate DECIMAL(16,2) NULL, | |||
netWeight DECIMAL(16,2) NULL, | |||
CONSTRAINT pk_material PRIMARY KEY (id) | |||
); | |||
CREATE TABLE product ( | |||
id INT NOT NULL AUTO_INCREMENT, | |||
version INT NOT NULL DEFAULT '0', | |||
created datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | |||
createdBy VARCHAR(30) NULL, | |||
modified datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | |||
modifiedBy VARCHAR(30) NULL, | |||
deleted TINYINT(1) NOT NULL DEFAULT '0', | |||
`code` VARCHAR(50) NOT NULL, | |||
`name` VARCHAR(50) NOT NULL, | |||
description VARCHAR(100) NULL, | |||
remarks varchar(500) NULL, | |||
isConsumables TINYINT(1) NOT NULL default 0, | |||
shelfLife INT(11) NULL, | |||
countryOfOrigin varchar(50) NULL, | |||
minHumid DECIMAL(16,2) NULL, | |||
maxHumid DECIMAL(16,2) NULL, | |||
minTemp DECIMAL(16,2) NULL, | |||
maxTemp DECIMAL(16,2) NULL, | |||
sampleRate DECIMAL(16,2) NULL, | |||
passingRate DECIMAL(16,2) NULL, | |||
netWeight DECIMAL(16,2) NULL, | |||
CONSTRAINT pk_product PRIMARY KEY (id) | |||
); | |||
CREATE TABLE product_material_weightUnit ( | |||
productId INT NULL, | |||
materialId INT NULL, | |||
weightUnit VARCHAR(30) NOT NULL, | |||
conversion DECIMAL(16,2) NOT NULL DEFAULT 1 | |||
); | |||
CREATE TABLE product_material_uom ( | |||
productId INT NULL, | |||
materialId INT NULL, | |||
uom VARCHAR(30) NOT NULL | |||
); | |||
CREATE TABLE product_material_type ( | |||
productId INT NULL, | |||
materialId INT NULL, | |||
name VARCHAR(30) NOT NULL | |||
); | |||
ALTER TABLE product_material_weightUnit ADD CONSTRAINT FK_PRODUCT_ON_WEIGHTUNIT FOREIGN KEY (productId) REFERENCES product (id); | |||
ALTER TABLE product_material_weightUnit ADD CONSTRAINT FK_MATERIAL_ON_WEIGHTUNIT FOREIGN KEY (materialId) REFERENCES material (id); | |||
ALTER TABLE product_material_uom ADD CONSTRAINT FK_PRODUCT_ON_UOM FOREIGN KEY (productId) REFERENCES product (id); | |||
ALTER TABLE product_material_uom ADD CONSTRAINT FK_MATERIAL_ON_UOM FOREIGN KEY (materialId) REFERENCES material (id); | |||
ALTER TABLE product_material_type ADD CONSTRAINT FK_PRODUCT_ON_TYPE FOREIGN KEY (productId) REFERENCES product (id); | |||
ALTER TABLE product_material_type ADD CONSTRAINT FK_MATERIAL_ON_TYPE FOREIGN KEY (materialId) REFERENCES material (id); |
@@ -1,10 +0,0 @@ | |||
ALTER TABLE `product_material_type` | |||
ADD COLUMN `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST; | |||
ALTER TABLE `product_material_uom` | |||
ADD COLUMN `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST; | |||
ALTER TABLE `product_material_weightUnit` | |||
ADD COLUMN `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST; |
@@ -1,6 +0,0 @@ | |||
ALTER TABLE `product_material_type` | |||
CHANGE COLUMN `name` `type` VARCHAR(30) NOT NULL; |
@@ -1,9 +0,0 @@ | |||
ALTER TABLE `product` | |||
CHANGE COLUMN `shelfLife` `shelfLife` DECIMAL(14,1) NOT NULL; | |||
ALTER TABLE `material` | |||
CHANGE COLUMN `shelfLife` `shelfLife` DECIMAL(14,1) NOT NULL; |
@@ -1,6 +0,0 @@ | |||
ALTER TABLE `product` | |||
DROP COLUMN `isConsumables`; |
@@ -0,0 +1,54 @@ | |||
--liquibase formatted sql | |||
--changeset derek:master item table | |||
CREATE TABLE item_type ( | |||
id INT NOT NULL AUTO_INCREMENT, | |||
name VARCHAR(50) NOT NULL, | |||
CONSTRAINT pk_item_type PRIMARY KEY (id) | |||
); | |||
INSERT INTO item_type (name) VALUES | |||
('material'), | |||
('product'), | |||
('by-product'), | |||
('consumables'); | |||
CREATE TABLE items ( | |||
id INT NOT NULL AUTO_INCREMENT, | |||
version INT NOT NULL DEFAULT '0', | |||
created datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | |||
createdBy VARCHAR(30) NULL, | |||
modified datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | |||
modifiedBy VARCHAR(30) NULL, | |||
deleted TINYINT(1) NOT NULL DEFAULT '0', | |||
`code` VARCHAR(50) NOT NULL, | |||
`name` VARCHAR(50) NOT NULL, | |||
description VARCHAR(100) NULL, | |||
remarks varchar(500) NULL, | |||
typeId INT(11) NOT NULL, | |||
shelfLife INT(11) NULL, | |||
countryOfOrigin varchar(50) NULL, | |||
minHumid DECIMAL(16,2) NULL, | |||
maxHumid DECIMAL(16,2) NULL, | |||
minTemp DECIMAL(16,2) NULL, | |||
maxTemp DECIMAL(16,2) NULL, | |||
sampleRate DECIMAL(16,2) NULL, | |||
passingRate DECIMAL(16,2) NULL, | |||
netWeight DECIMAL(16,2) NULL, | |||
CONSTRAINT pk_material PRIMARY KEY (id), | |||
CONSTRAINT fk_items FOREIGN KEY (`typeId`) REFERENCES `item_type` (`id`) | |||
); | |||
CREATE TABLE uom_conversion ( | |||
id INT NOT NULL AUTO_INCREMENT, | |||
version INT NOT NULL DEFAULT '0', | |||
created datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | |||
createdBy VARCHAR(30) NULL, | |||
modified datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | |||
modifiedBy VARCHAR(30) NULL, | |||
deleted TINYINT(1) NOT NULL DEFAULT '0', | |||
inQty DECIMAL(16,2) NOT NULL DEFAULT 1, | |||
inUom VARCHAR(50) NOT NULL, | |||
ratio DECIMAL(16,2) NOT NULL, | |||
outQty DECIMAL(16,2) NOT NULL DEFAULT 1, | |||
outUom VARCHAR(50) NOT NULL, | |||
CONSTRAINT pk_uom_conversion PRIMARY KEY (id) | |||
); |