Przeglądaj źródła

Truck Routing Summary List

master
B.E.N.S.O.N 7 godzin temu
rodzic
commit
112fe9418c
3 zmienionych plików z 421 dodań i 0 usunięć
  1. +186
    -0
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/TruckRoutingSummaryService.kt
  2. +66
    -0
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/TruckRoutingSummaryController.kt
  3. +169
    -0
      src/main/resources/DeliveryNote/TruckRoutingSummaryPDF.jrxml

+ 186
- 0
src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/TruckRoutingSummaryService.kt Wyświetl plik

@@ -0,0 +1,186 @@
package com.ffii.fpsms.modules.deliveryOrder.service

import com.ffii.core.support.JdbcDao
import org.springframework.stereotype.Service

@Service
class TruckRoutingSummaryService(
private val jdbcDao: JdbcDao,
) {
fun getStoreOptions(): List<Map<String, String>> {
val sql = """
SELECT DISTINCT t.Store_id AS value
FROM truck t
WHERE t.deleted = 0
AND t.Store_id IS NOT NULL
AND TRIM(t.Store_id) <> ''
ORDER BY t.Store_id
""".trimIndent()

return jdbcDao.queryForList(sql, emptyMap<String, Any>()).map { row ->
val rawValue = (row["value"] ?: "").toString().trim()
val label = when (rawValue.uppercase()) {
"2F", "2/F" -> "2/F"
"4F", "4/F" -> "4/F"
else -> rawValue
}
mapOf("label" to label, "value" to rawValue)
}
}

fun getLaneOptions(storeId: String?): List<Map<String, String>> {
val args = mutableMapOf<String, Any>()
val storeSql = if (!storeId.isNullOrBlank()) {
args["storeId"] = storeId.replace("/", "")
"AND REPLACE(t.Store_id, '/', '') = :storeId"
} else {
""
}

val sql = """
SELECT DISTINCT t.TruckLanceCode AS value
FROM truck t
WHERE t.deleted = 0
AND t.TruckLanceCode IS NOT NULL
AND TRIM(t.TruckLanceCode) <> ''
$storeSql
ORDER BY t.TruckLanceCode
""".trimIndent()

return jdbcDao.queryForList(sql, args).map { row ->
val value = (row["value"] ?: "").toString().trim()
mapOf("label" to value, "value" to value)
}
}

fun search(storeId: String?, truckLanceCode: String?, reportDate: String?): List<Map<String, Any>> {
val args = mutableMapOf<String, Any>()
val storeSql = if (!storeId.isNullOrBlank()) {
args["storeId"] = storeId.replace("/", "")
"AND REPLACE(t.Store_id, '/', '') = :storeId"
} else {
""
}
val laneSql = if (!truckLanceCode.isNullOrBlank()) {
args["truckLanceCode"] = truckLanceCode.trim()
"AND t.TruckLanceCode = :truckLanceCode"
} else {
""
}
val storeSqlForMax = if (!storeId.isNullOrBlank()) {
"AND REPLACE(t2.Store_id, '/', '') = :storeId"
} else {
""
}
val laneSqlForMax = if (!truckLanceCode.isNullOrBlank()) {
"AND t2.TruckLanceCode = :truckLanceCode"
} else {
""
}
val cartonDateSql = if (!reportDate.isNullOrBlank()) {
args["reportDate"] = reportDate.trim()
"AND dpor.RequiredDeliveryDate = :reportDate"
} else {
""
}

val sql = """
SELECT
CAST(
CASE
WHEN seq_max.maxLoading IS NULL OR t.LoadingSequence IS NULL THEN COALESCE(t.LoadingSequence, 0)
ELSE seq_max.maxLoading - t.LoadingSequence + 1
END AS CHAR
) AS dropOffSequence,
COALESCE(s.`code`, '') AS shopCode,
TRIM(
CASE
WHEN LOCATE(' - ', COALESCE(s.name, '')) > 0
THEN SUBSTRING(
COALESCE(s.name, ''),
LOCATE(' - ', COALESCE(s.name, '')) + 3
)
ELSE COALESCE(s.name, '')
END
) AS shopName,
COALESCE(s.addr3, '') AS address,
CAST(COALESCE(carton_sum.qty, 0) AS CHAR) AS noOfCartons
FROM truck t
LEFT JOIN shop s
ON t.shopId = s.id
AND s.deleted = 0
LEFT JOIN (
SELECT truck_id, SUM(cartonQty) AS qty
FROM do_pick_order_record dpor
WHERE dpor.deleted = 0
$cartonDateSql
GROUP BY truck_id
) carton_sum ON carton_sum.truck_id = t.id
CROSS JOIN (
SELECT MAX(t2.LoadingSequence) AS maxLoading
FROM truck t2
WHERE t2.deleted = 0
$storeSqlForMax
$laneSqlForMax
) seq_max
WHERE t.deleted = 0
$storeSql
$laneSql
ORDER BY t.LoadingSequence DESC, COALESCE(s.`code`, t.ShopCode) ASC
""".trimIndent()

val rows = jdbcDao.queryForList(sql, args)
if (rows.isNotEmpty()) {
return rows
}

return listOf(
mapOf(
"dropOffSequence" to "",
"shopCode" to "",
"shopName" to "",
"address" to "",
"noOfCartons" to "",
)
)
}

/**
* Earliest departure time among trucks matching store + lane (for PDF header).
*/
fun getDepartureTimeLabel(storeId: String?, truckLanceCode: String?): String {
val args = mutableMapOf<String, Any>()
val storeSql = if (!storeId.isNullOrBlank()) {
args["storeId"] = storeId.replace("/", "")
"AND REPLACE(t.Store_id, '/', '') = :storeId"
} else {
return ""
}
val laneSql = if (!truckLanceCode.isNullOrBlank()) {
args["truckLanceCode"] = truckLanceCode.trim()
"AND t.TruckLanceCode = :truckLanceCode"
} else {
return ""
}
val sql = """
SELECT DATE_FORMAT(MIN(t.DepartureTime), '%H:%i') AS departureLabel
FROM truck t
WHERE t.deleted = 0
AND t.DepartureTime IS NOT NULL
$storeSql
$laneSql
""".trimIndent()
val row = jdbcDao.queryForList(sql, args).firstOrNull()
return (row?.get("departureLabel") ?: "").toString().trim()
}

fun formatStoreIdForDisplay(raw: String?): String {
if (raw.isNullOrBlank()) return ""
val normalized = raw.trim().replace("/", "")
return when (normalized.uppercase()) {
"2F" -> "2/F"
"4F" -> "4/F"
else -> raw.trim()
}
}
}

