Pārlūkot izejas kodu

Supporting Function FG Pick Status Dashboard

master
Tommy\2Fi-Staff pirms 3 nedēļām
vecāks
revīzija
2a76180057
2 mainītis faili ar 201 papildinājumiem un 0 dzēšanām
  1. +180
    -0
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderService.kt
  2. +21
    -0
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/TruckScheduleDashboardResponse.kt

+ 180
- 0
src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderService.kt Parādīt failu

@@ -48,9 +48,11 @@ import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderLineRecord
import org.springframework.context.annotation.Lazy
import com.ffii.fpsms.modules.pickOrder.entity.PickOrderLineRepository
import com.ffii.fpsms.modules.deliveryOrder.web.models.TicketReleaseTableResponse
import com.ffii.fpsms.modules.deliveryOrder.web.models.TruckScheduleDashboardResponse
import com.ffii.fpsms.modules.deliveryOrder.web.models.SearchDeliveryOrderInfoRequest
import com.ffii.core.response.RecordsRes
import org.springframework.data.domain.PageRequest
import java.time.temporal.ChronoUnit
@Service
open class DoPickOrderService(
private val doPickOrderRepository: DoPickOrderRepository,
@@ -748,5 +750,183 @@ open class DoPickOrderService(
return allPickOrderLines.size
}

/**
* Get truck schedule dashboard data aggregated by store, truck lane, and departure time.
* Groups DoPickOrder and DoPickOrderRecord data to provide summary statistics.
*/
open fun getTruckScheduleDashboard(): List<TruckScheduleDashboardResponse> {
val today = LocalDate.now()
// Fetch all active DoPickOrders for today
val doPickOrders = doPickOrderRepository.findByStoreIdAndRequiredDeliveryDateAndTicketStatusIn(
"2/F", today, listOf(DoPickOrderStatus.pending, DoPickOrderStatus.released, DoPickOrderStatus.completed)
) + doPickOrderRepository.findByStoreIdAndRequiredDeliveryDateAndTicketStatusIn(
"4/F", today, listOf(DoPickOrderStatus.pending, DoPickOrderStatus.released, DoPickOrderStatus.completed)
)
// Fetch all DoPickOrderRecords for today (completed records)
val doPickOrderRecords = doPickOrderRecordRepository.findByStoreIdAndRequiredDeliveryDateAndTicketStatusIn(
"2/F", today, listOf(DoPickOrderStatus.completed)
) + doPickOrderRecordRepository.findByStoreIdAndRequiredDeliveryDateAndTicketStatusIn(
"4/F", today, listOf(DoPickOrderStatus.completed)
)
// Combine both types into a unified data structure for aggregation
data class TicketData(
val storeId: String?,
val truckId: Long?,
val truckLanceCode: String?,
val truckDepartureTime: java.time.LocalTime?,
val shopId: Long?,
val shopCode: String?,
val ticketNo: String?,
val ticketReleaseTime: LocalDateTime?,
val ticketCompleteDateTime: LocalDateTime?,
val ticketStatus: DoPickOrderStatus?,
val doPickOrderId: Long?,
val isRecord: Boolean
)
val allTickets = mutableListOf<TicketData>()
doPickOrders.forEach { dpo ->
allTickets.add(TicketData(
storeId = dpo.storeId,
truckId = dpo.truckId,
truckLanceCode = dpo.truckLanceCode,
truckDepartureTime = dpo.truckDepartureTime,
shopId = dpo.shopId,
shopCode = dpo.shopCode,
ticketNo = dpo.ticketNo,
ticketReleaseTime = dpo.ticketReleaseTime,
ticketCompleteDateTime = dpo.ticketCompleteDateTime,
ticketStatus = dpo.ticketStatus,
doPickOrderId = dpo.id,
isRecord = false
))
}
doPickOrderRecords.forEach { record ->
allTickets.add(TicketData(
storeId = record.storeId,
truckId = record.truckId,
truckLanceCode = record.truckLanceCode,
truckDepartureTime = record.truckDepartureTime,
shopId = record.shopId,
shopCode = record.shopCode,
ticketNo = record.ticketNo,
ticketReleaseTime = record.ticketReleaseTime,
ticketCompleteDateTime = record.ticketCompleteDateTime,
ticketStatus = record.ticketStatus,
doPickOrderId = record.recordId,
isRecord = true
))
}
// Group by storeId, truckLanceCode, truckDepartureTime
val grouped = allTickets.groupBy {
Triple(it.storeId, it.truckLanceCode, it.truckDepartureTime)
}
return grouped.map { (key, tickets) ->
val (storeId, truckLanceCode, truckDepartureTime) = key
// Count distinct shops
val distinctShops = tickets.mapNotNull { it.shopId ?: it.shopCode?.hashCode()?.toLong() }.distinct().size
// Count distinct tickets
val distinctTickets = tickets.mapNotNull { it.ticketNo }.distinct().size
// Calculate total items to pick
var totalItems = 0
tickets.forEach { ticket ->
if (ticket.doPickOrderId != null) {
if (ticket.isRecord) {
totalItems += countFGItemsFromRecordById(ticket.doPickOrderId)
} else {
totalItems += countFGItemsById(ticket.doPickOrderId)
}
}
}
// Count released tickets (ticketReleaseTime is not null)
val releasedTickets = tickets.count { it.ticketReleaseTime != null }
// Find first ticket start time (earliest ticketReleaseTime)
val firstTicketStartTime = tickets
.mapNotNull { it.ticketReleaseTime }
.minOrNull()
// Count completed tickets (ticketCompleteDateTime is not null)
val completedTickets = tickets.count { it.ticketCompleteDateTime != null }
// Find last ticket end time (latest ticketCompleteDateTime)
val lastTicketEndTime = tickets
.mapNotNull { it.ticketCompleteDateTime }
.maxOrNull()
// Calculate pick time taken in minutes
val pickTimeTakenMinutes = if (firstTicketStartTime != null && lastTicketEndTime != null) {
ChronoUnit.MINUTES.between(firstTicketStartTime, lastTicketEndTime)
} else {
null
}
// Get truck ID (use first non-null)
val truckId = tickets.firstOrNull { it.truckId != null }?.truckId
TruckScheduleDashboardResponse(
storeId = storeId,
truckId = truckId,
truckLanceCode = truckLanceCode,
truckDepartureTime = truckDepartureTime,
numberOfShopsToServe = distinctShops,
numberOfPickTickets = distinctTickets,
totalItemsToPick = totalItems,
numberOfTicketsReleased = releasedTickets,
firstTicketStartTime = firstTicketStartTime,
numberOfTicketsCompleted = completedTickets,
lastTicketEndTime = lastTicketEndTime,
pickTimeTakenMinutes = pickTimeTakenMinutes
)
}.sortedWith(compareBy({ it.storeId }, { it.truckDepartureTime }))
}
private fun countFGItemsById(doPickOrderId: Long): Int {
val doPickOrderLines = doPickOrderLineRepository.findByDoPickOrderIdAndDeletedFalse(doPickOrderId)
val pickOrderIds = doPickOrderLines.mapNotNull { it.pickOrderId }.distinct()

if (pickOrderIds.isEmpty()) {
val doPickOrder = doPickOrderRepository.findById(doPickOrderId).orElse(null)
val directPickOrderId = doPickOrder?.pickOrderId
if (directPickOrderId != null) {
val pickOrderLines = pickOrderLineRepository.findAllByPickOrderId(directPickOrderId)
return pickOrderLines.size
}
return 0
}
val allPickOrderLines = pickOrderIds.flatMap { pickOrderId ->
pickOrderLineRepository.findAllByPickOrderId(pickOrderId)
}
return allPickOrderLines.size
}

private fun countFGItemsFromRecordById(recordId: Long): Int {
val doPickOrderLineRecords = doPickOrderLineRecordRepository.findByDoPickOrderIdAndDeletedFalse(recordId)
if (doPickOrderLineRecords.isEmpty()) {
return 0
}

val pickOrderIds = doPickOrderLineRecords.mapNotNull { it.pickOrderId }.distinct()
if (pickOrderIds.isEmpty()) {
return 0
}

val allPickOrderLines = pickOrderIds.flatMap { pickOrderId ->
pickOrderLineRepository.findAllByPickOrderId(pickOrderId)
}

return allPickOrderLines.size
}

}// 类结束

+ 21
- 0
src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/TruckScheduleDashboardResponse.kt Parādīt failu

@@ -0,0 +1,21 @@
package com.ffii.fpsms.modules.deliveryOrder.web.models

import java.time.LocalDateTime
import java.time.LocalTime

data class TruckScheduleDashboardResponse(
val storeId: String?,
val truckId: Long?,
val truckLanceCode: String?,
val truckDepartureTime: LocalTime?,
val numberOfShopsToServe: Int,
val numberOfPickTickets: Int,
val totalItemsToPick: Int,
val numberOfTicketsReleased: Int,
val firstTicketStartTime: LocalDateTime?,
val numberOfTicketsCompleted: Int,
val lastTicketEndTime: LocalDateTime?,
val pickTimeTakenMinutes: Long?
)



Notiek ielāde…
Atcelt
Saglabāt