From d536a01fb19b8ce4d7402f8f6a76f59d402a3099 Mon Sep 17 00:00:00 2001 From: "cyril.tsui" Date: Mon, 16 Jun 2025 13:24:13 +0800 Subject: [PATCH] add delivery order --- .../deliveryOrder/entity/DeliveryOrder.kt | 56 +++++--- .../deliveryOrder/entity/DeliveryOrderLine.kt | 31 +++-- .../entity/DeliveryOrderRepository.kt | 7 + .../entity/models/DeliveryOrderInfo.kt | 23 ++++ .../entity/models/DeliveryOrderLineInfo.kt | 15 +++ .../deliveryOrder/enums/DeliveryOrderEnum.kt | 7 + .../enums/DeliveryOrderEnumConverter.kt | 18 +++ .../service/DeliveryOrderService.kt | 122 ++++++++++++++++++ .../web/controller/DeliveryOrderController.kt | 46 +++++++ .../web/models/SaveDeliveryOrderRequest.kt | 26 ++++ .../web/models/SaveDeliveryOrderResponse.kt | 15 +++ 11 files changed, 337 insertions(+), 29 deletions(-) create mode 100644 src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/models/DeliveryOrderInfo.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/models/DeliveryOrderLineInfo.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/deliveryOrder/enums/DeliveryOrderEnum.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/deliveryOrder/enums/DeliveryOrderEnumConverter.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/controller/DeliveryOrderController.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/SaveDeliveryOrderRequest.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/SaveDeliveryOrderResponse.kt diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DeliveryOrder.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DeliveryOrder.kt index 853b44a..932f410 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DeliveryOrder.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DeliveryOrder.kt @@ -1,48 +1,62 @@ package com.ffii.fpsms.modules.deliveryOrder.entity +import com.fasterxml.jackson.annotation.JsonManagedReference 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.purchaseOrder.entity.PurchaseOrder import com.ffii.fpsms.modules.user.entity.User import jakarta.persistence.* import jakarta.validation.constraints.NotNull import jakarta.validation.constraints.Size -import java.time.Instant +import java.time.LocalDateTime @Entity @Table(name = "delivery_order") open class DeliveryOrder: BaseEntity() { - @ManyToOne - @JoinColumn(name = "purchaseOrderId") - open var purchaseOrder: PurchaseOrder? = null - @Size(max = 100) - @NotNull - @Column(name = "code", nullable = false, length = 100) + @Column(name = "code", length = 100) 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 @JoinColumn(name = "shopId") 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 - @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 @JoinColumn(name = "handlerId", referencedColumnName = "id") 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 = mutableListOf() } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DeliveryOrderLine.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DeliveryOrderLine.kt index 2e55f21..aaf7482 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DeliveryOrderLine.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DeliveryOrderLine.kt @@ -1,6 +1,8 @@ package com.ffii.fpsms.modules.deliveryOrder.entity +import com.fasterxml.jackson.annotation.JsonBackReference 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.UomConversion import com.ffii.fpsms.modules.purchaseOrder.entity.PurchaseOrderLine @@ -12,26 +14,39 @@ import java.math.BigDecimal @Entity @Table(name = "delivery_order_line") open class DeliveryOrderLine: BaseEntity() { - @ManyToOne - @JoinColumn(name = "purchaseOrderLineId") - open var purchaseOrderLine: PurchaseOrderLine? = null @NotNull - @ManyToOne(fetch = FetchType.LAZY, optional = false) + @ManyToOne @JoinColumn(name = "itemId", nullable = false) open var item: Items? = null + @Size(max = 100) @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 - @NotNull - @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "uomId", nullable = false) + @ManyToOne + @JoinColumn(name = "uomId") open var uom: UomConversion? = null + @Column(name = "price", precision = 14, scale = 2) + open var price: BigDecimal? = null + @Size(max = 30) @NotNull @Column(name = "status", nullable = false, length = 30) 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 } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DeliveryOrderRepository.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DeliveryOrderRepository.kt index 93fbfa8..be5ab3e 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DeliveryOrderRepository.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DeliveryOrderRepository.kt @@ -1,8 +1,15 @@ package com.ffii.fpsms.modules.deliveryOrder.entity import com.ffii.core.support.AbstractRepository +import com.ffii.fpsms.modules.deliveryOrder.entity.models.DeliveryOrderInfo import org.springframework.stereotype.Repository +import java.io.Serializable @Repository interface DeliveryOrderRepository : AbstractRepository { + fun findTopByM18DataLogIdAndDeletedIsFalseOrderByModifiedDesc(m18datalogId: Serializable): DeliveryOrder? + + fun findDeliveryOrderInfoByDeletedIsFalse(): List + + fun findByIdAndDeletedIsFalse(id: Serializable): DeliveryOrder? } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/models/DeliveryOrderInfo.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/models/DeliveryOrderInfo.kt new file mode 100644 index 0000000..b0bbc8c --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/models/DeliveryOrderInfo.kt @@ -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 +} + diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/models/DeliveryOrderLineInfo.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/models/DeliveryOrderLineInfo.kt new file mode 100644 index 0000000..4777137 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/models/DeliveryOrderLineInfo.kt @@ -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? +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/enums/DeliveryOrderEnum.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/enums/DeliveryOrderEnum.kt new file mode 100644 index 0000000..7c7f76f --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/enums/DeliveryOrderEnum.kt @@ -0,0 +1,7 @@ +package com.ffii.fpsms.modules.deliveryOrder.enums + +enum class DeliveryOrderStatus(val value: String) { + PENDING("pending"), + RECEIVING("receiving"), + COMPLETED("completed"); +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/enums/DeliveryOrderEnumConverter.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/enums/DeliveryOrderEnumConverter.kt new file mode 100644 index 0000000..8bc971d --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/enums/DeliveryOrderEnumConverter.kt @@ -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{ + 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 } + } + } +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt new file mode 100644 index 0000000..6ade446 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt @@ -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 { + 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 + } +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/controller/DeliveryOrderController.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/controller/DeliveryOrderController.kt new file mode 100644 index 0000000..327f7cd --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/controller/DeliveryOrderController.kt @@ -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 { + 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); + } +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/SaveDeliveryOrderRequest.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/SaveDeliveryOrderRequest.kt new file mode 100644 index 0000000..dd7c666 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/SaveDeliveryOrderRequest.kt @@ -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?, +) \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/SaveDeliveryOrderResponse.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/SaveDeliveryOrderResponse.kt new file mode 100644 index 0000000..706b8be --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/SaveDeliveryOrderResponse.kt @@ -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?, +) \ No newline at end of file