+ 66
- 0
src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/TruckRoutingSummaryController.kt Wyświetl plik

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

import com.ffii.fpsms.modules.deliveryOrder.service.TruckRoutingSummaryService
import com.ffii.fpsms.modules.report.service.ReportService
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import java.time.LocalDate
import java.time.format.DateTimeFormatter

@RestController
@RequestMapping("/truck-routing-summary")
class TruckRoutingSummaryController(
private val truckRoutingSummaryService: TruckRoutingSummaryService,
private val reportService: ReportService,
) {
@GetMapping("/store-options")
fun getStoreOptions(): List<Map<String, String>> =
truckRoutingSummaryService.getStoreOptions()

@GetMapping("/lane-options")
fun getLaneOptions(
@RequestParam(required = false) storeId: String?
): List<Map<String, String>> =
truckRoutingSummaryService.getLaneOptions(storeId)

@GetMapping("/print")
fun print(
@RequestParam(required = false) storeId: String?,
@RequestParam(required = false) truckLanceCode: String?,
@RequestParam(required = false) date: String?
): ResponseEntity<ByteArray> {
val reportDate = if (date.isNullOrBlank()) {
LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
} else {
date
}

val departureLabel = truckRoutingSummaryService.getDepartureTimeLabel(storeId, truckLanceCode)
val lane = (truckLanceCode ?: "").trim()
val params = mutableMapOf<String, Any>(
"FLOOR_LABEL" to truckRoutingSummaryService.formatStoreIdForDisplay(storeId),
"TRUCK_ROUTE" to lane,
"DEPARTURE_TIME" to departureLabel,
"REPORT_DATE" to reportDate,
)
val rows = truckRoutingSummaryService.search(storeId, truckLanceCode, reportDate)
val pdfBytes = reportService.createPdfResponse(
"/DeliveryNote/TruckRoutingSummaryPDF.jrxml",
params,
rows
)

val headers = HttpHeaders().apply {
contentType = MediaType.APPLICATION_PDF
setContentDispositionFormData("attachment", "TruckRoutingSummary.pdf")
set("filename", "TruckRoutingSummary.pdf")
}
return ResponseEntity(pdfBytes, headers, HttpStatus.OK)
}
}

