| @@ -1,48 +1,62 @@ | |||||
| package com.ffii.fpsms.modules.deliveryOrder.entity | package com.ffii.fpsms.modules.deliveryOrder.entity | ||||
| import com.fasterxml.jackson.annotation.JsonManagedReference | |||||
| import com.ffii.core.entity.BaseEntity | import com.ffii.core.entity.BaseEntity | ||||
| import com.ffii.fpsms.m18.entity.M18DataLog | |||||
| import com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderStatus | |||||
| import com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderStatusConverter | |||||
| import com.ffii.fpsms.modules.master.entity.Currency | |||||
| import com.ffii.fpsms.modules.master.entity.Shop | import com.ffii.fpsms.modules.master.entity.Shop | ||||
| import com.ffii.fpsms.modules.purchaseOrder.entity.PurchaseOrder | import com.ffii.fpsms.modules.purchaseOrder.entity.PurchaseOrder | ||||
| import com.ffii.fpsms.modules.user.entity.User | import com.ffii.fpsms.modules.user.entity.User | ||||
| import jakarta.persistence.* | import jakarta.persistence.* | ||||
| import jakarta.validation.constraints.NotNull | import jakarta.validation.constraints.NotNull | ||||
| import jakarta.validation.constraints.Size | import jakarta.validation.constraints.Size | ||||
| import java.time.Instant | |||||
| import java.time.LocalDateTime | |||||
| @Entity | @Entity | ||||
| @Table(name = "delivery_order") | @Table(name = "delivery_order") | ||||
| open class DeliveryOrder: BaseEntity<Long>() { | open class DeliveryOrder: BaseEntity<Long>() { | ||||
| @ManyToOne | |||||
| @JoinColumn(name = "purchaseOrderId") | |||||
| open var purchaseOrder: PurchaseOrder? = null | |||||
| @Size(max = 100) | @Size(max = 100) | ||||
| @NotNull | |||||
| @Column(name = "code", nullable = false, length = 100) | |||||
| @Column(name = "code", length = 100) | |||||
| open var code: String? = null | open var code: String? = null | ||||
| @Size(max = 100) | |||||
| @Column(name = "consoCode", length = 100) | |||||
| open var consoCode: String? = null | |||||
| @Size(max = 500) | |||||
| @Column(name = "remarks", length = 500) | |||||
| open var remarks: String? = null | |||||
| @NotNull | |||||
| @Column(name = "targetDate", nullable = false) | |||||
| open var targetDate: Instant? = null | |||||
| @ManyToOne | |||||
| @JoinColumn(name = "supplierId") | |||||
| open var supplier: Shop? = null | |||||
| @ManyToOne | @ManyToOne | ||||
| @JoinColumn(name = "shopId") | @JoinColumn(name = "shopId") | ||||
| open var shop: Shop? = null | open var shop: Shop? = null | ||||
| @Size(max = 30) | |||||
| @ManyToOne | |||||
| @JoinColumn(name = "currencyId") | |||||
| open var currency: Currency? = null | |||||
| @Column(name = "orderDate") | |||||
| open var orderDate: LocalDateTime? = null | |||||
| @Column(name = "estimatedArrivalDate") | |||||
| open var estimatedArrivalDate: LocalDateTime? = null | |||||
| @Column(name = "completeDate") | |||||
| open var completeDate: LocalDateTime? = null | |||||
| @NotNull | @NotNull | ||||
| @Column(name = "status", nullable = false, length = 30) | |||||
| open var status: String? = null | |||||
| @Column(name = "status", nullable = false, length = 10) | |||||
| @Convert(converter = DeliveryOrderStatusConverter::class) | |||||
| open var status: DeliveryOrderStatus? = null | |||||
| @ManyToOne | @ManyToOne | ||||
| @JoinColumn(name = "handlerId", referencedColumnName = "id") | @JoinColumn(name = "handlerId", referencedColumnName = "id") | ||||
| open var handler: User? = null | open var handler: User? = null | ||||
| @NotNull | |||||
| @ManyToOne | |||||
| @JoinColumn(name = "m18DataLogId", nullable = false) | |||||
| open var m18DataLog: M18DataLog? = null | |||||
| @JsonManagedReference | |||||
| @OneToMany(mappedBy = "deliveryOrder", cascade = [CascadeType.ALL], orphanRemoval = true) | |||||
| open var deliveryOrderLines: MutableList<DeliveryOrderLine> = mutableListOf() | |||||
| } | } | ||||
| @@ -1,6 +1,8 @@ | |||||
| package com.ffii.fpsms.modules.deliveryOrder.entity | package com.ffii.fpsms.modules.deliveryOrder.entity | ||||
| import com.fasterxml.jackson.annotation.JsonBackReference | |||||
| import com.ffii.core.entity.BaseEntity | import com.ffii.core.entity.BaseEntity | ||||
| import com.ffii.fpsms.m18.entity.M18DataLog | |||||
| import com.ffii.fpsms.modules.master.entity.Items | import com.ffii.fpsms.modules.master.entity.Items | ||||
| import com.ffii.fpsms.modules.master.entity.UomConversion | import com.ffii.fpsms.modules.master.entity.UomConversion | ||||
| import com.ffii.fpsms.modules.purchaseOrder.entity.PurchaseOrderLine | import com.ffii.fpsms.modules.purchaseOrder.entity.PurchaseOrderLine | ||||
| @@ -12,26 +14,39 @@ import java.math.BigDecimal | |||||
| @Entity | @Entity | ||||
| @Table(name = "delivery_order_line") | @Table(name = "delivery_order_line") | ||||
| open class DeliveryOrderLine: BaseEntity<Long>() { | open class DeliveryOrderLine: BaseEntity<Long>() { | ||||
| @ManyToOne | |||||
| @JoinColumn(name = "purchaseOrderLineId") | |||||
| open var purchaseOrderLine: PurchaseOrderLine? = null | |||||
| @NotNull | @NotNull | ||||
| @ManyToOne(fetch = FetchType.LAZY, optional = false) | |||||
| @ManyToOne | |||||
| @JoinColumn(name = "itemId", nullable = false) | @JoinColumn(name = "itemId", nullable = false) | ||||
| open var item: Items? = null | open var item: Items? = null | ||||
| @Size(max = 100) | |||||
| @NotNull | @NotNull | ||||
| @Column(name = "qty", nullable = false, precision = 14, scale = 2) | |||||
| @Column(name = "itemNo", nullable = false, length = 100) | |||||
| open var itemNo: String? = null | |||||
| @Column(name = "qty", precision = 14, scale = 2) | |||||
| open var qty: BigDecimal? = null | open var qty: BigDecimal? = null | ||||
| @NotNull | |||||
| @ManyToOne(fetch = FetchType.LAZY, optional = false) | |||||
| @JoinColumn(name = "uomId", nullable = false) | |||||
| @ManyToOne | |||||
| @JoinColumn(name = "uomId") | |||||
| open var uom: UomConversion? = null | open var uom: UomConversion? = null | ||||
| @Column(name = "price", precision = 14, scale = 2) | |||||
| open var price: BigDecimal? = null | |||||
| @Size(max = 30) | @Size(max = 30) | ||||
| @NotNull | @NotNull | ||||
| @Column(name = "status", nullable = false, length = 30) | @Column(name = "status", nullable = false, length = 30) | ||||
| open var status: String? = null | open var status: String? = null | ||||
| @NotNull | |||||
| @ManyToOne | |||||
| @JoinColumn(name = "m18DataLogId", nullable = false) | |||||
| open var m18DataLog: M18DataLog? = null | |||||
| @JsonBackReference | |||||
| @ManyToOne | |||||
| @JoinColumn(name = "deliveryOrderId") | |||||
| open var deliveryOrder: DeliveryOrder? = null | |||||
| } | } | ||||
| @@ -1,8 +1,15 @@ | |||||
| package com.ffii.fpsms.modules.deliveryOrder.entity | package com.ffii.fpsms.modules.deliveryOrder.entity | ||||
| import com.ffii.core.support.AbstractRepository | import com.ffii.core.support.AbstractRepository | ||||
| import com.ffii.fpsms.modules.deliveryOrder.entity.models.DeliveryOrderInfo | |||||
| import org.springframework.stereotype.Repository | import org.springframework.stereotype.Repository | ||||
| import java.io.Serializable | |||||
| @Repository | @Repository | ||||
| interface DeliveryOrderRepository : AbstractRepository<DeliveryOrder, Long> { | interface DeliveryOrderRepository : AbstractRepository<DeliveryOrder, Long> { | ||||
| fun findTopByM18DataLogIdAndDeletedIsFalseOrderByModifiedDesc(m18datalogId: Serializable): DeliveryOrder? | |||||
| fun findDeliveryOrderInfoByDeletedIsFalse(): List<DeliveryOrderInfo> | |||||
| fun findByIdAndDeletedIsFalse(id: Serializable): DeliveryOrder? | |||||
| } | } | ||||
| @@ -0,0 +1,23 @@ | |||||
| package com.ffii.fpsms.modules.deliveryOrder.entity.models | |||||
| import com.ffii.fpsms.modules.deliveryOrder.entity.DeliveryOrderLine | |||||
| import com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderStatus | |||||
| import com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderStatusConverter | |||||
| import jakarta.persistence.Convert | |||||
| import org.springframework.beans.factory.annotation.Value | |||||
| import java.time.LocalDateTime | |||||
| interface DeliveryOrderInfo{ | |||||
| val id: Long | |||||
| val code: String | |||||
| val orderDate: LocalDateTime? | |||||
| @get:Value("#{target.status.value}") | |||||
| val status: String? | |||||
| @get:Value("#{target.shop?.name}") | |||||
| val shopName: String? | |||||
| val deliveryOrderLine: List<DeliveryOrderLineInfo> | |||||
| } | |||||
| @@ -0,0 +1,15 @@ | |||||
| package com.ffii.fpsms.modules.deliveryOrder.entity.models | |||||
| import org.springframework.beans.factory.annotation.Value | |||||
| import java.math.BigDecimal | |||||
| interface DeliveryOrderLineInfo { | |||||
| @get:Value("#{target.item?.name}") | |||||
| val itemName: String? | |||||
| val itemNo: String | |||||
| val qty: BigDecimal | |||||
| @get:Value("#{target.uom?.udfudesc}") | |||||
| val uom: String? | |||||
| val price: BigDecimal? | |||||
| val status: String? | |||||
| } | |||||
| @@ -0,0 +1,7 @@ | |||||
| package com.ffii.fpsms.modules.deliveryOrder.enums | |||||
| enum class DeliveryOrderStatus(val value: String) { | |||||
| PENDING("pending"), | |||||
| RECEIVING("receiving"), | |||||
| COMPLETED("completed"); | |||||
| } | |||||
| @@ -0,0 +1,18 @@ | |||||
| package com.ffii.fpsms.modules.deliveryOrder.enums | |||||
| import jakarta.persistence.AttributeConverter | |||||
| import jakarta.persistence.Converter | |||||
| // Delivery Order Status | |||||
| @Converter(autoApply = true) | |||||
| class DeliveryOrderStatusConverter : AttributeConverter<DeliveryOrderStatus, String>{ | |||||
| override fun convertToDatabaseColumn(status: DeliveryOrderStatus?): String? { | |||||
| return status?.value | |||||
| } | |||||
| override fun convertToEntityAttribute(value: String?): DeliveryOrderStatus? { | |||||
| return value?.let { v -> | |||||
| DeliveryOrderStatus.entries.find { it.value == v } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,122 @@ | |||||
| package com.ffii.fpsms.modules.deliveryOrder.service | |||||
| import com.ffii.fpsms.m18.entity.M18DataLogRepository | |||||
| import com.ffii.fpsms.m18.service.M18DataLogService | |||||
| import com.ffii.fpsms.modules.deliveryOrder.entity.DeliveryOrder | |||||
| import com.ffii.fpsms.modules.deliveryOrder.entity.DeliveryOrderRepository | |||||
| import com.ffii.fpsms.modules.deliveryOrder.entity.models.DeliveryOrderInfo | |||||
| import com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderStatus | |||||
| import com.ffii.fpsms.modules.deliveryOrder.web.models.SaveDeliveryOrderRequest | |||||
| import com.ffii.fpsms.modules.deliveryOrder.web.models.SaveDeliveryOrderResponse | |||||
| import com.ffii.fpsms.modules.deliveryOrder.web.models.SaveDeliveryOrderStatusRequest | |||||
| import com.ffii.fpsms.modules.master.service.CurrencyService | |||||
| import com.ffii.fpsms.modules.master.service.ShopService | |||||
| import com.ffii.fpsms.modules.master.web.models.MessageResponse | |||||
| import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderStatus | |||||
| import com.ffii.fpsms.modules.user.entity.UserRepository | |||||
| import com.ffii.fpsms.modules.user.service.UserService | |||||
| import org.springframework.stereotype.Service | |||||
| import org.springframework.transaction.annotation.Transactional | |||||
| import java.io.IOException | |||||
| import kotlin.jvm.optionals.getOrDefault | |||||
| import kotlin.jvm.optionals.getOrNull | |||||
| @Service | |||||
| open class DeliveryOrderService( | |||||
| private val deliveryOrderRepository: DeliveryOrderRepository, | |||||
| private val shopService: ShopService, | |||||
| private val currencyService: CurrencyService, | |||||
| private val m18DataLogService: M18DataLogService, | |||||
| private val m18DataLogRepository: M18DataLogRepository, | |||||
| private val userService: UserService, | |||||
| private val userRepository: UserRepository, | |||||
| ) { | |||||
| open fun findByM18DataLogId(m18DataLogId: Long): DeliveryOrder? { | |||||
| return deliveryOrderRepository.findTopByM18DataLogIdAndDeletedIsFalseOrderByModifiedDesc(m18DataLogId) | |||||
| } | |||||
| open fun getDoList() : List<DeliveryOrderInfo> { | |||||
| return deliveryOrderRepository.findDeliveryOrderInfoByDeletedIsFalse(); | |||||
| } | |||||
| open fun getDetailedDo(id: Long) : DeliveryOrder? { | |||||
| return deliveryOrderRepository.findByIdAndDeletedIsFalse(id); | |||||
| } | |||||
| open fun updateDeliveryOrderStatus(request: SaveDeliveryOrderStatusRequest): SaveDeliveryOrderResponse { | |||||
| val deliveryOrder = checkNotNull( | |||||
| request.id?.let { deliveryOrderRepository.findById(it).getOrNull() } | |||||
| ) { "ID must be set" } | |||||
| val status = checkNotNull( | |||||
| request.status?.let { status -> DeliveryOrderStatus.entries.find { it.value == status } } | |||||
| ) { "Status must be set" } | |||||
| deliveryOrder.apply { | |||||
| this.status = status | |||||
| } | |||||
| val savedDeliveryOrder = deliveryOrderRepository.save(deliveryOrder).let { | |||||
| SaveDeliveryOrderResponse( | |||||
| id = it.id, | |||||
| code = it.code, | |||||
| supplierCode = it.supplier?.code, | |||||
| shopCode = it.shop?.code, | |||||
| currencyCode = it.currency?.code, | |||||
| orderDate = it.orderDate, | |||||
| estimatedArrivalDate = it.estimatedArrivalDate, | |||||
| completeDate = it.completeDate, | |||||
| status = it.status?.value | |||||
| ) | |||||
| } | |||||
| return savedDeliveryOrder | |||||
| } | |||||
| @Throws(IOException::class) | |||||
| @Transactional | |||||
| open fun saveDeliveryOrder(request: SaveDeliveryOrderRequest): SaveDeliveryOrderResponse { | |||||
| val deliveryOrder = | |||||
| request.id?.let { deliveryOrderRepository.findById(it).getOrDefault(DeliveryOrder()) } ?: DeliveryOrder() | |||||
| val supplier = request.m18SupplierId?.let { shopService.findVendorByM18Id(it) } | |||||
| ?: request.supplierId?.let { shopService.findById(it) } | |||||
| val shop = request.m18ShopId?.let { shopService.findShopByM18Id(it) } | |||||
| ?: request.shopId?.let { shopService.findById(it) } | |||||
| val currency = request.m18CurrencyId?.let { currencyService.findByM18Id(it) } | |||||
| ?: request.currencyId?.let { currencyService.findById(it) } | |||||
| val status = request.status?.let { status -> DeliveryOrderStatus.entries.find { it.value == status } } | |||||
| val m18DataLog = request.m18DataLogId?.let { m18DataLogRepository.findById(it).getOrNull() } | |||||
| val handler = request.handlerId?.let { userRepository.findById(it).getOrNull() } | |||||
| //Need check duplicate? | |||||
| deliveryOrder.apply { | |||||
| code = request.code | |||||
| this.supplier = supplier | |||||
| this.shop = shop | |||||
| this.currency = currency | |||||
| orderDate = request.orderDate | |||||
| estimatedArrivalDate = request.estimatedArrivalDate | |||||
| completeDate = request.completeDate | |||||
| this.status = status | |||||
| this.m18DataLog = m18DataLog | |||||
| this.handler = handler | |||||
| } | |||||
| val savedDeliveryOrder = deliveryOrderRepository.saveAndFlush(deliveryOrder).let { | |||||
| SaveDeliveryOrderResponse( | |||||
| id = it.id, | |||||
| code = it.code, | |||||
| supplierCode = it.supplier?.code, | |||||
| shopCode = it.shop?.code, | |||||
| currencyCode = it.currency?.code, | |||||
| orderDate = it.orderDate, | |||||
| estimatedArrivalDate = it.estimatedArrivalDate, | |||||
| completeDate = it.completeDate, | |||||
| status = it.status?.value | |||||
| ) | |||||
| } | |||||
| return savedDeliveryOrder | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,46 @@ | |||||
| package com.ffii.fpsms.modules.deliveryOrder.web.controller | |||||
| import com.ffii.fpsms.modules.deliveryOrder.entity.DeliveryOrder | |||||
| import com.ffii.fpsms.modules.deliveryOrder.entity.models.DeliveryOrderInfo | |||||
| import com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderStatus | |||||
| import com.ffii.fpsms.modules.deliveryOrder.service.DeliveryOrderService | |||||
| import com.ffii.fpsms.modules.deliveryOrder.web.models.SaveDeliveryOrderRequest | |||||
| import com.ffii.fpsms.modules.deliveryOrder.web.models.SaveDeliveryOrderResponse | |||||
| import com.ffii.fpsms.modules.deliveryOrder.web.models.SaveDeliveryOrderStatusRequest | |||||
| import org.springframework.web.bind.annotation.GetMapping | |||||
| import org.springframework.web.bind.annotation.PathVariable | |||||
| import org.springframework.web.bind.annotation.PostMapping | |||||
| import org.springframework.web.bind.annotation.RequestBody | |||||
| import org.springframework.web.bind.annotation.RequestMapping | |||||
| import org.springframework.web.bind.annotation.RequestParam | |||||
| import org.springframework.web.bind.annotation.RestController | |||||
| @RequestMapping("/do") | |||||
| @RestController | |||||
| class DeliveryOrderController( | |||||
| private val deliveryOrderService: DeliveryOrderService, | |||||
| ) { | |||||
| @GetMapping("/list") | |||||
| fun getDoList(): List<DeliveryOrderInfo> { | |||||
| return deliveryOrderService.getDoList(); | |||||
| } | |||||
| @GetMapping("/detail/{id}") | |||||
| fun getDetailedDo(@PathVariable id: Long): DeliveryOrder? { | |||||
| return deliveryOrderService.getDetailedDo(id); | |||||
| } | |||||
| @PostMapping("/update-status") | |||||
| fun updateDoStatus(@RequestBody request: SaveDeliveryOrderStatusRequest): SaveDeliveryOrderResponse { | |||||
| return deliveryOrderService.updateDeliveryOrderStatus(request); | |||||
| } | |||||
| @PostMapping("/start") | |||||
| fun startDo(@RequestBody id: Long): SaveDeliveryOrderResponse { | |||||
| val request = SaveDeliveryOrderStatusRequest( | |||||
| id = id, | |||||
| status = DeliveryOrderStatus.RECEIVING.value | |||||
| ) | |||||
| return deliveryOrderService.updateDeliveryOrderStatus(request); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,26 @@ | |||||
| package com.ffii.fpsms.modules.deliveryOrder.web.models | |||||
| import java.time.LocalDateTime | |||||
| data class SaveDeliveryOrderRequest( | |||||
| val id: Long?, | |||||
| val code: String?, | |||||
| val supplierId: Long? = null, | |||||
| val m18SupplierId: Long? = null, | |||||
| val shopId: Long? = null, | |||||
| val m18ShopId: Long? = null, | |||||
| val currencyId: Long? = null, | |||||
| val m18CurrencyId: Long? = null, | |||||
| val orderDate: LocalDateTime?, | |||||
| val estimatedArrivalDate: LocalDateTime?, | |||||
| val completeDate: LocalDateTime?, | |||||
| val status: String?, | |||||
| val type: String?, | |||||
| val m18DataLogId: Long?, | |||||
| val handlerId: Long? | |||||
| ) | |||||
| data class SaveDeliveryOrderStatusRequest( | |||||
| val id: Long?, | |||||
| val status: String?, | |||||
| ) | |||||
| @@ -0,0 +1,15 @@ | |||||
| package com.ffii.fpsms.modules.deliveryOrder.web.models | |||||
| import java.time.LocalDateTime | |||||
| data class SaveDeliveryOrderResponse( | |||||
| val id: Long?, | |||||
| val code: String?, | |||||
| val supplierCode: String?, | |||||
| val shopCode: String?, | |||||
| val currencyCode: String?, | |||||
| val orderDate: LocalDateTime?, | |||||
| val estimatedArrivalDate: LocalDateTime?, | |||||
| val completeDate: LocalDateTime?, | |||||
| val status: String?, | |||||
| ) | |||||