| @@ -1,7 +1,7 @@ | |||
| package com.ffii.fpsms.modules.deliveryOrder.entity | |||
| import com.ffii.core.support.AbstractRepository | |||
| import com.ffii.fpsms.modules.deliveryOrder.entity.models.DeliveryOrderInfo | |||
| import com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderStatus | |||
| import org.springframework.data.jpa.repository.JpaRepository | |||
| import org.springframework.data.jpa.repository.Query | |||
| @@ -11,7 +11,8 @@ import org.springframework.data.domain.Pageable | |||
| import org.springframework.stereotype.Repository | |||
| import java.io.Serializable | |||
| import java.time.LocalDateTime | |||
| import com.ffii.fpsms.modules.deliveryOrder.web.models.* | |||
| import com.ffii.fpsms.modules.deliveryOrder.entity.models.* | |||
| @Repository | |||
| interface DeliveryOrderRepository : AbstractRepository<DeliveryOrder, Long> { | |||
| @Query(""" | |||
| @@ -77,4 +78,44 @@ interface DeliveryOrderRepository : AbstractRepository<DeliveryOrder, Long> { | |||
| fun findAllByCodeContainsAndShopNameContainsAndStatusAndDeletedIsFalse(code: String?, shopName: String?, staus: DeliveryOrderStatus?) : List<DeliveryOrderInfo>; | |||
| fun findDeliveryOrderInfoByCodeContainsAndShopNameContainsAndDeletedIsFalseOrderByIdDesc(code: String, shopName: String, pageable: Pageable): Page<DeliveryOrderInfo> | |||
| @Query(""" | |||
| select d from DeliveryOrder d | |||
| where d.deleted = false | |||
| and (:code is null or d.code like concat('%', :code, '%')) | |||
| and (:shopName is null or d.shop.name like concat('%', :shopName, '%')) | |||
| and (:status is null or d.status = :status) | |||
| and (:estimatedArrivalDate is null or DATE(d.estimatedArrivalDate) = DATE(:estimatedArrivalDate)) | |||
| order by d.id desc | |||
| """) | |||
| fun searchDoLite( | |||
| @Param("code") code: String?, | |||
| @Param("shopName") shopName: String?, | |||
| @Param("status") status: String?, | |||
| @Param("estimatedArrivalDate") estimatedArrivalDate: LocalDateTime?, | |||
| pageable: Pageable | |||
| ): Page<DeliveryOrderInfoLite> | |||
| @Query(""" | |||
| select d from DeliveryOrder d | |||
| where d.deleted = false | |||
| and (:code is null or d.code like concat('%', :code, '%')) | |||
| and (:shopName is null or d.shop.name like concat('%', :shopName, '%')) | |||
| and (:status is null or d.status = :status) | |||
| and (:etaStart is null or d.estimatedArrivalDate >= :etaStart) | |||
| and (:etaEnd is null or d.estimatedArrivalDate < :etaEnd) | |||
| order by d.id desc | |||
| """) | |||
| fun searchDoLitePage( | |||
| @Param("code") code: String?, | |||
| @Param("shopName") shopName: String?, | |||
| @Param("status") status: DeliveryOrderStatus?, // 直接用枚举最稳 | |||
| @Param("etaStart") etaStart: LocalDateTime?, | |||
| @Param("etaEnd") etaEnd: LocalDateTime?, | |||
| pageable: Pageable | |||
| ): Page<DeliveryOrderInfo> | |||
| } | |||
| @@ -29,3 +29,31 @@ interface DeliveryOrderInfo{ | |||
| val deliveryOrderLines: List<DeliveryOrderLineInfo> | |||
| } | |||
| interface DeliveryOrderInfoLite { | |||
| val id: Long | |||
| val code: String | |||
| val orderDate: LocalDateTime? | |||
| val estimatedArrivalDate: LocalDateTime? | |||
| @get:Value("#{target.status.value}") | |||
| val status: String? | |||
| @get:Value("#{target.shop?.name}") | |||
| val shopName: String? | |||
| @get:Value("#{target.supplier?.name}") | |||
| val supplierName: String? | |||
| @get:Value("#{target.shop?.addr3}") | |||
| val shopAddress: String? | |||
| } | |||
| data class DeliveryOrderInfoLiteDto( | |||
| val id: Long, | |||
| val code: String, | |||
| val orderDate: LocalDateTime?, | |||
| val estimatedArrivalDate: LocalDateTime?, | |||
| val status: String?, | |||
| val shopName: String?, | |||
| val supplierName: String?, | |||
| val shopAddress: String? | |||
| ) | |||
| @@ -72,7 +72,12 @@ import com.ffii.fpsms.modules.stock.service.SuggestedPickLotService // 添加 | |||
| import com.ffii.fpsms.modules.deliveryOrder.web.models.* | |||
| import com.ffii.fpsms.modules.pickOrder.entity.PickExecutionIssueRepository // 添加 | |||
| import com.ffii.core.utils.CanonPrinterUtil | |||
| import com.ffii.core.response.RecordsRes | |||
| import org.springframework.data.domain.PageRequest | |||
| import org.springframework.data.domain.Page | |||
| import org.springframework.data.domain.Pageable | |||
| import com.ffii.fpsms.modules.deliveryOrder.entity.models.DeliveryOrderInfoLite | |||
| import com.ffii.fpsms.modules.deliveryOrder.entity.models.DeliveryOrderInfoLiteDto | |||
| @Service | |||
| open class DeliveryOrderService( | |||
| private val deliveryOrderRepository: DeliveryOrderRepository, | |||
| @@ -103,7 +108,51 @@ open class DeliveryOrderService( | |||
| private val doPickOrderLineRepository: DoPickOrderLineRepository, | |||
| private val doPickOrderLineRecordRepository: DoPickOrderLineRecordRepository | |||
| ) { | |||
| open fun searchDoLiteByPage( | |||
| code: String?, | |||
| shopName: String?, | |||
| status: String?, | |||
| estimatedArrivalDate: LocalDateTime?, | |||
| pageNum: Int?, | |||
| pageSize: Int? | |||
| ): RecordsRes<DeliveryOrderInfoLiteDto> { | |||
| val page = (pageNum ?: 1) - 1 // 如果你前端是 1-based;如果前端本来就是 0-based 就不要 -1 | |||
| val size = pageSize ?: 10 | |||
| val pageable = PageRequest.of(page.coerceAtLeast(0), size) | |||
| val statusEnum = status?.let { s -> DeliveryOrderStatus.entries.find { it.value == s } } | |||
| val etaStart = estimatedArrivalDate | |||
| val etaEnd = estimatedArrivalDate?.plusDays(1) | |||
| val result = deliveryOrderRepository.searchDoLitePage( | |||
| code = code?.ifBlank { null }, | |||
| shopName = shopName?.ifBlank { null }, | |||
| status = statusEnum, | |||
| etaStart = etaStart, | |||
| etaEnd = etaEnd, | |||
| pageable = pageable | |||
| ) | |||
| val records = result.content.map { | |||
| DeliveryOrderInfoLiteDto( | |||
| id = it.id, | |||
| code = it.code, | |||
| orderDate = it.orderDate, | |||
| estimatedArrivalDate = it.estimatedArrivalDate, | |||
| status = it.status, | |||
| shopName = it.shopName, | |||
| supplierName = it.supplierName, | |||
| shopAddress = it.shopAddress | |||
| ) | |||
| } | |||
| return RecordsRes(records, result.totalElements.toInt()) | |||
| } | |||
| open fun findByM18DataLogId(m18DataLogId: Long): DeliveryOrder? { | |||
| return deliveryOrderRepository.findTopByM18DataLogIdAndDeletedIsFalseOrderByModifiedDesc(m18DataLogId) | |||
| } | |||
| @@ -221,7 +270,43 @@ open class DeliveryOrderService( | |||
| orderEndDate | |||
| ); | |||
| } | |||
| /* | |||
| open fun searchDoForList( | |||
| code: String?, | |||
| shopName: String?, | |||
| status: String?, // 前端传过来的字符串(pending/receiving/completed 或空) | |||
| orderFrom: LocalDateTime?, | |||
| orderTo: LocalDateTime?, | |||
| etaFrom: LocalDateTime?, | |||
| etaTo: LocalDateTime?, | |||
| ): Page<DoSearchRow> { | |||
| val page = deliveryOrderRepository.search( | |||
| code = if (code.isNullOrBlank()) null else code, | |||
| shopName = if (shopName.isNullOrBlank()) null else shopName, | |||
| status = if (status.isNullOrBlank()) null else status, | |||
| orderFrom = orderFrom, | |||
| orderTo = orderTo, | |||
| etaFrom = etaFrom, | |||
| etaTo = etaTo, | |||
| pageable = pageable | |||
| ) | |||
| return page.map { d -> | |||
| DoSearchRow( | |||
| id = d.id!!, | |||
| code = d.code, | |||
| shopName = d.shop?.name, | |||
| supplierName = d.supplier?.name, | |||
| orderDate = d.orderDate, | |||
| estimatedArrivalDate = d.estimatedArrivalDate, | |||
| status = d.status?.value, | |||
| deliveryOrderLineCount = d.deliveryOrderLines.size // 只要数量 | |||
| ) | |||
| } | |||
| } | |||
| */ | |||
| open fun searchWithoutEstArrDateAndStatus( | |||
| code: String?, | |||
| shopName: String?, | |||
| @@ -79,15 +79,15 @@ open class DoPickOrderService( | |||
| code = request.code ?: "", | |||
| shopName = request.shopName ?: "", | |||
| pageable = pageable | |||
| ) | |||
| val estArrStartDate = request.estArrStartDate | |||
| val estArrEndDate = request.estArrEndDate | |||
| ) | |||
| val estimatedArrivalDate = request.estimatedArrivalDate | |||
| val status = request.status | |||
| val records = response.content | |||
| .filter { | |||
| (estArrStartDate == null || (it.estimatedArrivalDate != null && (estArrStartDate.isEqual(it.estimatedArrivalDate) || estArrStartDate.isBefore(it.estimatedArrivalDate)))) && | |||
| (estArrEndDate == null || (it.estimatedArrivalDate != null && (estArrEndDate.isEqual(it.estimatedArrivalDate) || estArrEndDate.isAfter(it.estimatedArrivalDate)))) && | |||
| (status == null || it.status == status) | |||
| // 如果提供了 estimatedArrivalDate,只匹配同一天的记录 | |||
| (estimatedArrivalDate == null || (it.estimatedArrivalDate != null && | |||
| it.estimatedArrivalDate!!.toLocalDate() == estimatedArrivalDate.toLocalDate())) && | |||
| (status == null || it.status == status) | |||
| } | |||
| val total = response.totalElements | |||
| return RecordsRes<DeliveryOrderInfo>(records, total.toInt()); | |||
| @@ -39,14 +39,33 @@ import com.ffii.core.response.RecordsRes | |||
| import com.ffii.fpsms.modules.deliveryOrder.web.models.PrintQrCodeForDoRequest | |||
| import com.ffii.fpsms.modules.stock.service.StockInLineService | |||
| import com.ffii.fpsms.modules.deliveryOrder.web.models.Check4FTruckBatchResponse | |||
| import com.ffii.fpsms.modules.deliveryOrder.web.models.DoSearchRowResponse | |||
| import com.ffii.fpsms.modules.deliveryOrder.entity.models.DeliveryOrderInfoLite | |||
| import com.ffii.fpsms.modules.deliveryOrder.entity.models.DeliveryOrderInfoLiteDto | |||
| @RequestMapping("/do") | |||
| @RestController | |||
| class DeliveryOrderController( | |||
| private val deliveryOrderService: DeliveryOrderService, | |||
| private val stockInLineService: StockInLineService, | |||
| private val doPickOrderService: DoPickOrderService | |||
| private val doPickOrderService: DoPickOrderService, | |||
| ) { | |||
| @PostMapping("/search-do-lite") | |||
| fun searchDoLite(@RequestBody request: SearchDeliveryOrderInfoRequest): RecordsRes<DeliveryOrderInfoLiteDto> { // 改为 DeliveryOrderInfoLiteDto | |||
| println("DEBUG: searchDoLite - request: code=${request.code}, shopName=${request.shopName}, status=${request.status}") | |||
| println("DEBUG: searchDoLite - estimatedArrivalDate=${request.estimatedArrivalDate}") | |||
| println("DEBUG: searchDoLite - pagination: pageNum=${request.pageNum}, pageSize=${request.pageSize}") | |||
| return deliveryOrderService.searchDoLiteByPage( | |||
| code = request.code, | |||
| shopName = request.shopName, | |||
| status = request.status, | |||
| estimatedArrivalDate = request.estimatedArrivalDate, | |||
| pageNum = request.pageNum, | |||
| pageSize = request.pageSize | |||
| ) | |||
| } | |||
| @GetMapping("/list") | |||
| fun getDoList(): List<DeliveryOrderInfo> { | |||
| return deliveryOrderService.getDoList(); | |||
| @@ -171,7 +190,6 @@ class DeliveryOrderController( | |||
| } | |||
| @PostMapping("/update-status") | |||
| fun updateDoStatus(@RequestBody request: SaveDeliveryOrderStatusRequest): SaveDeliveryOrderResponse { | |||
| return deliveryOrderService.updateDeliveryOrderStatus(request); | |||
| @@ -57,4 +57,36 @@ data class DoPickOrderSummaryItem( | |||
| val truckDepartureTime: java.time.LocalTime?, | |||
| val truckLanceCode: String?, | |||
| val handledBy: Long? | |||
| ) | |||
| ) | |||
| data class DoSearchRow( | |||
| val id: Long, | |||
| val code: String?, | |||
| val shopName: String?, | |||
| val status: String, | |||
| val orderDate: LocalDateTime, | |||
| val estimatedArrivalDate: LocalDateTime, | |||
| val completeDate: LocalDateTime, | |||
| val supplierName: String, | |||
| val shopCode: String, | |||
| val supplierCode: String, | |||
| ) | |||
| data class DoSearchRowResponse( | |||
| val id: Long, | |||
| val code: String, | |||
| val shopName: String?, | |||
| val supplierName: String?, | |||
| val orderDate: LocalDateTime?, | |||
| val estimatedArrivalDate: LocalDateTime?, | |||
| val status: String?, | |||
| val deliveryOrderLineCount: Int | |||
| ) | |||
| interface DoSearchRowProjection { | |||
| val id: Long | |||
| val code: String | |||
| val shopName: String? | |||
| val supplierName: String? | |||
| val orderDate: LocalDateTime? | |||
| val estimatedArrivalDate: LocalDateTime? | |||
| val status: String? | |||
| val deliveryOrderLineCount: Long | |||
| } | |||
| @@ -25,10 +25,7 @@ data class SearchDeliveryOrderInfoRequest( | |||
| val code: String?, | |||
| val shopName: String?, | |||
| val status: String?, | |||
| val orderStartDate: LocalDateTime?, | |||
| val orderEndDate: LocalDateTime?, | |||
| val estArrStartDate: LocalDateTime?, | |||
| val estArrEndDate: LocalDateTime?, | |||
| val estimatedArrivalDate: LocalDateTime?, | |||
| val pageSize: Int?, | |||
| val pageNum: Int?, | |||
| ) | |||