| @@ -30,6 +30,8 @@ interface TruckRepository : AbstractRepository<Truck, Long> { | |||
| // 按 TruckLanceCode 查询 | |||
| 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 findByShopCodeAndStoreId(shopCode: String, storeId: String): Truck? | |||
| @@ -74,7 +76,7 @@ fun findByShopIdAndStoreIdAndDayOfWeek( | |||
| @Query( | |||
| nativeQuery = true, | |||
| 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.addr1 as addr1, s.addr2 as addr2, s.addr3 as addr3, s.type as type, | |||
| t.TruckLanceCode as truckLanceCode, t.DepartureTime as departureTime, | |||
| @@ -87,4 +89,58 @@ fun findByShopIdAndStoreIdAndDayOfWeek( | |||
| """ | |||
| ) | |||
| 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.TruckRepository | |||
| 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.format.DateTimeFormatter | |||
| import com.ffii.fpsms.modules.master.entity.ShopRepository | |||
| 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.UpdateLoadingSequenceRequest | |||
| import jakarta.transaction.Transactional | |||
| @@ -222,7 +223,7 @@ open class TruckService( | |||
| } | |||
| @Transactional | |||
| open fun createTruck(request: SaveTruckRequest): Truck { | |||
| open fun createTruckInShop(request: SaveTruckRequest): Truck { | |||
| // Always create a new truck, ignore id if provided | |||
| val truck = Truck() | |||
| val shop = shopRepository.findById(request.shopId).orElse(null) | |||
| @@ -254,13 +255,84 @@ open class TruckService( | |||
| 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 | |||
| open fun updateLoadingSequence(request: UpdateLoadingSequenceRequest): Truck { | |||
| open fun updateTruckShopDetails(request: UpdateTruckShopDetailsRequest): Truck { | |||
| val truck = truckRepository.findById(request.id).orElseThrow { | |||
| 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 | |||
| // 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) | |||
| } | |||
| @@ -12,11 +12,12 @@ import org.springframework.web.bind.annotation.* | |||
| import org.springframework.web.multipart.MultipartHttpServletRequest | |||
| 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.entity.TruckRepository | |||
| 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.UpdateLoadingSequenceRequest | |||
| import jakarta.validation.Valid | |||
| @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 { | |||
| val truck = truckService.createTruck(request) | |||
| val truck = truckService.createTruckInShop(request) | |||
| return MessageResponse( | |||
| id = truck.id, | |||
| name = truck.shopName, | |||
| @@ -187,16 +188,67 @@ class TruckController( | |||
| 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 { | |||
| val truck = truckService.updateLoadingSequence(request) | |||
| val truck = truckService.updateTruckShopDetails(request) | |||
| return MessageResponse( | |||
| id = truck.id, | |||
| name = truck.shopName, | |||
| code = truck.truckLanceCode, | |||
| 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, | |||
| entity = truck | |||
| ) | |||
| @@ -24,7 +24,19 @@ data class SaveTruckLane( | |||
| data class deleteTruckLane( | |||
| val id: Long | |||
| ) | |||
| data class UpdateLoadingSequenceRequest( | |||
| data class UpdateTruckShopDetailsRequest( | |||
| 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, | |||
| ) | |||