@@ -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<Long>() { | |||
@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<DeliveryOrderLine> = mutableListOf() | |||
} |
@@ -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<Long>() { | |||
@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 | |||
} |
@@ -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<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?, | |||
) |