+ 169
- 0
src/main/resources/DeliveryNote/TruckRoutingSummaryPDF.jrxml Wyświetl plik

@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.21.3.final using JasperReports Library version 6.21.3-4a3078d20785ebe464f18037d738d12fc98c13cf -->
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="TruckRoutingSummaryPDF" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="7d4d8f47-32ad-4c63-80ac-3df3f8492c62">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/>
<parameter name="TRUCK_ROUTE" class="java.lang.String"/>
<parameter name="PLAN_TRUCK_SCHEDULE" class="java.lang.String"/>
<parameter name="DEPARTURE_TIME" class="java.lang.String"/>
<parameter name="REPORT_DATE" class="java.lang.String"/>
<field name="dropOffSequence" class="java.lang.String"/>
<field name="shopCode" class="java.lang.String"/>
<field name="shopName" class="java.lang.String"/>
<field name="address" class="java.lang.String"/>
<field name="noOfCartons" class="java.lang.String"/>
<title>
<band height="28">
<staticText>
<reportElement x="0" y="0" width="555" height="24" uuid="c1d2c147-cf58-41e6-9214-3f8251dd8aa5"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="16" isBold="true"/>
</textElement>
<text><![CDATA[送貨路線摘要]]></text>
</staticText>
</band>
</title>
<pageHeader>
<band height="25">
<staticText>
<reportElement x="0" y="0" width="60" height="20" uuid="117504db-1b66-4838-a84b-1b0e5a9245cc"/>
<textElement verticalAlignment="Middle">
<font fontName="微軟正黑體" size="11" isBold="true"/>
</textElement>
<text><![CDATA[送貨路線:]]></text>
</staticText>
<textField>
<reportElement x="60" y="0" width="130" height="20" uuid="71f86ded-88e6-4ab7-a62d-b9c7de8b6c37"/>
<textElement verticalAlignment="Middle">
<font fontName="微軟正黑體" size="11"/>
</textElement>
<textFieldExpression><![CDATA[$P{TRUCK_ROUTE}]]></textFieldExpression>
</textField>
<staticText>
<reportElement x="200" y="0" width="110" height="20" uuid="9d3f5b73-ceaa-4653-909f-e8534d19c61e"/>
<textElement verticalAlignment="Middle">
<font fontName="微軟正黑體" size="11" isBold="true"/>
</textElement>
<text><![CDATA[計劃車次出發時間:]]></text>
</staticText>
<textField>
<reportElement x="310" y="0" width="110" height="20" uuid="92335393-c410-4935-bd28-29a6175a9769"/>
<textElement verticalAlignment="Middle">
<font fontName="微軟正黑體" size="11"/>
</textElement>
<textFieldExpression><![CDATA[$P{DEPARTURE_TIME}]]></textFieldExpression>
</textField>
<staticText>
<reportElement x="430" y="0" width="40" height="20" uuid="8770a6e7-8a03-47ab-aa3c-00f02815d3b4"/>
<textElement verticalAlignment="Middle">
<font fontName="微軟正黑體" size="11" isBold="true"/>
</textElement>
<text><![CDATA[日期:]]></text>
</staticText>
<textField>
<reportElement x="470" y="0" width="85" height="20" uuid="1a628742-c50c-47a8-9f3d-df91dbc4b184"/>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="11"/>
</textElement>
<textFieldExpression><![CDATA[$P{REPORT_DATE}]]></textFieldExpression>
</textField>
<line>
<reportElement x="0" y="20" width="555" height="1" uuid="593aa99a-7978-473d-b70f-93f79fb64289"/>
</line>
</band>
</pageHeader>
<columnHeader>
<band height="24">
<staticText>
<reportElement x="0" y="4" width="60" height="18" uuid="7dbf4192-d9d9-4f3e-95bc-d2700d4e5798"/>
<textElement verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10" isBold="true"/>
</textElement>
<text><![CDATA[卸貨順序]]></text>
</staticText>
<staticText>
<reportElement x="60" y="4" width="50" height="18" uuid="9c31b1d9-d866-4555-9ee9-57b924ff2540"/>
<textElement verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10" isBold="true"/>
</textElement>
<text><![CDATA[店鋪代碼]]></text>
</staticText>
<staticText>
<reportElement x="110" y="4" width="130" height="18" uuid="e7d49961-b1c8-40b0-a109-29da1142fc8d"/>
<textElement verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10" isBold="true"/>
</textElement>
<text><![CDATA[店鋪名稱]]></text>
</staticText>
<staticText>
<reportElement x="240" y="4" width="260" height="18" uuid="d2538a2b-ebbb-4cbb-a6c1-51249b831afe"/>
<textElement verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10" isBold="true"/>
</textElement>
<text><![CDATA[地址]]></text>
</staticText>
<staticText>
<reportElement x="500" y="4" width="54" height="18" uuid="8473f6ea-a5bd-4739-bc05-618c0afb06d2"/>
<textElement textAlignment="Right" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10" isBold="true"/>
</textElement>
<text><![CDATA[箱數]]></text>
</staticText>
<line>
<reportElement x="0" y="23" width="555" height="1" uuid="a370b2d2-4853-460a-900a-a15d2e1b8e94"/>
</line>
</band>
</columnHeader>
<detail>
<band height="20">
<textField isBlankWhenNull="true">
<reportElement x="0" y="2" width="60" height="16" uuid="31c8d1cf-9298-4866-9dca-d5bbaa08b277"/>
<textElement verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<textFieldExpression><![CDATA[$F{dropOffSequence}]]></textFieldExpression>
</textField>
<textField isBlankWhenNull="true">
<reportElement x="60" y="2" width="50" height="16" uuid="f4ed6642-ce1c-4130-bf80-1024c5453db4"/>
<textElement verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<textFieldExpression><![CDATA[$F{shopCode}]]></textFieldExpression>
</textField>
<textField isBlankWhenNull="true">
<reportElement x="110" y="2" width="130" height="16" uuid="a44a3df4-a77f-4dda-8b82-d77b47e56eaf"/>
<textElement verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<textFieldExpression><![CDATA[$F{shopName}]]></textFieldExpression>
</textField>
<textField isBlankWhenNull="true">
<reportElement x="240" y="2" width="260" height="16" uuid="553b201d-910f-40d9-aea3-711852ebff59"/>
<textElement verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<textFieldExpression><![CDATA[$F{address}]]></textFieldExpression>
</textField>
<textField isBlankWhenNull="true">
<reportElement x="500" y="2" width="54" height="16" uuid="ff0c3947-9dd6-48eb-8ba9-83e47b7cd8e1"/>
<textElement textAlignment="Right" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<textFieldExpression><![CDATA[$F{noOfCartons}]]></textFieldExpression>
</textField>
</band>
</detail>
<pageFooter>
<band height="24">
<line>
<reportElement x="0" y="0" width="555" height="1" uuid="de87272d-679e-4890-8c9c-c783bd687f9c"/>
</line>
<textField>
<reportElement x="0" y="6" width="555" height="16" uuid="c5cacb11-0b81-4a67-b3c5-c7593d2f3270"/>
<textElement textAlignment="Right" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="9"/>
</textElement>
<textFieldExpression><![CDATA["第 " + $V{PAGE_NUMBER} + " 頁"]]></textFieldExpression>
</textField>
</band>
</pageFooter>
</jasperReport>

Ładowanie…
Anuluj
Zapisz