| @@ -1,7 +1,7 @@ | |||||
| 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 com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderStatus | import com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderStatus | ||||
| import org.springframework.data.jpa.repository.JpaRepository | import org.springframework.data.jpa.repository.JpaRepository | ||||
| import org.springframework.data.jpa.repository.Query | import org.springframework.data.jpa.repository.Query | ||||
| @@ -11,7 +11,8 @@ import org.springframework.data.domain.Pageable | |||||
| import org.springframework.stereotype.Repository | import org.springframework.stereotype.Repository | ||||
| import java.io.Serializable | import java.io.Serializable | ||||
| import java.time.LocalDateTime | import java.time.LocalDateTime | ||||
| import com.ffii.fpsms.modules.deliveryOrder.web.models.* | |||||
| import com.ffii.fpsms.modules.deliveryOrder.entity.models.* | |||||
| @Repository | @Repository | ||||
| interface DeliveryOrderRepository : AbstractRepository<DeliveryOrder, Long> { | interface DeliveryOrderRepository : AbstractRepository<DeliveryOrder, Long> { | ||||
| @Query(""" | @Query(""" | ||||
| @@ -77,4 +78,44 @@ interface DeliveryOrderRepository : AbstractRepository<DeliveryOrder, Long> { | |||||
| fun findAllByCodeContainsAndShopNameContainsAndStatusAndDeletedIsFalse(code: String?, shopName: String?, staus: DeliveryOrderStatus?) : List<DeliveryOrderInfo>; | fun findAllByCodeContainsAndShopNameContainsAndStatusAndDeletedIsFalse(code: String?, shopName: String?, staus: DeliveryOrderStatus?) : List<DeliveryOrderInfo>; | ||||
| fun findDeliveryOrderInfoByCodeContainsAndShopNameContainsAndDeletedIsFalseOrderByIdDesc(code: String, shopName: String, pageable: Pageable): Page<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> | 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.deliveryOrder.web.models.* | ||||
| import com.ffii.fpsms.modules.pickOrder.entity.PickExecutionIssueRepository // 添加 | import com.ffii.fpsms.modules.pickOrder.entity.PickExecutionIssueRepository // 添加 | ||||
| import com.ffii.core.utils.CanonPrinterUtil | 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 | @Service | ||||
| open class DeliveryOrderService( | open class DeliveryOrderService( | ||||
| private val deliveryOrderRepository: DeliveryOrderRepository, | private val deliveryOrderRepository: DeliveryOrderRepository, | ||||
| @@ -103,7 +108,51 @@ open class DeliveryOrderService( | |||||
| private val doPickOrderLineRepository: DoPickOrderLineRepository, | private val doPickOrderLineRepository: DoPickOrderLineRepository, | ||||
| private val doPickOrderLineRecordRepository: DoPickOrderLineRecordRepository | 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? { | open fun findByM18DataLogId(m18DataLogId: Long): DeliveryOrder? { | ||||
| return deliveryOrderRepository.findTopByM18DataLogIdAndDeletedIsFalseOrderByModifiedDesc(m18DataLogId) | return deliveryOrderRepository.findTopByM18DataLogIdAndDeletedIsFalseOrderByModifiedDesc(m18DataLogId) | ||||
| } | } | ||||
| @@ -221,7 +270,43 @@ open class DeliveryOrderService( | |||||
| orderEndDate | 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( | open fun searchWithoutEstArrDateAndStatus( | ||||
| code: String?, | code: String?, | ||||
| shopName: String?, | shopName: String?, | ||||
| @@ -79,15 +79,15 @@ open class DoPickOrderService( | |||||
| code = request.code ?: "", | code = request.code ?: "", | ||||
| shopName = request.shopName ?: "", | shopName = request.shopName ?: "", | ||||
| pageable = pageable | pageable = pageable | ||||
| ) | |||||
| val estArrStartDate = request.estArrStartDate | |||||
| val estArrEndDate = request.estArrEndDate | |||||
| ) | |||||
| val estimatedArrivalDate = request.estimatedArrivalDate | |||||
| val status = request.status | val status = request.status | ||||
| val records = response.content | val records = response.content | ||||
| .filter { | .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 | val total = response.totalElements | ||||
| return RecordsRes<DeliveryOrderInfo>(records, total.toInt()); | 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.deliveryOrder.web.models.PrintQrCodeForDoRequest | ||||
| import com.ffii.fpsms.modules.stock.service.StockInLineService | 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.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") | @RequestMapping("/do") | ||||
| @RestController | @RestController | ||||
| class DeliveryOrderController( | class DeliveryOrderController( | ||||
| private val deliveryOrderService: DeliveryOrderService, | private val deliveryOrderService: DeliveryOrderService, | ||||
| private val stockInLineService: StockInLineService, | 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") | @GetMapping("/list") | ||||
| fun getDoList(): List<DeliveryOrderInfo> { | fun getDoList(): List<DeliveryOrderInfo> { | ||||
| return deliveryOrderService.getDoList(); | return deliveryOrderService.getDoList(); | ||||
| @@ -171,7 +190,6 @@ class DeliveryOrderController( | |||||
| } | } | ||||
| @PostMapping("/update-status") | @PostMapping("/update-status") | ||||
| fun updateDoStatus(@RequestBody request: SaveDeliveryOrderStatusRequest): SaveDeliveryOrderResponse { | fun updateDoStatus(@RequestBody request: SaveDeliveryOrderStatusRequest): SaveDeliveryOrderResponse { | ||||
| return deliveryOrderService.updateDeliveryOrderStatus(request); | return deliveryOrderService.updateDeliveryOrderStatus(request); | ||||
| @@ -57,4 +57,36 @@ data class DoPickOrderSummaryItem( | |||||
| val truckDepartureTime: java.time.LocalTime?, | val truckDepartureTime: java.time.LocalTime?, | ||||
| val truckLanceCode: String?, | val truckLanceCode: String?, | ||||
| val handledBy: Long? | 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 code: String?, | ||||
| val shopName: String?, | val shopName: String?, | ||||
| val status: String?, | val status: String?, | ||||
| val orderStartDate: LocalDateTime?, | |||||
| val orderEndDate: LocalDateTime?, | |||||
| val estArrStartDate: LocalDateTime?, | |||||
| val estArrEndDate: LocalDateTime?, | |||||
| val estimatedArrivalDate: LocalDateTime?, | |||||
| val pageSize: Int?, | val pageSize: Int?, | ||||
| val pageNum: Int?, | val pageNum: Int?, | ||||
| ) | ) | ||||