CANCERYS\kw093 7 часов назад
Родитель
Сommit
7606c052e3
3 измененных файлов: 253 добавлений и 42 удалений
  1. +204
    -0
      src/main/java/com/ffii/fpsms/modules/report/service/ReportService.kt
  2. +23
    -23
      src/main/java/com/ffii/fpsms/modules/report/web/ReportController.kt
  3. +26
    -19
      src/main/resources/jasper/FGDeliveryReport.jrxml

+ 204
- 0
src/main/java/com/ffii/fpsms/modules/report/service/ReportService.kt Просмотреть файл

@@ -72,7 +72,211 @@ open class ReportService(
return jdbcDao.queryForList(sql, args)
}
fun searchFGDeliveryReport(
stockCategory: String?,
stockSubCategory: String?,
itemCode: String?,
year: String?,
lastOutDateStart: String?,
lastOutDateEnd: String?
): List<Map<String, Any>> {
val args = mutableMapOf<String, Any>()
// Stock Category 过滤:通过 qc_category.code 或 qc_category.name
val stockCategorySql = if (!stockCategory.isNullOrBlank()) {
val categories = stockCategory.split(",").map { it.trim() }.filter { it.isNotBlank() }
if (categories.isNotEmpty()) {
val conditions = categories.mapIndexed { index, cat ->
val paramName = "stockCategory_$index"
args[paramName] = "%$cat%"
"(qc.code LIKE :$paramName OR qc.name LIKE :$paramName)"
}
"AND (${conditions.joinToString(" OR ")})"
} else {
""
}
} else {
""
}
// 修正:stockSubCategory 也过滤 qc_category.name(而不是 item_category.sub)
val stockSubCategorySql = if (!stockSubCategory.isNullOrBlank()) {
val values = stockSubCategory.split(",").map { it.trim() }.filter { it.isNotBlank() }
if (values.isNotEmpty()) {
val conditions = values.mapIndexed { index, value ->
val paramName = "stockSubCategory_$index"
args[paramName] = "%$value%"
"qc.name LIKE :$paramName"
}
"AND (${conditions.joinToString(" OR ")})"
} else {
""
}
} else {
""
}
val itemCodeSql = buildMultiValueLikeClause(itemCode, "it.code", "itemCode", args)
val yearSql = if (!year.isNullOrBlank()) {
args["year"] = year
"AND YEAR(IFNULL(dpor.RequiredDeliveryDate, do.estimatedArrivalDate)) = :year"
} else {
""
}
val lastOutDateStartSql = if (!lastOutDateStart.isNullOrBlank()) {
args["lastOutDateStart"] = lastOutDateStart
"AND DATE(IFNULL(dpor.RequiredDeliveryDate, do.estimatedArrivalDate)) >= :lastOutDateStart"
} else ""
val lastOutDateEndSql = if (!lastOutDateEnd.isNullOrBlank()) {
args["lastOutDateEnd"] = lastOutDateEnd
"AND DATE(IFNULL(dpor.RequiredDeliveryDate, do.estimatedArrivalDate)) < :lastOutDateEnd"
} else ""
val sql = """
SELECT
IFNULL(DATE_FORMAT(
IFNULL(dpor.RequiredDeliveryDate, do.estimatedArrivalDate),
'%Y-%m-%d'
), '') AS deliveryDate,
IFNULL(it.code, '') AS itemNo,
IFNULL(it.name, '') AS itemName,
IFNULL(uc.udfudesc, '') AS unitOfMeasure,
IFNULL(sil.dnNo, '') AS dnNo,
CAST(IFNULL(sp.id, 0) AS CHAR) AS customerId,
IFNULL(sp.name, '') AS customerName,
CAST(
SUM(IFNULL(IFNULL(sol.qty, dol.qty), 0)) OVER (
PARTITION BY it.code
) AS DECIMAL(14,2)
) AS qtyNumeric,

CAST(ROUND(IFNULL(IFNULL(sol.qty, dol.qty), 0), 2) AS CHAR) AS qty,
COALESCE(
dpor.TruckLanceCode,
(SELECT t2.TruckLanceCode
FROM truck t2
WHERE t2.shopId = do.shopId
AND t2.deleted = 0
AND t2.Store_id = CASE
WHEN supplier.code = 'P06B' THEN '4F'
ELSE '2F'
END
AND (
(CASE WHEN supplier.code = 'P06B' THEN '4F' ELSE '2F' END = '4F'
AND (SELECT COUNT(*) FROM truck t3
WHERE t3.shopId = do.shopId AND t3.deleted = 0
AND t3.Store_id = '4F') > 1
AND IFNULL(dpor.RequiredDeliveryDate, do.estimatedArrivalDate) IS NOT NULL
AND t2.TruckLanceCode LIKE CONCAT('%',
CASE DAYNAME(IFNULL(dpor.RequiredDeliveryDate, do.estimatedArrivalDate))
WHEN 'Monday' THEN 'Mon'
WHEN 'Tuesday' THEN 'Tue'
WHEN 'Wednesday' THEN 'Wed'
WHEN 'Thursday' THEN 'Thu'
WHEN 'Friday' THEN 'Fri'
WHEN 'Saturday' THEN 'Sat'
WHEN 'Sunday' THEN 'Sun'
ELSE ''
END, '%'))
OR
t2.Store_id = CASE WHEN supplier.code = 'P06B' THEN '4F' ELSE '2F' END
)
ORDER BY t2.DepartureTime ASC
LIMIT 1),
''
) AS truckNo,
'' AS driver,
IFNULL(do.code, '') AS deliveryOrderNo,
IFNULL(qc.name, '') AS stockSubCategory
FROM do_pick_order_line_record dpolr
LEFT JOIN do_pick_order_record dpor
ON dpolr.do_pick_order_id = dpor.id
AND dpor.deleted = 0
AND dpor.ticket_status = 'completed'
INNER JOIN delivery_order do
ON dpolr.do_order_id = do.id
AND do.deleted = 0
LEFT JOIN shop supplier
ON do.supplierId = supplier.id
AND supplier.deleted = 0
LEFT JOIN shop sp
ON do.shopId = sp.id
AND sp.deleted = 0
LEFT JOIN delivery_order_line dol
ON do.id = dol.deliveryOrderId
AND dol.deleted = 0
LEFT JOIN items it
ON dol.itemId = it.id
AND it.deleted = 0
LEFT JOIN items_qc_category_mapping iqcm
ON it.id = iqcm.itemId
LEFT JOIN qc_category qc
ON iqcm.qcCategoryId = qc.id
AND qc.deleted = 0
LEFT JOIN item_category ic
ON it.categoryId = ic.id
LEFT JOIN item_uom iu
ON it.id = iu.itemId
AND iu.stockUnit = 1
LEFT JOIN uom_conversion uc
ON iu.uomId = uc.id
LEFT JOIN pick_order_line pol
ON dpolr.pick_order_id = pol.poId
AND pol.itemId = it.id
AND pol.deleted = 0
LEFT JOIN stock_out_line sol
ON pol.id = sol.pickOrderLineId
AND sol.itemId = it.id
AND sol.deleted = 0
LEFT JOIN inventory_lot_line ill
ON sol.inventoryLotLineId = ill.id
AND ill.deleted = 0
LEFT JOIN inventory_lot il
ON ill.inventoryLotId = il.id
AND il.deleted = 0
LEFT JOIN stock_in_line sil
ON il.stockInLineId = sil.id
AND sil.deleted = 0
WHERE
dpolr.deleted = 0
AND (dpor.id IS NULL OR dpor.ticket_status = 'completed')
$stockCategorySql
$stockSubCategorySql
$itemCodeSql
$yearSql
$lastOutDateStartSql
$lastOutDateEndSql
ORDER BY
qc.name,
it.code,
IFNULL(sil.lotNo, '')
""".trimIndent()

val result = jdbcDao.queryForList(sql, args)
// 打印查询结果(前 10 行)
println("=== Query Result (Total: ${result.size} rows) ===")
result.take(50).forEachIndexed { index, row ->
println("Row $index:")
println(" deliveryDate: ${row["deliveryDate"]}")
println(" itemNo: ${row["itemNo"]}")
println(" itemName: ${row["itemName"]}")
println(" qty: ${row["qty"]}")
println(" qtyNumeric: ${row["qtyNumeric"]}")
println(" deliveryOrderNo: ${row["deliveryOrderNo"]}")
println(" stockSubCategory: ${row["stockSubCategory"]}")
println(" ---")
}
if (result.size > 50) {
println("... (showing first 10 rows, total ${result.size} rows)")
}

return result
}
/**
* Helper function to build SQL clause for comma-separated values.
* Supports multiple values like "val1, val2, val3" and generates OR conditions with LIKE.


+ 23
- 23
src/main/java/com/ffii/fpsms/modules/report/web/ReportController.kt Просмотреть файл

@@ -79,50 +79,50 @@ class ReportController(

return ResponseEntity(pdfBytes, headers, HttpStatus.OK)
}

@GetMapping("/print-stock-in-traceability")
fun generateStockInTraceabilityReport(
@GetMapping("/print-fg-delivery-report")
fun generateFGDeliveryReport(
@RequestParam(required = false) stockCategory: String?,
@RequestParam(required = false) stockSubCategory: String?,
@RequestParam(required = false) itemCode: String?,
@RequestParam(required = false) year: String?,
@RequestParam(required = false) lastInDateStart: String?,
@RequestParam(required = false) lastInDateEnd: String?
@RequestParam(required = false) lastOutDateStart: String?,
@RequestParam(required = false) lastOutDateEnd: String?
): ResponseEntity<ByteArray> {
val parameters = mutableMapOf<String, Any>()
// Set report header parameters
// 设置报表头部参数
parameters["stockCategory"] = stockCategory ?: "All"
parameters["stockSubCategory"] = stockSubCategory ?: "All"
parameters["itemNo"] = itemCode ?: "All"
parameters["year"] = year ?: LocalDate.now().year.toString()
parameters["reportDate"] = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
parameters["reportTime"] = LocalTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss"))
parameters["lastInDateStart"] = lastInDateStart ?: ""
parameters["lastInDateEnd"] = lastInDateEnd ?: ""

// Query the DB to get a list of data
val dbData = reportService.searchStockInTraceabilityReport(
stockCategory,
stockSubCategory,
itemCode,
year,
lastInDateStart,
lastInDateEnd
parameters["lastOutDateStart"] = lastOutDateStart ?: ""
parameters["lastOutDateEnd"] = lastOutDateEnd ?: ""
parameters["deliveryPeriodStart"] = ""
parameters["deliveryPeriodEnd"] = ""
val dbData = reportService.searchFGDeliveryReport(
stockCategory,
stockSubCategory,
itemCode,
year,
lastOutDateStart,
lastOutDateEnd
)
val pdfBytes = reportService.createPdfResponse(
"/jasper/StockInTraceabilityReport.jrxml",
"/jasper/FGDeliveryReport.jrxml",
parameters,
dbData
)
val headers = HttpHeaders().apply {
contentType = MediaType.APPLICATION_PDF
setContentDispositionFormData("attachment", "StockInTraceabilityReport.pdf")
set("filename", "StockInTraceabilityReport.pdf")
setContentDispositionFormData("attachment", "FGDeliveryReport.pdf")
set("filename", "FGDeliveryReport.pdf")
}
return ResponseEntity(pdfBytes, headers, HttpStatus.OK)
}



+ 26
- 19
src/main/resources/jasper/FGDeliveryReport.jrxml Просмотреть файл

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.21.3.final using JasperReports Library version 5.5.2 -->
<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="FGStockOutTraceabilityReport" pageWidth="842" pageHeight="595" orientation="Landscape" whenNoDataType="AllSectionsNoDetail" columnWidth="802" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="c40e235b-365d-48a0-a1b8-a8e0ece2cdd3">
<!-- Created with Jaspersoft Studio version 6.17.0.final using JasperReports Library version 6.17.0-6d93193241dd8cc42629e188b94f9e0bc5722efd -->
<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="FGStockOutTraceabilityReport" pageWidth="842" pageHeight="595" orientation="Landscape" columnWidth="802" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="c40e235b-365d-48a0-a1b8-a8e0ece2cdd3">
<property name="com.jaspersoft.studio.unit." value="pixel"/>
<property name="com.jaspersoft.studio.unit.pageHeight" value="pixel"/>
<property name="com.jaspersoft.studio.unit.pageWidth" value="pixel"/>
@@ -10,33 +10,32 @@
<property name="com.jaspersoft.studio.unit.rightMargin" value="pixel"/>
<property name="com.jaspersoft.studio.unit.columnWidth" value="pixel"/>
<property name="com.jaspersoft.studio.unit.columnSpacing" value="pixel"/>
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/>
<subDataset name="Dataset1" uuid="dfaf2f9f-3937-4f84-9b1f-fd0ecf2f1ee9">
<queryString>
<![CDATA[]]>
</queryString>
</subDataset>
<parameter name="stockSubCategory" class="java.lang.String" isForPrompting="false">
<parameter name="stockSubCategory" class="java.lang.String">
<defaultValueExpression><![CDATA["stockSubCategory"]]></defaultValueExpression>
</parameter>
<parameter name="date" class="java.lang.String" isForPrompting="false">
<parameter name="date" class="java.lang.String">
<defaultValueExpression><![CDATA["date"]]></defaultValueExpression>
</parameter>
<parameter name="stockCategory" class="java.lang.String" isForPrompting="false">
<parameter name="stockCategory" class="java.lang.String">
<defaultValueExpression><![CDATA["stockCategory"]]></defaultValueExpression>
</parameter>
<parameter name="reportDate" class="java.lang.String" isForPrompting="false"/>
<parameter name="reportTime" class="java.lang.String" isForPrompting="false"/>
<parameter name="deliveryPeriodStart" class="java.lang.String" isForPrompting="false"/>
<parameter name="deliveryPeriodEnd" class="java.lang.String" isForPrompting="false"/>
<parameter name="year" class="java.lang.String" isForPrompting="false"/>
<parameter name="itemNo" class="java.lang.String" isForPrompting="false">
<parameter name="reportDate" class="java.lang.String"/>
<parameter name="reportTime" class="java.lang.String"/>
<parameter name="deliveryPeriodStart" class="java.lang.String"/>
<parameter name="deliveryPeriodEnd" class="java.lang.String"/>
<parameter name="year" class="java.lang.String"/>
<parameter name="itemNo" class="java.lang.String">
<defaultValueExpression><![CDATA["itemCode"]]></defaultValueExpression>
</parameter>
<parameter name="lastOutDateStart" class="java.lang.String" isForPrompting="false">
<parameter name="lastOutDateStart" class="java.lang.String">
<parameterDescription><![CDATA["lastOutDateStart"]]></parameterDescription>
</parameter>
<parameter name="lastOutDateEnd" class="java.lang.String" isForPrompting="false">
<parameter name="lastOutDateEnd" class="java.lang.String">
<parameterDescription><![CDATA["lastOutDateStart"]]></parameterDescription>
</parameter>
<queryString>
@@ -60,13 +59,21 @@
<field name="customerId" class="java.lang.String"/>
<field name="customerName" class="java.lang.String"/>
<field name="qty" class="java.lang.String"/>
<field name="qtyNumeric" class="java.math.BigDecimal"/>
<field name="truckNo" class="java.lang.String"/>
<field name="driver" class="java.lang.String"/>
<field name="deliveryOrderNo" class="java.lang.String"/>
<field name="stockSubCategory" class="java.lang.String"/>
<variable name="totalDeliveredQtyPerDeliveryOrder" class="java.lang.String" incrementType="Group" incrementGroup="qty" calculation="Sum"/>
<group name="qty">
<groupExpression><![CDATA[$F{qty}]]></groupExpression>
<variable name="totalDeliveredQtyPerDeliveryOrder" class="java.math.BigDecimal"
incrementType="Group"
incrementGroup="itemGroup"
calculation="First"
resetType="Group"
resetGroup="itemGroup">
<variableExpression><![CDATA[$F{qtyNumeric}]]></variableExpression>
</variable>
<group name="itemGroup">
<groupExpression><![CDATA[$F{itemNo}]]></groupExpression>
<groupHeader>
<band height="69">
<textField>
@@ -260,7 +267,7 @@
<textElement textAlignment="Right">
<font fontName="微軟正黑體" size="10" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA[$V{totalDeliveredQtyPerDeliveryOrder}]]></textFieldExpression>
<textFieldExpression><![CDATA[$F{qtyNumeric} != null ? $F{qtyNumeric}.toString() : "0.00"]]></textFieldExpression>
</textField>
<line>
<reportElement x="0" y="23" width="799" height="1" uuid="a7505f85-e928-4098-b9ba-644111766b84">
@@ -310,7 +317,7 @@
<property name="com.jaspersoft.studio.unit.y" value="px"/>
<property name="com.jaspersoft.studio.unit.height" value="px"/>
</reportElement>
<textElement textAlignment="Center" verticalAlignment="Top">
<textElement textAlignment="Center" verticalAlignment="Justified">
<font fontName="微軟正黑體" size="12"/>
</textElement>
<text><![CDATA[/]]></text>


Загрузка…
Отмена
Сохранить