Browse Source

Merge branch 'master' of https://git.2fi-solutions.com/derek/FPSMS-backend

# Conflicts:
#	src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt
master
kelvin.yau 2 months ago
parent
commit
47f160ecc2
9 changed files with 1081 additions and 146 deletions
  1. +97
    -0
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderRecord.kt
  2. +18
    -0
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderRecordRepository.kt
  3. +1
    -0
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/enums/DoPickOrderStatus.kt
  4. +58
    -29
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt
  5. +58
    -7
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderService.kt
  6. +1
    -1
      src/main/java/com/ffii/fpsms/modules/pickOrder/entity/RouterRepository.kt
  7. +825
    -109
      src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt
  8. +16
    -0
      src/main/java/com/ffii/fpsms/modules/pickOrder/web/PickOrderController.kt
  9. +7
    -0
      src/main/resources/db/changelog/changes/20251098_01_enson/02_altertable_enson.sql

+ 97
- 0
src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderRecord.kt View File

@@ -0,0 +1,97 @@
package com.ffii.fpsms.modules.deliveryOrder.entity

import jakarta.persistence.*
import java.time.LocalDateTime
import java.time.LocalTime
import com.ffii.fpsms.modules.deliveryOrder.enums.DoPickOrderStatus
import org.hibernate.annotations.CreationTimestamp
import org.hibernate.annotations.UpdateTimestamp

@Entity
@Table(name = "do_pick_order_record")
class DoPickOrderRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long? = null
@Column(name = "store_id", length = 10)
var storeId: String? = null
@Column(name = "ticket_no", length = 50)
var ticketNo: String? = null
@Column(name = "pick_order_id")
var pickOrderId: Long? = null
@Enumerated(EnumType.STRING)
@Column(name = "ticket_status")
var ticketStatus: DoPickOrderStatus? = null
@Column(name = "truck_id")
var truckId: Long? = null
@Column(name = "truck_departure_time")
var truckDepartureTime: LocalTime? = null
@Column(name = "item_id")
var itemId: Long? = null
@Column(name = "shop_id")
var shopId: Long? = null
@Column(name = "shop_po_supplier_id")
var shopPoSupplierId: Long? = null
@Column(name = "handled_by")
var handledBy: Long? = null
@CreationTimestamp
@Column(name = "created")
var created: LocalDateTime? = null
@Column(name = "createdBy", length = 30)
var createdBy: String? = null
@Version
var version: Int = 0
@UpdateTimestamp
@Column(name = "modified")
var modified: LocalDateTime? = null
@Column(name = "modifiedBy", length = 30)
var modifiedBy: String? = null
@Column(name = "deleted")
var deleted: Boolean = false
// Default constructor for Hibernate
constructor()
// Constructor for creating new instances
constructor(
storeId: String,
ticketNo: String,
ticketStatus: DoPickOrderStatus,
truckId: Long? = null,
truckDepartureTime: LocalTime? = null,
pickOrderId: Long? = null,
itemId: Long? = null,
shopId: Long? = null,
shopPoSupplierId: Long? = null,
handledBy: Long? = null,
createdBy: String? = null,
modifiedBy: String? = null
) {
this.storeId = storeId
this.ticketNo = ticketNo
this.pickOrderId = pickOrderId
this.ticketStatus = ticketStatus
this.truckId = truckId
this.truckDepartureTime = truckDepartureTime
this.itemId = itemId
this.shopId = shopId
this.shopPoSupplierId = shopPoSupplierId
this.handledBy = handledBy
this.createdBy = createdBy
this.modifiedBy = modifiedBy
}
}

+ 18
- 0
src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderRecordRepository.kt View File

@@ -0,0 +1,18 @@
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 com.ffii.fpsms.modules.deliveryOrder.enums.DoPickOrderStatus
import com.ffii.fpsms.modules.master.entity.projections.SearchId
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Query
import org.springframework.stereotype.Repository
import java.io.Serializable
import java.time.LocalDateTime

@Repository
interface DoPickOrderRecordRepository : JpaRepository<DoPickOrderRecord, Long> {
fun findByPickOrderId(pickOrderId: Long): List<DoPickOrderRecord>
fun findByTicketNoStartingWith(ticketPrefix: String): List<DoPickOrderRecord>
}

