| @@ -30,6 +30,8 @@ interface TruckRepository : AbstractRepository<Truck, Long> { | |||||
| // 按 TruckLanceCode 查询 | // 按 TruckLanceCode 查询 | ||||
| fun findByTruckLanceCode(truckLanceCode: String): Truck? | fun findByTruckLanceCode(truckLanceCode: String): Truck? | ||||
| @Query("SELECT t FROM Truck t WHERE t.truckLanceCode = :truckLanceCode AND t.deleted = false") | |||||
| fun findAllByTruckLanceCodeAndDeletedFalse(@Param("truckLanceCode") truckLanceCode: String): List<Truck> | |||||
| fun findByShopNameAndStoreIdAndTruckLanceCode(shopName: String, storeId: String, truckLanceCode: String): Truck? | fun findByShopNameAndStoreIdAndTruckLanceCode(shopName: String, storeId: String, truckLanceCode: String): Truck? | ||||
| fun findByShopCodeAndStoreId(shopCode: String, storeId: String): Truck? | fun findByShopCodeAndStoreId(shopCode: String, storeId: String): Truck? | ||||
| @@ -74,7 +76,7 @@ fun findByShopIdAndStoreIdAndDayOfWeek( | |||||
| @Query( | @Query( | ||||
| nativeQuery = true, | nativeQuery = true, | ||||
| value = """ | value = """ | ||||
| SELECT s.id as id, t.ShopCode as code, s.name as name, s.contactNo as contactNo, | |||||
| SELECT s.id as id, t.ShopCode as code, t.ShopName as name, s.contactNo as contactNo, | |||||
| s.contactEmail as contactEmail, s.contactName as contactName, | s.contactEmail as contactEmail, s.contactName as contactName, | ||||
| s.addr1 as addr1, s.addr2 as addr2, s.addr3 as addr3, s.type as type, | s.addr1 as addr1, s.addr2 as addr2, s.addr3 as addr3, s.type as type, | ||||
| t.TruckLanceCode as truckLanceCode, t.DepartureTime as departureTime, | t.TruckLanceCode as truckLanceCode, t.DepartureTime as departureTime, | ||||
| @@ -87,4 +89,58 @@ fun findByShopIdAndStoreIdAndDayOfWeek( | |||||
| """ | """ | ||||
| ) | ) | ||||
| fun findAllFromShopAndTruckByTruckLanceCodeAndDeletedFalse(@Param("truckLanceCode") truckLanceCode: String): List<ShopAndTruck> | fun findAllFromShopAndTruckByTruckLanceCodeAndDeletedFalse(@Param("truckLanceCode") truckLanceCode: String): List<ShopAndTruck> | ||||
| @Query( | |||||
| nativeQuery = true, | |||||
| value = """ | |||||
| SELECT DISTINCT t.ShopName as name, t.ShopCode as code | |||||
| FROM truck t | |||||
| WHERE t.deleted = false | |||||
| AND t.ShopName IS NOT NULL | |||||
| AND t.ShopCode IS NOT NULL | |||||
| AND t.ShopName != '' | |||||
| AND t.ShopCode != '' | |||||
| ORDER BY t.ShopName, t.ShopCode | |||||
| """ | |||||
| ) | |||||
| fun findAllUniqueShopNamesAndCodesFromTrucks(): List<Map<String, String>> | |||||
| @Query( | |||||
| nativeQuery = true, | |||||
| value = """ | |||||
| SELECT DISTINCT t.remark as remark | |||||
| FROM truck t | |||||
| WHERE t.deleted = false | |||||
| AND t.remark IS NOT NULL | |||||
| AND t.remark != '' | |||||
| ORDER BY t.remark | |||||
| """ | |||||
| ) | |||||
| fun findAllUniqueRemarksFromTrucks(): List<String> | |||||
| @Query( | |||||
| nativeQuery = true, | |||||
| value = """ | |||||
| SELECT DISTINCT t.ShopCode as code | |||||
| FROM truck t | |||||
| WHERE t.deleted = false | |||||
| AND t.ShopCode IS NOT NULL | |||||
| AND t.ShopCode != '' | |||||
| ORDER BY t.ShopCode | |||||
| """ | |||||
| ) | |||||
| fun findAllUniqueShopCodesFromTrucks(): List<String> | |||||
| @Query( | |||||
| nativeQuery = true, | |||||
| value = """ | |||||
| SELECT DISTINCT t.ShopName as name | |||||
| FROM truck t | |||||
| WHERE t.deleted = false | |||||
| AND t.ShopName IS NOT NULL | |||||
| AND t.ShopName != '' | |||||
| ORDER BY t.ShopName | |||||
| """ | |||||
| ) | |||||
| fun findAllUniqueShopNamesFromTrucks(): List<String> | |||||
| } | } | ||||
| @@ -9,12 +9,13 @@ import org.springframework.stereotype.Service | |||||
| import com.ffii.fpsms.modules.pickOrder.entity.Truck | import com.ffii.fpsms.modules.pickOrder.entity.Truck | ||||
| import com.ffii.fpsms.modules.pickOrder.entity.TruckRepository | import com.ffii.fpsms.modules.pickOrder.entity.TruckRepository | ||||
| import com.ffii.fpsms.modules.pickOrder.web.models.SaveTruckRequest | import com.ffii.fpsms.modules.pickOrder.web.models.SaveTruckRequest | ||||
| import com.ffii.fpsms.modules.pickOrder.web.models.CreateTruckWithoutShopRequest | |||||
| import com.ffii.fpsms.modules.pickOrder.web.models.UpdateTruckShopDetailsRequest | |||||
| import java.time.LocalTime | import java.time.LocalTime | ||||
| import java.time.format.DateTimeFormatter | import java.time.format.DateTimeFormatter | ||||
| import com.ffii.fpsms.modules.master.entity.ShopRepository | import com.ffii.fpsms.modules.master.entity.ShopRepository | ||||
| import com.ffii.fpsms.modules.master.entity.projections.ShopAndTruck | import com.ffii.fpsms.modules.master.entity.projections.ShopAndTruck | ||||
| import com.ffii.fpsms.modules.pickOrder.web.models.SaveTruckLane | import com.ffii.fpsms.modules.pickOrder.web.models.SaveTruckLane | ||||
| import com.ffii.fpsms.modules.pickOrder.web.models.UpdateLoadingSequenceRequest | |||||
| import jakarta.transaction.Transactional | import jakarta.transaction.Transactional | ||||
| @@ -222,7 +223,7 @@ open class TruckService( | |||||
| } | } | ||||
| @Transactional | @Transactional | ||||
| open fun createTruck(request: SaveTruckRequest): Truck { | |||||
| open fun createTruckInShop(request: SaveTruckRequest): Truck { | |||||
| // Always create a new truck, ignore id if provided | // Always create a new truck, ignore id if provided | ||||
| val truck = Truck() | val truck = Truck() | ||||
| val shop = shopRepository.findById(request.shopId).orElse(null) | val shop = shopRepository.findById(request.shopId).orElse(null) | ||||
| @@ -254,13 +255,84 @@ open class TruckService( | |||||
| return truckRepository.findAllFromShopAndTruckByTruckLanceCodeAndDeletedFalse(truckLanceCode) | return truckRepository.findAllFromShopAndTruckByTruckLanceCodeAndDeletedFalse(truckLanceCode) | ||||
| } | } | ||||
| open fun findAllByTruckLanceCodeAndDeletedFalse(truckLanceCode: String): List<Truck> { | |||||
| return truckRepository.findAllByTruckLanceCodeAndDeletedFalse(truckLanceCode) | |||||
| } | |||||
| open fun findAllUniqueShopNamesAndCodesFromTrucks(): List<Map<String, String>> { | |||||
| return truckRepository.findAllUniqueShopNamesAndCodesFromTrucks() | |||||
| } | |||||
| open fun findAllUniqueRemarksFromTrucks(): List<String> { | |||||
| return truckRepository.findAllUniqueRemarksFromTrucks() | |||||
| } | |||||
| open fun findAllUniqueShopCodesFromTrucks(): List<String> { | |||||
| return truckRepository.findAllUniqueShopCodesFromTrucks() | |||||
| } | |||||
| open fun findAllUniqueShopNamesFromTrucks(): List<String> { | |||||
| return truckRepository.findAllUniqueShopNamesFromTrucks() | |||||
| } | |||||
| @Transactional | @Transactional | ||||
| open fun updateLoadingSequence(request: UpdateLoadingSequenceRequest): Truck { | |||||
| open fun updateTruckShopDetails(request: UpdateTruckShopDetailsRequest): Truck { | |||||
| val truck = truckRepository.findById(request.id).orElseThrow { | val truck = truckRepository.findById(request.id).orElseThrow { | ||||
| IllegalArgumentException("Truck not found with id: ${request.id}") | IllegalArgumentException("Truck not found with id: ${request.id}") | ||||
| } | } | ||||
| // Update shop relationship if shopId is provided | |||||
| if (request.shopId != null) { | |||||
| val shop = shopRepository.findById(request.shopId).orElse(null) | |||||
| if (shop != null) { | |||||
| truck.shop = shop | |||||
| } else { | |||||
| throw IllegalArgumentException("Shop not found with id: ${request.shopId}") | |||||
| } | |||||
| } | |||||
| // Always use shopName and shopCode from request (from truck table), not from shop entity | |||||
| // This allows truck table to have different shop names/codes than shop table | |||||
| if (request.shopName != null) { | |||||
| truck.shopName = request.shopName | |||||
| } | |||||
| if (request.shopCode != null) { | |||||
| truck.shopCode = request.shopCode | |||||
| } | |||||
| // Update loadingSequence | |||||
| truck.loadingSequence = request.loadingSequence | truck.loadingSequence = request.loadingSequence | ||||
| // Update remark - only set if storeId is "4F", otherwise set to null | |||||
| val storeIdStr = truck.storeId | |||||
| if (storeIdStr == "4F") { | |||||
| truck.remark = request.remark | |||||
| } else { | |||||
| truck.remark = null | |||||
| } | |||||
| return truckRepository.save(truck) | |||||
| } | |||||
| @Transactional | |||||
| open fun createTruckWithoutShop(request: CreateTruckWithoutShopRequest): Truck { | |||||
| // Create a new truck without a shop | |||||
| val truck = Truck() | |||||
| truck.apply { | |||||
| this.storeId = request.store_id | |||||
| this.truckLanceCode = request.truckLanceCode | |||||
| this.departureTime = request.departureTime | |||||
| this.shop = null | |||||
| this.shopName = "Unassign" | |||||
| this.shopCode = "Unassign" | |||||
| this.loadingSequence = request.loadingSequence | |||||
| this.districtReference = request.districtReference | |||||
| // Only set remark if store_id is "4F", otherwise set to null | |||||
| this.remark = if (request.store_id == "4F") request.remark else null | |||||
| } | |||||
| return truckRepository.save(truck) | return truckRepository.save(truck) | ||||
| } | } | ||||
| @@ -12,11 +12,12 @@ import org.springframework.web.bind.annotation.* | |||||
| import org.springframework.web.multipart.MultipartHttpServletRequest | import org.springframework.web.multipart.MultipartHttpServletRequest | ||||
| import com.ffii.fpsms.modules.pickOrder.web.models.SaveTruckRequest | import com.ffii.fpsms.modules.pickOrder.web.models.SaveTruckRequest | ||||
| import com.ffii.fpsms.modules.pickOrder.web.models.CreateTruckWithoutShopRequest | |||||
| import com.ffii.fpsms.modules.pickOrder.web.models.UpdateTruckShopDetailsRequest | |||||
| import com.ffii.fpsms.modules.pickOrder.service.TruckService | import com.ffii.fpsms.modules.pickOrder.service.TruckService | ||||
| import com.ffii.fpsms.modules.pickOrder.entity.TruckRepository | import com.ffii.fpsms.modules.pickOrder.entity.TruckRepository | ||||
| import com.ffii.fpsms.modules.pickOrder.web.models.SaveTruckLane | import com.ffii.fpsms.modules.pickOrder.web.models.SaveTruckLane | ||||
| import com.ffii.fpsms.modules.pickOrder.web.models.deleteTruckLane | import com.ffii.fpsms.modules.pickOrder.web.models.deleteTruckLane | ||||
| import com.ffii.fpsms.modules.pickOrder.web.models.UpdateLoadingSequenceRequest | |||||
| import jakarta.validation.Valid | import jakarta.validation.Valid | ||||
| @RestController | @RestController | ||||
| @@ -53,10 +54,10 @@ class TruckController( | |||||
| } | } | ||||
| } | } | ||||
| @PostMapping("/create") | |||||
| fun createTruck(@Valid @RequestBody request: SaveTruckRequest): MessageResponse { | |||||
| @PostMapping("/createTruckInShop") | |||||
| fun createTruckInShop(@Valid @RequestBody request: SaveTruckRequest): MessageResponse { | |||||
| try { | try { | ||||
| val truck = truckService.createTruck(request) | |||||
| val truck = truckService.createTruckInShop(request) | |||||
| return MessageResponse( | return MessageResponse( | ||||
| id = truck.id, | id = truck.id, | ||||
| name = truck.shopName, | name = truck.shopName, | ||||
| @@ -187,16 +188,67 @@ class TruckController( | |||||
| return truckService.findAllFromShopAndTruckByTruckLanceCodeAndDeletedFalse(truckLanceCode) | return truckService.findAllFromShopAndTruckByTruckLanceCodeAndDeletedFalse(truckLanceCode) | ||||
| } | } | ||||
| @PostMapping("/updateLoadingSequence") | |||||
| fun updateLoadingSequence(@Valid @RequestBody request: UpdateLoadingSequenceRequest): MessageResponse { | |||||
| @GetMapping("/findAllByTruckLanceCodeAndDeletedFalse") | |||||
| fun findAllByTruckLanceCodeAndDeletedFalse(@RequestParam truckLanceCode: String): List<Truck> { | |||||
| return truckService.findAllByTruckLanceCodeAndDeletedFalse(truckLanceCode) | |||||
| } | |||||
| @GetMapping("/findAllUniqueShopNamesAndCodesFromTrucks") | |||||
| fun findAllUniqueShopNamesAndCodesFromTrucks(): List<Map<String, String>> { | |||||
| return truckService.findAllUniqueShopNamesAndCodesFromTrucks() | |||||
| } | |||||
| @GetMapping("/findAllUniqueRemarksFromTrucks") | |||||
| fun findAllUniqueRemarksFromTrucks(): List<String> { | |||||
| return truckService.findAllUniqueRemarksFromTrucks() | |||||
| } | |||||
| @GetMapping("/findAllUniqueShopCodesFromTrucks") | |||||
| fun findAllUniqueShopCodesFromTrucks(): List<String> { | |||||
| return truckService.findAllUniqueShopCodesFromTrucks() | |||||
| } | |||||
| @GetMapping("/findAllUniqueShopNamesFromTrucks") | |||||
| fun findAllUniqueShopNamesFromTrucks(): List<String> { | |||||
| return truckService.findAllUniqueShopNamesFromTrucks() | |||||
| } | |||||
| @PostMapping("/updateTruckShopDetails") | |||||
| fun updateTruckShopDetails(@Valid @RequestBody request: UpdateTruckShopDetailsRequest): MessageResponse { | |||||
| try { | try { | ||||
| val truck = truckService.updateLoadingSequence(request) | |||||
| val truck = truckService.updateTruckShopDetails(request) | |||||
| return MessageResponse( | return MessageResponse( | ||||
| id = truck.id, | id = truck.id, | ||||
| name = truck.shopName, | name = truck.shopName, | ||||
| code = truck.truckLanceCode, | code = truck.truckLanceCode, | ||||
| type = "truck", | type = "truck", | ||||
| message = "Loading sequence updated successfully", | |||||
| message = "Truck shop details updated successfully", | |||||
| errorPosition = null, | |||||
| entity = truck | |||||
| ) | |||||
| } catch (e: Exception) { | |||||
| return MessageResponse( | |||||
| id = null, | |||||
| name = null, | |||||
| code = null, | |||||
| type = "truck", | |||||
| message = "Error: ${e.message}", | |||||
| errorPosition = null, | |||||
| entity = null | |||||
| ) | |||||
| } | |||||
| } | |||||
| @PostMapping("/createTruckWithoutShop") | |||||
| fun createTruckWithoutShop(@Valid @RequestBody request: CreateTruckWithoutShopRequest): MessageResponse { | |||||
| try { | |||||
| val truck = truckService.createTruckWithoutShop(request) | |||||
| return MessageResponse( | |||||
| id = truck.id, | |||||
| name = truck.shopName, | |||||
| code = truck.truckLanceCode, | |||||
| type = "truck", | |||||
| message = "Truck created successfully", | |||||
| errorPosition = null, | errorPosition = null, | ||||
| entity = truck | entity = truck | ||||
| ) | ) | ||||
| @@ -24,7 +24,19 @@ data class SaveTruckLane( | |||||
| data class deleteTruckLane( | data class deleteTruckLane( | ||||
| val id: Long | val id: Long | ||||
| ) | ) | ||||
| data class UpdateLoadingSequenceRequest( | |||||
| data class UpdateTruckShopDetailsRequest( | |||||
| val id: Long, | val id: Long, | ||||
| val loadingSequence: Int | |||||
| val shopId: Long? = null, | |||||
| val shopName: String?, | |||||
| val shopCode: String?, | |||||
| val loadingSequence: Int, | |||||
| val remark: String? = null, | |||||
| ) | |||||
| data class CreateTruckWithoutShopRequest( | |||||
| val store_id: String, | |||||
| val truckLanceCode: String, | |||||
| val departureTime: LocalTime, | |||||
| val loadingSequence: Int = 0, | |||||
| val districtReference: Int? = null, | |||||
| val remark: String? = null, | |||||
| ) | ) | ||||