+ 1
- 0
src/main/java/com/ffii/fpsms/modules/deliveryOrder/enums/DoPickOrderStatus.kt View File

@@ -2,5 +2,6 @@ package com.ffii.fpsms.modules.deliveryOrder.enums

enum class DoPickOrderStatus(val value: String) {
pending("pending"),
released("released"),
completed("completed")
}

+ 58
- 29
src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt View File

@@ -57,6 +57,9 @@ import org.springframework.core.io.ClassPathResource
import java.io.File
import java.io.FileNotFoundException

import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderRecord
import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderRecordRepository

@Service
open class DeliveryOrderService(
private val deliveryOrderRepository: DeliveryOrderRepository,
@@ -75,7 +78,8 @@ open class DeliveryOrderService(
private val stockOutRepository: StockOutRepository,
private val stockOutLineRepository: StockOutLIneRepository,
private val pickOrderLineRepository: PickOrderLineRepository,
private val printerService: PrinterService
private val printerService: PrinterService,
private val doPickOrderRecordRepository: DoPickOrderRecordRepository
) {

open fun findByM18DataLogId(m18DataLogId: Long): DeliveryOrder? {
@@ -452,14 +456,9 @@ open class DeliveryOrderService(
val datePrefix = targetDate.format(DateTimeFormatter.ofPattern("ddMMyy"))
println("�� DEBUG: Target date: $targetDate, Date prefix: $datePrefix")
// Get next ticket number for this date
val nextTicketNumber = doPickOrderService.getNextTicketNumber(datePrefix)
println("🔍 DEBUG: Next ticket number: $nextTicketNumber")
// ✅ Find truck by shop ID with earliest departure time

val truck = deliveryOrder.shop?.id?.let { shopId ->
println("�� DEBUG: Looking for truck with shop ID: $shopId")
println("🔍 DEBUG: Looking for truck with shop ID: $shopId")
val trucks = truckRepository.findByShopIdAndDeletedFalse(shopId)
println("🔍 DEBUG: Found ${trucks.size} trucks for shop $shopId")
trucks.forEach { t ->
@@ -472,29 +471,59 @@ open class DeliveryOrderService(
println("🔍 DEBUG: Processing ${deliveryOrder.deliveryOrderLines.size} delivery order lines")
deliveryOrder.deliveryOrderLines.forEach { line ->
val storeId = if (deliveryOrder.supplier?.code == "P06B") "4/F" else "2/F"
println("�� DEBUG: Processing line - Item ID: ${line.item?.id}, Store ID: $storeId")
val doPickOrder = DoPickOrder(
storeId = storeId,
ticketNo = nextTicketNumber,
ticketStatus = DoPickOrderStatus.pending,
truckId = truck?.id,
pickOrderId = createdPickOrder.id,
truckDepartureTime = truck?.departureTime,
itemId = line.item?.id,
shopId = deliveryOrder.shop?.id,
shopPoSupplierId = deliveryOrder.shop?.id,
handledBy = null
)
println("�� DEBUG: Creating DoPickOrder - Store: $storeId, Ticket: $nextTicketNumber, Truck: ${truck?.id}")
val savedDoPickOrder = doPickOrderService.save(doPickOrder)
println("🔍 DEBUG: Saved DoPickOrder - ID: ${savedDoPickOrder.id}")
// ✅ Group lines by store ID to get unique ticket numbers per store
val linesByStore = deliveryOrder.deliveryOrderLines.groupBy { line ->
if (deliveryOrder.supplier?.code == "P06B") "4/F" else "2/F"
}

linesByStore.forEach { (storeId, lines) ->
// ✅ Get ticket number for this specific store
val nextTicketNumber = doPickOrderService.getNextTicketNumber(datePrefix, storeId)
println("🔍 DEBUG: Next ticket number for store $storeId: $nextTicketNumber")

lines.forEach { line ->
println("�� DEBUG: Processing line - Item ID: ${line.item?.id}, Store ID: $storeId")

val doPickOrderRecord = DoPickOrderRecord(
storeId = storeId,
ticketNo = nextTicketNumber,
ticketStatus = DoPickOrderStatus.pending,
truckId = truck?.id,
pickOrderId = createdPickOrder.id,
truckDepartureTime = truck?.departureTime,
itemId = line.item?.id,
shopId = deliveryOrder.shop?.id,
shopPoSupplierId = deliveryOrder.shop?.id,
handledBy = null
)

println("�� DEBUG: Creating DoPickOrderRecord - Store: $storeId, Ticket: $nextTicketNumber, Truck: ${truck?.id}")

val savedDoPickOrderRecord = doPickOrderRecordRepository.save(doPickOrderRecord)
println("🔍 DEBUG: Saved DoPickOrderRecord - ID: ${savedDoPickOrderRecord.id}")
}
// ✅ Also create DoPickOrder records for this store
lines.forEach { line ->
println("�� DEBUG: Creating DoPickOrder - Store: $storeId, Ticket: $nextTicketNumber, Truck: ${truck?.id}")

val doPickOrder = DoPickOrder(
storeId = storeId,
ticketNo = nextTicketNumber,
ticketStatus = DoPickOrderStatus.pending,
truckId = truck?.id,
pickOrderId = createdPickOrder.id,
truckDepartureTime = truck?.departureTime,
itemId = line.item?.id,
shopId = deliveryOrder.shop?.id,
shopPoSupplierId = deliveryOrder.shop?.id,
handledBy = null
)

val savedDoPickOrder = doPickOrderService.save(doPickOrder)
println("🔍 DEBUG: Saved DoPickOrder - ID: ${savedDoPickOrder.id}")
}
}
return MessageResponse(
id = deliveryOrder.id,
code = deliveryOrder.code,


+ 58
- 7
src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderService.kt View File

@@ -33,21 +33,27 @@ import java.math.BigDecimal
import com.ffii.fpsms.modules.master.web.models.MessageResponse
import java.time.LocalDateTime
import com.ffii.fpsms.modules.deliveryOrder.web.models.AssignByStoreRequest
import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderRecord
import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderRecordRepository
@Service
class DoPickOrderService(
private val doPickOrderRepository: DoPickOrderRepository
private val doPickOrderRepository: DoPickOrderRepository,
private val doPickOrderRecordRepository: DoPickOrderRecordRepository
) {
fun getNextTicketNumber(datePrefix: String): String {
println("🔍 DEBUG: Getting next ticket number for date prefix: $datePrefix")
fun getNextTicketNumber(datePrefix: String, storeId: String): String {
println("🔍 DEBUG: Getting next ticket number for date prefix: $datePrefix, store: $storeId")
try {
val todayTickets = doPickOrderRepository.findByTicketNoStartingWith("${datePrefix}_")
println("🔍 DEBUG: Found ${todayTickets.size} existing tickets with prefix ${datePrefix}_")
val sanitizedStoreId = storeId.replace("/", "")
// ✅ Include store ID in the search pattern
val searchPattern = "${datePrefix}_${sanitizedStoreId}_"
val todayTickets = doPickOrderRepository.findByTicketNoStartingWith(searchPattern)
println("🔍 DEBUG: Found ${todayTickets.size} existing tickets with prefix $searchPattern")
todayTickets.forEach { ticket ->
println("�� DEBUG: Existing ticket: ${ticket.ticketNo}, Status: ${ticket.ticketStatus}")
}
val nextNumber = (todayTickets.size + 1).toString().padStart(3, '0')
val ticketNumber = "${datePrefix}_${nextNumber}"
val ticketNumber = "${datePrefix}_${sanitizedStoreId}_${nextNumber}"
println("🔍 DEBUG: Generated ticket number: $ticketNumber")
return ticketNumber
} catch (e: Exception) {
@@ -94,7 +100,52 @@ class DoPickOrderService(
}
fun updateHandledByForPickOrder(pickOrderId: Long, userId: Long): List<DoPickOrder> {
val doPickOrders = doPickOrderRepository.findByPickOrderId(pickOrderId)
doPickOrders.forEach { it.handledBy = userId }
doPickOrders.forEach { it.handledBy = userId
it.ticketStatus = DoPickOrderStatus.released }
return doPickOrderRepository.saveAll(doPickOrders)
}
fun completeDoPickOrdersForPickOrder(pickOrderId: Long): List<DoPickOrder> {
val doPickOrders = doPickOrderRepository.findByPickOrderId(pickOrderId)
doPickOrders.forEach {
it.ticketStatus = DoPickOrderStatus.completed // ✅ Update status to "completed"
}
return doPickOrderRepository.saveAll(doPickOrders)
}
// ✅ New method to remove do_pick_order records when auto-assigning by store
fun removeDoPickOrdersForPickOrder(pickOrderId: Long): Int {
val doPickOrders = doPickOrderRepository.findByPickOrderId(pickOrderId)
if (doPickOrders.isNotEmpty()) {
// Mark as deleted instead of physically deleting
doPickOrders.forEach {
it.ticketStatus = DoPickOrderStatus.completed
it.deleted = true }
doPickOrderRepository.saveAll(doPickOrders)
return doPickOrders.size
}
return 0
}

fun saveRecord(record: DoPickOrderRecord): DoPickOrderRecord {
return doPickOrderRecordRepository.save(record)
}
// ✅ Add method to update DoPickOrderRecord status
fun updateRecordHandledByForPickOrder(pickOrderId: Long, userId: Long): List<DoPickOrderRecord> {
val doPickOrderRecords = doPickOrderRecordRepository.findByPickOrderId(pickOrderId)
doPickOrderRecords.forEach {
it.handledBy = userId
it.ticketStatus = DoPickOrderStatus.released
}
return doPickOrderRecordRepository.saveAll(doPickOrderRecords)
}
// ✅ Add method to complete DoPickOrderRecord
fun completeDoPickOrderRecordsForPickOrder(pickOrderId: Long): List<DoPickOrderRecord> {
val doPickOrderRecords = doPickOrderRecordRepository.findByPickOrderId(pickOrderId)
doPickOrderRecords.forEach {
it.ticketStatus = DoPickOrderStatus.completed
}
return doPickOrderRecordRepository.saveAll(doPickOrderRecords)
}
}

+ 1
- 1
src/main/java/com/ffii/fpsms/modules/pickOrder/entity/RouterRepository.kt View File

@@ -22,5 +22,5 @@ interface RouterRepository : AbstractRepository<Router, Long> {
@Query("SELECT r FROM Router r WHERE r.route = :route AND r.deleted = false")
fun findByRouteAndDeletedFalse(@Param("route") route: String): List<Router>
}

+ 825
- 109
src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt
File diff suppressed because it is too large
View File


+ 16
- 0
src/main/java/com/ffii/fpsms/modules/pickOrder/web/PickOrderController.kt View File

@@ -266,4 +266,20 @@ class PickOrderController(
fun getAllPickOrderLotsWithDetailsWithoutAutoAssign(@PathVariable userId: Long): List<Map<String, Any>> {
return pickOrderService.getAllPickOrderLotsWithDetailsWithoutAutoAssign(userId)
}
@GetMapping("/all-lots-hierarchical/{userId}")
fun getAllPickOrderLotsHierarchical(@PathVariable userId: Long): Map<String, Any?> {
return pickOrderService.getAllPickOrderLotsWithDetailsHierarchical(userId)
}
@PostMapping("/auto-assign-release-by-ticket")
fun autoAssignAndReleasePickOrderByTicket(
@RequestParam storeId: String,
@RequestParam ticketNo: String,
@RequestParam userId: Long
): MessageResponse {
return pickOrderService.autoAssignAndReleasePickOrderByStoreAndTicket(storeId, ticketNo, userId)
}
@GetMapping("/orders-by-store/{storeId}")
fun getPickOrdersByStore(@PathVariable storeId: String): Map<String, Any?> {
return pickOrderService.getPickOrdersByDateAndStore(storeId)
}
}

+ 7
- 0
src/main/resources/db/changelog/changes/20251098_01_enson/02_altertable_enson.sql View File

@@ -0,0 +1,7 @@
-- liquibase formatted sql
-- changeset enson:altertable_enson

ALTER TABLE `fpsmsdb`.`do_pick_order`
CHANGE COLUMN `ticket_status` `ticket_status` ENUM('pending', 'released', 'completed') NULL DEFAULT 'pending' ;
ALTER TABLE `fpsmsdb`.`do_pick_order_record`
CHANGE COLUMN `ticket_status` `ticket_status` ENUM('pending', 'released', 'completed') NULL DEFAULT 'pending' ;

Loading…
Cancel
Save