瀏覽代碼

Stock Item Consumption Trend Report

master
B.E.N.S.O.N 3 小時之前
父節點
當前提交
95ddc8d077
共有 5 個檔案被更改,包括 1293 行新增0 行删除
  1. +256
    -0
      src/main/java/com/ffii/fpsms/modules/report/service/SemiFGProductionAnalysisReportService.kt
  2. +226
    -0
      src/main/java/com/ffii/fpsms/modules/report/service/StockItemConsumptionTrendReportService.kt
  3. +82
    -0
      src/main/java/com/ffii/fpsms/modules/report/web/SemiFGProductionAnalysisReportController.kt
  4. +79
    -0
      src/main/java/com/ffii/fpsms/modules/report/web/StockItemConsumptionTrendReportController.kt
  5. +650
    -0
      src/main/resources/jasper/StockItemConsumptionTrendReport.jrxml

+ 256
- 0
src/main/java/com/ffii/fpsms/modules/report/service/SemiFGProductionAnalysisReportService.kt 查看文件

@@ -0,0 +1,256 @@
package com.ffii.fpsms.modules.report.service

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

@Service
class SemiFGProductionAnalysisReportService(
private val jdbcDao: JdbcDao,
) {
/**
* Helper function to build SQL clause for comma-separated values.
* Supports multiple values like "val1, val2, val3" and generates OR conditions with LIKE.
*/
private fun buildMultiValueLikeClause(
paramValue: String?,
columnName: String,
paramPrefix: String,
args: MutableMap<String, Any>
): String {
if (paramValue.isNullOrBlank()) return ""
val values = paramValue.split(",").map { it.trim() }.filter { it.isNotBlank() }
if (values.isEmpty()) return ""
val conditions = values.mapIndexed { index, value ->
val paramName = "${paramPrefix}_$index"
args[paramName] = "%$value%"
"$columnName LIKE :$paramName"
}
return "AND (${conditions.joinToString(" OR ")})"
}

/**
* Helper function to build SQL clause for comma-separated values with exact match.
* Supports multiple values like "val1, val2, val3" and generates OR conditions with =.
*/
private fun buildMultiValueExactClause(
paramValue: String?,
columnName: String,
paramPrefix: String,
args: MutableMap<String, Any>
): String {
if (paramValue.isNullOrBlank()) return ""
val values = paramValue.split(",").map { it.trim() }.filter { it.isNotBlank() }
if (values.isEmpty()) return ""
val conditions = values.mapIndexed { index, value ->
val paramName = "${paramPrefix}_$index"
args[paramName] = value
"$columnName = :$paramName"
}
return "AND (${conditions.joinToString(" OR ")})"
}

/**
* Queries the database for Semi FG Production Analysis Report data.
* Flow:
* 1. Filter bom by description (FG/WIP) to get bom.code values
* 2. Match bom.code with stock_ledger.itemCode
* 3. Aggregate stock_ledger data by month for each item based on inQty
* Supports comma-separated values for stockCategory, stockSubCategory, and itemCode.
*/
fun searchSemiFGProductionAnalysisReport(
stockCategory: String?,
stockSubCategory: String?,
itemCode: String?,
year: String?,
lastOutDateStart: String?,
lastOutDateEnd: String?
): List<Map<String, Any>> {
val args = mutableMapOf<String, Any>()
// Filter by stockCategory from bom.description (FG/WIP) - this finds which bom.code values match
// Supports multiple categories separated by comma (e.g., "FG,WIP")
// If "All" is selected or contains "All", don't filter by description
val stockCategorySql = if (!itemCode.isNullOrBlank()) {
// When itemCode is provided, skip stockCategory filter
""
} else if (!stockCategory.isNullOrBlank() && stockCategory != "All" && !stockCategory.contains("All")) {
// Handle multiple categories (comma-separated)
val categories = stockCategory.split(",").map { it.trim() }.filter { it.isNotBlank() && it != "All" }
if (categories.isNotEmpty()) {
val conditions = categories.mapIndexed { index, cat ->
val paramName = "stockCategory_$index"
args[paramName] = cat
"b.description = :$paramName"
}
"AND (${conditions.joinToString(" OR ")})"
} else {
""
}
} else {
""
}
val stockSubCategorySql = buildMultiValueLikeClause(stockSubCategory, "ic.sub", "stockSubCategory", args)
// Filter by itemCode - match bom.code (user input should match bom.code, which then matches stock_ledger.itemCode)
val itemCodeSql = buildMultiValueExactClause(itemCode, "b.code", "itemCode", args)
val yearSql = if (!year.isNullOrBlank()) {
args["year"] = year
"AND YEAR(sl.modified) = :year"
} else {
""
}
val lastOutDateStartSql = if (!lastOutDateStart.isNullOrBlank()) {
args["lastOutDateStart"] = lastOutDateStart
"AND DATE(sl.modified) >= :lastOutDateStart"
} else ""
val lastOutDateEndSql = if (!lastOutDateEnd.isNullOrBlank()) {
args["lastOutDateEnd"] = lastOutDateEnd
"AND DATE(sl.modified) < :lastOutDateEnd"
} else ""

val sql = """
SELECT
COALESCE(ic.sub, '') as stockSubCategory,
COALESCE(sl.itemCode, '') as itemNo,
COALESCE(b.name, '') as itemName,
COALESCE(uc.code, '') as unitOfMeasure,
CAST(COALESCE(SUM(CASE WHEN MONTH(sl.modified) = 1 THEN sl.inQty ELSE 0 END), 0) AS DECIMAL(18,2)) as qtyJan,
CAST(COALESCE(SUM(CASE WHEN MONTH(sl.modified) = 2 THEN sl.inQty ELSE 0 END), 0) AS DECIMAL(18,2)) as qtyFeb,
CAST(COALESCE(SUM(CASE WHEN MONTH(sl.modified) = 3 THEN sl.inQty ELSE 0 END), 0) AS DECIMAL(18,2)) as qtyMar,
CAST(COALESCE(SUM(CASE WHEN MONTH(sl.modified) = 4 THEN sl.inQty ELSE 0 END), 0) AS DECIMAL(18,2)) as qtyApr,
CAST(COALESCE(SUM(CASE WHEN MONTH(sl.modified) = 5 THEN sl.inQty ELSE 0 END), 0) AS DECIMAL(18,2)) as qtyMay,
CAST(COALESCE(SUM(CASE WHEN MONTH(sl.modified) = 6 THEN sl.inQty ELSE 0 END), 0) AS DECIMAL(18,2)) as qtyJun,
CAST(COALESCE(SUM(CASE WHEN MONTH(sl.modified) = 7 THEN sl.inQty ELSE 0 END), 0) AS DECIMAL(18,2)) as qtyJul,
CAST(COALESCE(SUM(CASE WHEN MONTH(sl.modified) = 8 THEN sl.inQty ELSE 0 END), 0) AS DECIMAL(18,2)) as qtyAug,
CAST(COALESCE(SUM(CASE WHEN MONTH(sl.modified) = 9 THEN sl.inQty ELSE 0 END), 0) AS DECIMAL(18,2)) as qtySep,
CAST(COALESCE(SUM(CASE WHEN MONTH(sl.modified) = 10 THEN sl.inQty ELSE 0 END), 0) AS DECIMAL(18,2)) as qtyOct,
CAST(COALESCE(SUM(CASE WHEN MONTH(sl.modified) = 11 THEN sl.inQty ELSE 0 END), 0) AS DECIMAL(18,2)) as qtyNov,
CAST(COALESCE(SUM(CASE WHEN MONTH(sl.modified) = 12 THEN sl.inQty ELSE 0 END), 0) AS DECIMAL(18,2)) as qtyDec,
CAST(COALESCE(SUM(sl.inQty), 0) AS CHAR) as totalProductionQty
FROM stock_ledger sl
INNER JOIN bom b ON sl.itemCode = b.code AND b.deleted = false
LEFT JOIN items it ON sl.itemId = it.id
LEFT JOIN item_category ic ON it.categoryId = ic.id
LEFT JOIN item_uom iu ON it.id = iu.itemId AND iu.stockUnit = true
LEFT JOIN uom_conversion uc ON iu.uomId = uc.id
WHERE sl.deleted = false
AND sl.inQty IS NOT NULL
AND sl.inQty > 0
$stockCategorySql
$stockSubCategorySql
$itemCodeSql
$yearSql
$lastOutDateStartSql
$lastOutDateEndSql
GROUP BY sl.itemCode, ic.sub, it.id, b.name, uc.code, b.description
ORDER BY ic.sub, sl.itemCode
""".trimIndent()
return jdbcDao.queryForList(sql, args)
}

/**
* Gets list of item codes (bom.code) with names based on stockCategory filter.
* Supports multiple categories separated by comma (e.g., "FG,WIP").
* If stockCategory is "All" or null, returns all codes.
* If stockCategory is "FG" or "WIP" or "FG,WIP", returns codes matching those descriptions.
* Returns a list of maps with "code" and "name" keys.
*/
fun getSemiFGItemCodes(stockCategory: String?): List<Map<String, String>> {
val args = mutableMapOf<String, Any>()
val stockCategorySql = if (!stockCategory.isNullOrBlank() && stockCategory != "All" && !stockCategory.contains("All")) {
// Handle multiple categories (comma-separated)
val categories = stockCategory.split(",").map { it.trim() }.filter { it.isNotBlank() && it != "All" }
if (categories.isNotEmpty()) {
val conditions = categories.mapIndexed { index, cat ->
val paramName = "stockCategory_$index"
args[paramName] = cat
"b.description = :$paramName"
}
"AND (${conditions.joinToString(" OR ")})"
} else {
""
}
} else {
""
}

val sql = """
SELECT DISTINCT b.code, COALESCE(b.name, '') as name
FROM bom b
WHERE b.deleted = false
AND b.code IS NOT NULL
AND b.code != ''
$stockCategorySql
ORDER BY b.code
""".trimIndent()
val results = jdbcDao.queryForList(sql, args)
return results.mapNotNull {
val code = it["code"]?.toString()
val name = it["name"]?.toString() ?: ""
if (code != null) {
mapOf("code" to code, "name" to name)
} else {
null
}
}
}

/**
* Gets list of item codes with their category (FG/WIP) and name based on stockCategory filter.
* Supports multiple categories separated by comma (e.g., "FG,WIP").
* Returns a list of maps with "code", "category", and "name" keys.
*/
fun getSemiFGItemCodesWithCategory(stockCategory: String?): List<Map<String, String>> {
val args = mutableMapOf<String, Any>()
val stockCategorySql = if (!stockCategory.isNullOrBlank() && stockCategory != "All" && !stockCategory.contains("All")) {
// Handle multiple categories (comma-separated)
val categories = stockCategory.split(",").map { it.trim() }.filter { it.isNotBlank() && it != "All" }
if (categories.isNotEmpty()) {
val conditions = categories.mapIndexed { index, cat ->
val paramName = "stockCategory_$index"
args[paramName] = cat
"b.description = :$paramName"
}
"AND (${conditions.joinToString(" OR ")})"
} else {
""
}
} else {
""
}

val sql = """
SELECT DISTINCT b.code, COALESCE(b.description, '') as category, COALESCE(b.name, '') as name
FROM bom b
WHERE b.deleted = false
AND b.code IS NOT NULL
AND b.code != ''
$stockCategorySql
ORDER BY b.code
""".trimIndent()
val results = jdbcDao.queryForList(sql, args)
return results.mapNotNull {
val code = it["code"]?.toString()
val category = it["category"]?.toString() ?: ""
val name = it["name"]?.toString() ?: ""
if (code != null) {
mapOf("code" to code, "category" to category, "name" to name)
} else {
null
}
}
}
}

+ 226
- 0
src/main/java/com/ffii/fpsms/modules/report/service/StockItemConsumptionTrendReportService.kt 查看文件

@@ -0,0 +1,226 @@
package com.ffii.fpsms.modules.report.service

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

@Service
class StockItemConsumptionTrendReportService(
private val jdbcDao: JdbcDao,
) {
/**
* Helper function to build SQL clause for comma-separated values.
* Supports multiple values like "val1, val2, val3" and generates OR conditions with LIKE.
*/
private fun buildMultiValueLikeClause(
paramValue: String?,
columnName: String,
paramPrefix: String,
args: MutableMap<String, Any>
): String {
if (paramValue.isNullOrBlank()) return ""
val values = paramValue.split(",").map { it.trim() }.filter { it.isNotBlank() }
if (values.isEmpty()) return ""
val conditions = values.mapIndexed { index, value ->
val paramName = "${paramPrefix}_$index"
args[paramName] = "%$value%"
"$columnName LIKE :$paramName"
}
return "AND (${conditions.joinToString(" OR ")})"
}

/**
* Helper function to build SQL clause for comma-separated values with exact match.
* Supports multiple values like "val1, val2, val3" and generates OR conditions with =.
*/
private fun buildMultiValueExactClause(
paramValue: String?,
columnName: String,
paramPrefix: String,
args: MutableMap<String, Any>
): String {
if (paramValue.isNullOrBlank()) return ""
val values = paramValue.split(",").map { it.trim() }.filter { it.isNotBlank() }
if (values.isEmpty()) return ""
val conditions = values.mapIndexed { index, value ->
val paramName = "${paramPrefix}_$index"
args[paramName] = value
"$columnName = :$paramName"
}
return "AND (${conditions.joinToString(" OR ")})"
}

/**
* Queries the database for Stock Item Consumption Trend Report data.
* Flow:
* 1. Filter items by type (MAT, WIP) - this is the stockCategory filter
* 2. Use items.code to match stock_ledger.itemCode
* 3. Aggregate stock_ledger.outQty by month based on stock_ledger.modified
* Supports comma-separated values for stockCategory, stockSubCategory, and itemCode.
*/
fun searchStockItemConsumptionTrendReport(
stockCategory: String?,
itemCode: String?,
year: String?,
lastOutDateStart: String?,
lastOutDateEnd: String?
): List<Map<String, Any>> {
val args = mutableMapOf<String, Any>()
// Filter by stockCategory from items.type (MAT/WIP/NM/FG/CMB)
// Supports multiple categories separated by comma (e.g., "MAT,WIP,NM")
// Valid categories: MAT, WIP, NM, FG, CMB
// If "All" is selected or empty, show all valid categories
// If specific categories are selected, show only those
val validCategories = setOf("MAT", "WIP", "NM", "FG", "CMB")
val stockCategorySql = if (!stockCategory.isNullOrBlank() && stockCategory != "All" && !stockCategory.contains("All")) {
// Handle multiple categories (comma-separated)
val categories = stockCategory.split(",").map { it.trim() }.filter { it.isNotBlank() && it != "All" && validCategories.contains(it) }
if (categories.isNotEmpty()) {
val conditions = categories.mapIndexed { index, cat ->
val paramName = "stockCategory_$index"
args[paramName] = cat
"it.type = :$paramName"
}
"AND (${conditions.joinToString(" OR ")})"
} else {
// If no valid categories, default to all valid categories
"AND (it.type = 'MAT' OR it.type = 'WIP' OR it.type = 'NM' OR it.type = 'FG' OR it.type = 'CMB')"
}
} else {
// If "All" or empty, filter to all valid categories
"AND (it.type = 'MAT' OR it.type = 'WIP' OR it.type = 'NM' OR it.type = 'FG' OR it.type = 'CMB')"
}
// itemCode now contains prefixes (first 2 letters), so we use LIKE to match codes starting with those prefixes
val itemCodeSql = if (!itemCode.isNullOrBlank()) {
val prefixes = itemCode.split(",").map { it.trim() }.filter { it.isNotBlank() }
if (prefixes.isNotEmpty()) {
val conditions = prefixes.mapIndexed { index, prefix ->
val paramName = "itemCode_$index"
args[paramName] = "$prefix%"
"it.code LIKE :$paramName"
}
"AND (${conditions.joinToString(" OR ")})"
} else {
""
}
} else {
""
}
val yearSql = if (!year.isNullOrBlank()) {
args["year"] = year
"AND YEAR(sl.modified) = :year"
} else {
""
}
val lastOutDateStartSql = if (!lastOutDateStart.isNullOrBlank()) {
args["lastOutDateStart"] = lastOutDateStart
"AND DATE(sl.modified) >= :lastOutDateStart"
} else ""
val lastOutDateEndSql = if (!lastOutDateEnd.isNullOrBlank()) {
args["lastOutDateEnd"] = lastOutDateEnd
"AND DATE(sl.modified) < :lastOutDateEnd"
} else ""

val sql = """
SELECT
COALESCE(ic.sub, '') as stockSubCategory,
COALESCE(it.code, '') as itemNo,
COALESCE(it.name, '') as itemName,
COALESCE(uc.code, '') as unitOfMeasure,
CAST(COALESCE(SUM(CASE WHEN MONTH(sl.modified) = 1 THEN COALESCE(sl.outQty, 0) ELSE 0 END), 0) AS DECIMAL(18,2)) as qtyJan,
CAST(COALESCE(SUM(CASE WHEN MONTH(sl.modified) = 2 THEN COALESCE(sl.outQty, 0) ELSE 0 END), 0) AS DECIMAL(18,2)) as qtyFeb,
CAST(COALESCE(SUM(CASE WHEN MONTH(sl.modified) = 3 THEN COALESCE(sl.outQty, 0) ELSE 0 END), 0) AS DECIMAL(18,2)) as qtyMar,
CAST(COALESCE(SUM(CASE WHEN MONTH(sl.modified) = 4 THEN COALESCE(sl.outQty, 0) ELSE 0 END), 0) AS DECIMAL(18,2)) as qtyApr,
CAST(COALESCE(SUM(CASE WHEN MONTH(sl.modified) = 5 THEN COALESCE(sl.outQty, 0) ELSE 0 END), 0) AS DECIMAL(18,2)) as qtyMay,
CAST(COALESCE(SUM(CASE WHEN MONTH(sl.modified) = 6 THEN COALESCE(sl.outQty, 0) ELSE 0 END), 0) AS DECIMAL(18,2)) as qtyJun,
CAST(COALESCE(SUM(CASE WHEN MONTH(sl.modified) = 7 THEN COALESCE(sl.outQty, 0) ELSE 0 END), 0) AS DECIMAL(18,2)) as qtyJul,
CAST(COALESCE(SUM(CASE WHEN MONTH(sl.modified) = 8 THEN COALESCE(sl.outQty, 0) ELSE 0 END), 0) AS DECIMAL(18,2)) as qtyAug,
CAST(COALESCE(SUM(CASE WHEN MONTH(sl.modified) = 9 THEN COALESCE(sl.outQty, 0) ELSE 0 END), 0) AS DECIMAL(18,2)) as qtySep,
CAST(COALESCE(SUM(CASE WHEN MONTH(sl.modified) = 10 THEN COALESCE(sl.outQty, 0) ELSE 0 END), 0) AS DECIMAL(18,2)) as qtyOct,
CAST(COALESCE(SUM(CASE WHEN MONTH(sl.modified) = 11 THEN COALESCE(sl.outQty, 0) ELSE 0 END), 0) AS DECIMAL(18,2)) as qtyNov,
CAST(COALESCE(SUM(CASE WHEN MONTH(sl.modified) = 12 THEN COALESCE(sl.outQty, 0) ELSE 0 END), 0) AS DECIMAL(18,2)) as qtyDec,
CAST(COALESCE(SUM(COALESCE(sl.outQty, 0)), 0) AS CHAR) as totalProductionQty
FROM items it
INNER JOIN stock_ledger sl ON it.code = sl.itemCode
LEFT JOIN item_category ic ON it.categoryId = ic.id
LEFT JOIN item_uom iu ON it.id = iu.itemId AND iu.stockUnit = true
LEFT JOIN uom_conversion uc ON iu.uomId = uc.id
WHERE it.deleted = false
AND sl.deleted = false
AND sl.itemCode IS NOT NULL
AND sl.itemCode != ''
AND COALESCE(sl.outQty, 0) > 0
$stockCategorySql
$itemCodeSql
$yearSql
$lastOutDateStartSql
$lastOutDateEndSql
GROUP BY it.id, ic.sub, it.code, it.name, it.description, uc.code
ORDER BY ic.sub, it.code
""".trimIndent()
return jdbcDao.queryForList(sql, args)
}

/**
* Gets list of item code prefixes (first 2 letters) based on stockCategory filter.
* Supports multiple categories separated by comma (e.g., "MAT,WIP,NM").
* If stockCategory is "All" or null, returns prefixes for all valid categories (MAT, WIP, NM, FG, CMB).
* Returns a list of maps with "prefix" key.
*/
fun getStockItemCodePrefixes(stockCategory: String?): List<Map<String, String>> {
val args = mutableMapOf<String, Any>()
val validCategories = setOf("MAT", "WIP", "NM", "FG", "CMB")
val stockCategorySql = if (!stockCategory.isNullOrBlank() && stockCategory != "All" && !stockCategory.contains("All")) {
// Handle multiple categories (comma-separated)
val categories = stockCategory.split(",").map { it.trim() }.filter { it.isNotBlank() && it != "All" && validCategories.contains(it) }
if (categories.isNotEmpty()) {
val conditions = categories.mapIndexed { index, cat ->
val paramName = "stockCategory_$index"
args[paramName] = cat
"it.type = :$paramName"
}
"AND (${conditions.joinToString(" OR ")})"
} else {
"AND (it.type = 'MAT' OR it.type = 'WIP' OR it.type = 'NM' OR it.type = 'FG' OR it.type = 'CMB')"
}
} else {
"AND (it.type = 'MAT' OR it.type = 'WIP' OR it.type = 'NM' OR it.type = 'FG' OR it.type = 'CMB')"
}

val sql = """
SELECT DISTINCT LEFT(it.code, 2) as prefix
FROM items it
INNER JOIN stock_ledger sl ON it.code = sl.itemCode
WHERE it.deleted = false
AND sl.deleted = false
AND sl.itemCode IS NOT NULL
AND sl.itemCode != ''
AND COALESCE(sl.outQty, 0) > 0
AND LENGTH(it.code) >= 2
$stockCategorySql
ORDER BY prefix
""".trimIndent()
val results = jdbcDao.queryForList(sql, args)
return results.mapNotNull {
val prefix = it["prefix"]?.toString()
if (prefix != null && prefix.isNotBlank()) {
mapOf("prefix" to prefix, "label" to prefix, "value" to prefix)
} else {
null
}
}
}
}

+ 82
- 0
src/main/java/com/ffii/fpsms/modules/report/web/SemiFGProductionAnalysisReportController.kt 查看文件

@@ -0,0 +1,82 @@
package com.ffii.fpsms.modules.report.web

import net.sf.jasperreports.engine.*
import org.springframework.http.*
import org.springframework.web.bind.annotation.*
import java.time.LocalDate
import java.time.LocalTime
import java.time.format.DateTimeFormatter
import com.ffii.fpsms.modules.report.service.SemiFGProductionAnalysisReportService
import com.ffii.fpsms.modules.report.service.ReportService

@RestController
@RequestMapping("/report")
class SemiFGProductionAnalysisReportController(
private val semiFGProductionAnalysisReportService: SemiFGProductionAnalysisReportService,
private val reportService: ReportService,
) {

@GetMapping("/print-semi-fg-production-analysis")
fun generateSemiFGProductionAnalysisReport(
@RequestParam(required = false) stockCategory: String?,
@RequestParam(required = false) stockSubCategory: String?,
@RequestParam(required = false) itemCode: String?,
@RequestParam(required = false) year: 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["lastOutDateStart"] = lastOutDateStart ?: ""
parameters["lastOutDateEnd"] = lastOutDateEnd ?: ""
parameters["deliveryPeriodStart"] = ""
parameters["deliveryPeriodEnd"] = ""

// Query the DB to get a list of data
val dbData = semiFGProductionAnalysisReportService.searchSemiFGProductionAnalysisReport(
stockCategory,
stockSubCategory,
itemCode,
year,
lastOutDateStart,
lastOutDateEnd
)

val pdfBytes = reportService.createPdfResponse(
"/jasper/SemiFGProductionAnalysisReport.jrxml",
parameters,
dbData
)

val headers = HttpHeaders().apply {
contentType = MediaType.APPLICATION_PDF
setContentDispositionFormData("attachment", "SemiFGProductionAnalysisReport.pdf")
set("filename", "SemiFGProductionAnalysisReport.pdf")
}

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

@GetMapping("/semi-fg-item-codes")
fun getSemiFGItemCodes(
@RequestParam(required = false) stockCategory: String?
): ResponseEntity<List<Map<String, String>>> {
val itemCodes = semiFGProductionAnalysisReportService.getSemiFGItemCodes(stockCategory)
return ResponseEntity(itemCodes, HttpStatus.OK)
}

@GetMapping("/semi-fg-item-codes-with-category")
fun getSemiFGItemCodesWithCategory(
@RequestParam(required = false) stockCategory: String?
): ResponseEntity<List<Map<String, String>>> {
val itemCodesWithCategory = semiFGProductionAnalysisReportService.getSemiFGItemCodesWithCategory(stockCategory)
return ResponseEntity(itemCodesWithCategory, HttpStatus.OK)
}
}

+ 79
- 0
src/main/java/com/ffii/fpsms/modules/report/web/StockItemConsumptionTrendReportController.kt 查看文件

@@ -0,0 +1,79 @@
package com.ffii.fpsms.modules.report.web

import net.sf.jasperreports.engine.*
import org.springframework.http.*
import org.springframework.web.bind.annotation.*
import java.time.LocalDate
import java.time.LocalTime
import java.time.format.DateTimeFormatter
import com.ffii.fpsms.modules.report.service.StockItemConsumptionTrendReportService
import com.ffii.fpsms.modules.report.service.ReportService

@RestController
@RequestMapping("/report")
class StockItemConsumptionTrendReportController(
private val stockItemConsumptionTrendReportService: StockItemConsumptionTrendReportService,
private val reportService: ReportService,
) {

@GetMapping("/print-stock-item-consumption-trend")
fun generateStockItemConsumptionTrendReport(
@RequestParam(required = false) stockCategory: String?,
@RequestParam(required = false) itemCode: String?,
@RequestParam(required = false) year: String?,
@RequestParam(required = false) lastOutDateStart: String?,
@RequestParam(required = false) lastOutDateEnd: String?
): ResponseEntity<ByteArray> {
try {
val parameters = mutableMapOf<String, Any>()
// Set report header parameters
parameters["stockCategory"] = stockCategory ?: "All"
parameters["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["lastOutDateStart"] = lastOutDateStart ?: ""
parameters["lastOutDateEnd"] = lastOutDateEnd ?: ""
parameters["deliveryPeriodStart"] = ""
parameters["deliveryPeriodEnd"] = ""

// Query the DB to get a list of data
val dbData = stockItemConsumptionTrendReportService.searchStockItemConsumptionTrendReport(
stockCategory,
itemCode,
year,
lastOutDateStart,
lastOutDateEnd
)

val pdfBytes = reportService.createPdfResponse(
"/jasper/StockItemConsumptionTrendReport.jrxml",
parameters,
dbData
)

val headers = HttpHeaders().apply {
contentType = MediaType.APPLICATION_PDF
setContentDispositionFormData("attachment", "StockItemConsumptionTrendReport.pdf")
set("filename", "StockItemConsumptionTrendReport.pdf")
}

return ResponseEntity(pdfBytes, headers, HttpStatus.OK)
} catch (e: Exception) {
e.printStackTrace()
val errorMessage = e.message ?: "Unknown error occurred"
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(errorMessage.toByteArray())
}
}

@GetMapping("/stock-item-code-prefixes")
fun getStockItemCodePrefixes(
@RequestParam(required = false) stockCategory: String?
): ResponseEntity<List<Map<String, String>>> {
val prefixes = stockItemConsumptionTrendReportService.getStockItemCodePrefixes(stockCategory)
return ResponseEntity(prefixes, HttpStatus.OK)
}
}

+ 650
- 0
src/main/resources/jasper/StockItemConsumptionTrendReport.jrxml 查看文件

@@ -0,0 +1,650 @@
<?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="StockItemConsumptionTrendReport" pageWidth="842" pageHeight="595" orientation="Landscape" columnWidth="802" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="055685d6-c02e-403a-8511-48e9df2752d3">
<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"/>
<property name="com.jaspersoft.studio.unit.topMargin" value="pixel"/>
<property name="com.jaspersoft.studio.unit.bottomMargin" value="pixel"/>
<property name="com.jaspersoft.studio.unit.leftMargin" value="pixel"/>
<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"/>
<property name="com.jaspersoft.studio.data.sql.tables" value=""/>
<parameter name="stockSubCategory" class="java.lang.String">
<defaultValueExpression><![CDATA["stockSubCategory"]]></defaultValueExpression>
</parameter>
<parameter name="stockCategory" class="java.lang.String">
<defaultValueExpression><![CDATA["stockCategory"]]></defaultValueExpression>
</parameter>
<parameter name="itemNo" class="java.lang.String">
<defaultValueExpression><![CDATA["itemCode"]]></defaultValueExpression>
</parameter>
<parameter name="year" class="java.lang.String"/>
<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="lastOutDateStart" class="java.lang.String">
<parameterDescription><![CDATA["lastOutDateStart"]]></parameterDescription>
</parameter>
<parameter name="lastOutDateEnd" class="java.lang.String">
<parameterDescription><![CDATA["lastOutDateStart"]]></parameterDescription>
</parameter>
<queryString>
<![CDATA[select * from fpsmsdb.items , fpsmsdb.stock_out_line]]>
</queryString>
<field name="id" class="java.lang.Integer">
<property name="com.jaspersoft.studio.field.name" value="id"/>
<property name="com.jaspersoft.studio.field.label" value="id"/>
<property name="com.jaspersoft.studio.field.tree.path" value="items"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="modified" class="java.time.LocalDateTime">
<property name="com.jaspersoft.studio.field.name" value="modified"/>
<property name="com.jaspersoft.studio.field.label" value="modified"/>
<property name="com.jaspersoft.studio.field.tree.path" value="items"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="itemNo" class="java.lang.String">
<property name="com.jaspersoft.studio.field.name" value="code"/>
<property name="com.jaspersoft.studio.field.label" value="code"/>
<property name="com.jaspersoft.studio.field.tree.path" value="items"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="itemName" class="java.lang.String">
<property name="com.jaspersoft.studio.field.name" value="name"/>
<property name="com.jaspersoft.studio.field.label" value="name"/>
<property name="com.jaspersoft.studio.field.tree.path" value="items"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="description" class="java.lang.String">
<property name="com.jaspersoft.studio.field.name" value="description"/>
<property name="com.jaspersoft.studio.field.label" value="description"/>
<property name="com.jaspersoft.studio.field.tree.path" value="items"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="remarks" class="java.lang.String">
<property name="com.jaspersoft.studio.field.name" value="remarks"/>
<property name="com.jaspersoft.studio.field.label" value="remarks"/>
<property name="com.jaspersoft.studio.field.tree.path" value="items"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="type" class="java.lang.String">
<property name="com.jaspersoft.studio.field.name" value="type"/>
<property name="com.jaspersoft.studio.field.label" value="type"/>
<property name="com.jaspersoft.studio.field.tree.path" value="items"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="stockSubCategory" class="java.lang.Integer">
<property name="com.jaspersoft.studio.field.name" value="categoryId"/>
<property name="com.jaspersoft.studio.field.label" value="categoryId"/>
<property name="com.jaspersoft.studio.field.tree.path" value="items"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="qcCategoryId" class="java.lang.Integer">
<property name="com.jaspersoft.studio.field.name" value="qcCategoryId"/>
<property name="com.jaspersoft.studio.field.label" value="qcCategoryId"/>
<property name="com.jaspersoft.studio.field.tree.path" value="items"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="uomId" class="java.lang.Integer">
<property name="com.jaspersoft.studio.field.name" value="uomId"/>
<property name="com.jaspersoft.studio.field.label" value="uomId"/>
<property name="com.jaspersoft.studio.field.tree.path" value="items"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="itemId" class="java.lang.Integer">
<property name="com.jaspersoft.studio.field.name" value="itemId"/>
<property name="com.jaspersoft.studio.field.label" value="itemId"/>
<property name="com.jaspersoft.studio.field.tree.path" value="stock_out_line"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="qty" class="java.math.BigDecimal">
<property name="com.jaspersoft.studio.field.name" value="qty"/>
<property name="com.jaspersoft.studio.field.label" value="qty"/>
<property name="com.jaspersoft.studio.field.tree.path" value="stock_out_line"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="stockOutId" class="java.lang.Integer">
<property name="com.jaspersoft.studio.field.name" value="stockOutId"/>
<property name="com.jaspersoft.studio.field.label" value="stockOutId"/>
<property name="com.jaspersoft.studio.field.tree.path" value="stock_out_line"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="pickOrderLineId" class="java.lang.Integer">
<property name="com.jaspersoft.studio.field.name" value="pickOrderLineId"/>
<property name="com.jaspersoft.studio.field.label" value="pickOrderLineId"/>
<property name="com.jaspersoft.studio.field.tree.path" value="stock_out_line"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="status" class="java.lang.String">
<property name="com.jaspersoft.studio.field.name" value="status"/>
<property name="com.jaspersoft.studio.field.label" value="status"/>
<property name="com.jaspersoft.studio.field.tree.path" value="stock_out_line"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="pickTime" class="java.time.LocalDateTime">
<property name="com.jaspersoft.studio.field.name" value="pickTime"/>
<property name="com.jaspersoft.studio.field.label" value="pickTime"/>
<property name="com.jaspersoft.studio.field.tree.path" value="stock_out_line"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="qtyJan" class="java.math.BigDecimal">
<property name="com.jaspersoft.studio.field.name" value="qty"/>
<property name="com.jaspersoft.studio.field.label" value="qty"/>
<property name="com.jaspersoft.studio.field.tree.path" value="stock_out_line"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="qtyFeb" class="java.math.BigDecimal">
<property name="com.jaspersoft.studio.field.name" value="qty"/>
<property name="com.jaspersoft.studio.field.label" value="qty"/>
<property name="com.jaspersoft.studio.field.tree.path" value="stock_out_line"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="qtyMar" class="java.math.BigDecimal">
<property name="com.jaspersoft.studio.field.name" value="qty"/>
<property name="com.jaspersoft.studio.field.label" value="qty"/>
<property name="com.jaspersoft.studio.field.tree.path" value="stock_out_line"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="qtyApr" class="java.math.BigDecimal">
<property name="com.jaspersoft.studio.field.name" value="qty"/>
<property name="com.jaspersoft.studio.field.label" value="qty"/>
<property name="com.jaspersoft.studio.field.tree.path" value="stock_out_line"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="qtyMay" class="java.math.BigDecimal">
<property name="com.jaspersoft.studio.field.name" value="qty"/>
<property name="com.jaspersoft.studio.field.label" value="qty"/>
<property name="com.jaspersoft.studio.field.tree.path" value="stock_out_line"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="qtyJun" class="java.math.BigDecimal">
<property name="com.jaspersoft.studio.field.name" value="qty"/>
<property name="com.jaspersoft.studio.field.label" value="qty"/>
<property name="com.jaspersoft.studio.field.tree.path" value="stock_out_line"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="qtyJul" class="java.math.BigDecimal">
<property name="com.jaspersoft.studio.field.name" value="qty"/>
<property name="com.jaspersoft.studio.field.label" value="qty"/>
<property name="com.jaspersoft.studio.field.tree.path" value="stock_out_line"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="qtyAug" class="java.math.BigDecimal">
<property name="com.jaspersoft.studio.field.name" value="qty"/>
<property name="com.jaspersoft.studio.field.label" value="qty"/>
<property name="com.jaspersoft.studio.field.tree.path" value="stock_out_line"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="qtySep" class="java.math.BigDecimal">
<property name="com.jaspersoft.studio.field.name" value="qty"/>
<property name="com.jaspersoft.studio.field.label" value="qty"/>
<property name="com.jaspersoft.studio.field.tree.path" value="stock_out_line"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="qtyOct" class="java.math.BigDecimal">
<property name="com.jaspersoft.studio.field.name" value="qty"/>
<property name="com.jaspersoft.studio.field.label" value="qty"/>
<property name="com.jaspersoft.studio.field.tree.path" value="stock_out_line"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="qtyNov" class="java.math.BigDecimal">
<property name="com.jaspersoft.studio.field.name" value="qty"/>
<property name="com.jaspersoft.studio.field.label" value="qty"/>
<property name="com.jaspersoft.studio.field.tree.path" value="stock_out_line"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="qtyDec" class="java.math.BigDecimal">
<property name="com.jaspersoft.studio.field.name" value="qty"/>
<property name="com.jaspersoft.studio.field.label" value="qty"/>
<property name="com.jaspersoft.studio.field.tree.path" value="stock_out_line"/>
<fieldDescription><![CDATA[]]></fieldDescription>
</field>
<field name="unitOfMeasure" class="java.lang.String"/>
<field name="totalProductionQty" class="java.lang.String"/>
<group name="Group1">
<groupExpression><![CDATA[$F{itemNo}]]></groupExpression>
<groupHeader>
<band height="67">
<staticText>
<reportElement x="8" y="0" width="72" height="20" uuid="09bcfab9-9520-48dd-b851-3c00951cc550">
<property name="com.jaspersoft.studio.unit.y" value="px"/>
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="12"/>
</textElement>
<text><![CDATA[貨品編號:]]></text>
</staticText>
<textField>
<reportElement x="80" y="0" width="70" height="20" uuid="6f905a5d-cf6b-4d62-8433-ff3d570829ae"/>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="12"/>
</textElement>
<textFieldExpression><![CDATA[$F{itemNo}]]></textFieldExpression>
</textField>
<staticText>
<reportElement x="170" y="0" width="70" height="20" uuid="f0d35ecc-bc8d-4f5e-a94c-5cc6e5cde51e">
<property name="com.jaspersoft.studio.unit.y" value="px"/>
<property name="com.jaspersoft.studio.unit.height" value="px"/>
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Right" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="12"/>
</textElement>
<text><![CDATA[貨品名稱:]]></text>
</staticText>
<textField>
<reportElement x="240" y="0" width="210" height="20" uuid="11265d83-f36f-4cf2-ae3f-60d504226ab0">
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement verticalAlignment="Middle">
<font fontName="微軟正黑體" size="12"/>
</textElement>
<textFieldExpression><![CDATA[$F{itemName}]]></textFieldExpression>
</textField>
<staticText>
<reportElement x="480" y="0" width="41" height="20" uuid="a9054f9d-f217-4daa-a35c-076fe16a2df6">
<property name="com.jaspersoft.studio.unit.y" value="px"/>
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Right" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="12"/>
</textElement>
<text><![CDATA[單位:]]></text>
</staticText>
<textField>
<reportElement x="521" y="0" width="120" height="20" uuid="1a6c5348-668b-40cd-b8c7-a7b53c5dbcbe">
<property name="com.jaspersoft.studio.unit.height" value="px"/>
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="12"/>
</textElement>
<textFieldExpression><![CDATA[$F{unitOfMeasure}]]></textFieldExpression>
</textField>
<line>
<reportElement x="2" y="66" width="799" height="1" uuid="72083934-812f-42b9-b29b-b73d98fe6925">
<property name="com.jaspersoft.studio.unit.height" value="px"/>
</reportElement>
</line>
<staticText>
<reportElement x="512" y="20" width="56" height="20" uuid="a6161aa7-2abd-4bb6-894d-ccdd6f9575c4">
<property name="com.jaspersoft.studio.unit.y" value="px"/>
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<text><![CDATA[十月]]></text>
</staticText>
<textField pattern="#,##0">
<reportElement x="232" y="40" width="56" height="20" uuid="0f873665-fc42-4c6d-bb26-7f80537edb34">
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<textFieldExpression><![CDATA[$F{qtyMay}]]></textFieldExpression>
</textField>
<textField pattern="#,##0">
<reportElement x="456" y="40" width="56" height="20" uuid="bef5a00a-cc6c-4505-a170-0df341cc0a0b">
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<textFieldExpression><![CDATA[$F{qtySep}]]></textFieldExpression>
</textField>
<textField pattern="#,##0">
<reportElement x="176" y="40" width="56" height="20" uuid="ca9e080a-3a8b-4924-8197-6fa302b149c2">
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<textFieldExpression><![CDATA[$F{qtyApr}]]></textFieldExpression>
</textField>
<textField pattern="#,##0">
<reportElement x="8" y="40" width="56" height="20" uuid="06ace712-1de4-4cc0-b8d7-c56a08a0dbc6">
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<textFieldExpression><![CDATA[$F{qtyJan}]]></textFieldExpression>
</textField>
<textField pattern="#,##0">
<reportElement x="288" y="40" width="56" height="20" uuid="fc7e228a-ea4f-4990-b3f3-a17a7899a24a">
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<textFieldExpression><![CDATA[$F{qtyJun}]]></textFieldExpression>
</textField>
<textField pattern="#,##0">
<reportElement x="698" y="40" width="90" height="20" uuid="be0fb0b2-ce4d-4a20-8cf3-9049a58ae21e">
<property name="com.jaspersoft.studio.unit.height" value="px"/>
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<textFieldExpression><![CDATA[$F{totalProductionQty} != null && !$F{totalProductionQty}.isEmpty() ? new java.math.BigDecimal($F{totalProductionQty}) : new java.math.BigDecimal("0")]]></textFieldExpression>
</textField>
<textField pattern="#,##0">
<reportElement x="400" y="40" width="56" height="20" uuid="826bb018-835b-4c05-bd4e-8bbfabdfbfe8">
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<textFieldExpression><![CDATA[$F{qtyAug}]]></textFieldExpression>
</textField>
<textField pattern="#,##0">
<reportElement x="512" y="40" width="56" height="20" uuid="a6d6a1e2-e02a-4ff3-aac8-aa81af99f40a">
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<textFieldExpression><![CDATA[$F{qtyOct}]]></textFieldExpression>
</textField>
<textField pattern="#,##0">
<reportElement x="624" y="40" width="74" height="20" uuid="1525fa22-1c84-44dd-bf81-80a0cc14bc7d">
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<textFieldExpression><![CDATA[$F{qtyDec}]]></textFieldExpression>
</textField>
<staticText>
<reportElement x="176" y="20" width="56" height="20" uuid="8c5260bc-9079-4f62-803d-1c3e3fc9f41c">
<property name="com.jaspersoft.studio.unit.y" value="px"/>
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<text><![CDATA[四月]]></text>
</staticText>
<staticText>
<reportElement x="456" y="20" width="56" height="20" uuid="85c77a9b-c044-4bc2-8cd9-3b0058e4b74e">
<property name="com.jaspersoft.studio.unit.y" value="px"/>
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<text><![CDATA[九月]]></text>
</staticText>
<staticText>
<reportElement x="698" y="20" width="90" height="20" uuid="f092d4db-d5c5-4515-a826-8fec621a8992">
<property name="com.jaspersoft.studio.unit.y" value="px"/>
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<text><![CDATA[總和]]></text>
</staticText>
<staticText>
<reportElement x="64" y="20" width="56" height="20" uuid="ec7698ae-c92b-4b44-9f7a-28f10ba5f385">
<property name="com.jaspersoft.studio.unit.y" value="px"/>
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle" markup="html">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<text><![CDATA[二月]]></text>
</staticText>
<staticText>
<reportElement x="120" y="20" width="56" height="20" uuid="ac124afb-3aa8-4ec6-b4a8-8de161e8bbc5">
<property name="com.jaspersoft.studio.unit.y" value="px"/>
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<text><![CDATA[三月]]></text>
</staticText>
<textField pattern="#,##0">
<reportElement x="344" y="40" width="56" height="20" uuid="609cce9b-4703-441d-91c0-5ee489a324ac">
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<textFieldExpression><![CDATA[$F{qtyJul}]]></textFieldExpression>
</textField>
<textField pattern="#,##0">
<reportElement x="120" y="40" width="56" height="20" uuid="4d98e638-347d-46fe-9379-cebb088c43a1">
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<textFieldExpression><![CDATA[$F{qtyMar}]]></textFieldExpression>
</textField>
<staticText>
<reportElement x="568" y="20" width="56" height="20" uuid="e51758d1-2a7e-4fef-8b41-206e9aa6c611">
<property name="com.jaspersoft.studio.unit.y" value="px"/>
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<text><![CDATA[十一月]]></text>
</staticText>
<staticText>
<reportElement x="232" y="20" width="56" height="20" uuid="5204319c-5b4e-421b-9493-4dd988caca52">
<property name="com.jaspersoft.studio.unit.y" value="px"/>
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<text><![CDATA[五月]]></text>
</staticText>
<textField pattern="#,##0">
<reportElement x="64" y="40" width="56" height="20" uuid="bccf4a6c-8364-4a2e-be89-8e0d35154f06">
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<textFieldExpression><![CDATA[$F{qtyFeb}]]></textFieldExpression>
</textField>
<staticText>
<reportElement x="344" y="20" width="56" height="20" uuid="b221e73b-0f35-4036-bffb-9230a495b827">
<property name="com.jaspersoft.studio.unit.y" value="px"/>
<property name="com.jaspersoft.studio.unit.height" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<text><![CDATA[七月]]></text>
</staticText>
<textField pattern="#,##0">
<reportElement x="568" y="40" width="56" height="20" uuid="933ea07b-1ecc-4f91-b522-9fb5382fbf5b">
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<textFieldExpression><![CDATA[$F{qtyNov}]]></textFieldExpression>
</textField>
<staticText>
<reportElement x="624" y="20" width="74" height="20" uuid="d7c79995-7b3c-4622-8d08-6b4a87345cbe">
<property name="com.jaspersoft.studio.unit.y" value="px"/>
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<text><![CDATA[十二月]]></text>
</staticText>
<staticText>
<reportElement x="288" y="20" width="56" height="20" uuid="424446ec-655d-4bff-a30a-61e898dbc7ad">
<property name="com.jaspersoft.studio.unit.y" value="px"/>
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<text><![CDATA[六月]]></text>
</staticText>
<staticText>
<reportElement x="8" y="20" width="56" height="20" uuid="e4267f38-4a00-4a22-965d-9ab531262592">
<property name="com.jaspersoft.studio.unit.y" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<text><![CDATA[一月]]></text>
</staticText>
<staticText>
<reportElement x="400" y="20" width="56" height="20" uuid="2a9e0115-d056-4c4b-b0b2-0800f55435ad">
<property name="com.jaspersoft.studio.unit.y" value="px"/>
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="10"/>
</textElement>
<text><![CDATA[八月]]></text>
</staticText>
</band>
</groupHeader>
</group>
<pageHeader>
<band height="85" splitType="Stretch">
<property name="com.jaspersoft.studio.unit.height" value="px"/>
<textField evaluationTime="Report">
<reportElement x="760" y="0" width="30" height="23" uuid="6e9ed0a2-e1e6-4533-a786-f086b868a84c">
<property name="com.jaspersoft.studio.unit.width" value="px"/>
<property name="com.jaspersoft.studio.unit.height" value="px"/>
</reportElement>
<textElement textAlignment="Center" verticalAlignment="Middle"/>
<textFieldExpression><![CDATA[$V{PAGE_NUMBER}]]></textFieldExpression>
</textField>
<staticText>
<reportElement x="670" y="0" width="40" height="23" uuid="5a9e0fa9-418d-4838-9f82-e2f336e5bce7">
<property name="com.jaspersoft.studio.unit.y" value="px"/>
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="12"/>
</textElement>
<text><![CDATA[頁數]]></text>
</staticText>
<staticText>
<reportElement x="740" y="0" width="20" height="23" uuid="26d3d09c-48aa-4870-822a-c403e7faddfa">
<property name="com.jaspersoft.studio.unit.y" value="px"/>
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="12"/>
</textElement>
<text><![CDATA[/]]></text>
</staticText>
<textField>
<reportElement x="710" y="0" width="30" height="23" uuid="0c758a26-1c7f-484d-919e-d215917e9216">
<property name="com.jaspersoft.studio.unit.width" value="px"/>
</reportElement>
<textElement textAlignment="Center" verticalAlignment="Middle"/>
<textFieldExpression><![CDATA[$V{PAGE_NUMBER}]]></textFieldExpression>
</textField>
<staticText>
<reportElement x="8" y="30" width="90" height="23" uuid="0daddd8b-ca61-42af-9c2b-cbf11b7d7dac">
<property name="com.jaspersoft.studio.unit.y" value="px"/>
<property name="com.jaspersoft.studio.unit.height" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="12" isBold="true"/>
</textElement>
<text><![CDATA[報告日期:]]></text>
</staticText>
<textField>
<reportElement x="711" y="53" width="78" height="23" uuid="53b66bc3-4925-4340-add0-b4f2069a76c1"/>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA[$P{year}]]></textFieldExpression>
</textField>
<staticText>
<reportElement x="640" y="30" width="71" height="23" uuid="e2be43a3-3570-4a4e-a671-d96f872a5ad7">
<property name="com.jaspersoft.studio.unit.y" value="px"/>
<property name="com.jaspersoft.studio.unit.height" value="px"/>
</reportElement>
<textElement textAlignment="Right" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="12" isBold="true"/>
</textElement>
<text><![CDATA[報告時間:]]></text>
</staticText>
<staticText>
<reportElement x="640" y="53" width="71" height="23" uuid="29ed871d-3417-4978-9799-964389143451">
<property name="com.jaspersoft.studio.unit.y" value="px"/>
<property name="com.jaspersoft.studio.unit.height" value="px"/>
</reportElement>
<textElement textAlignment="Right" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="12" isBold="true"/>
</textElement>
<text><![CDATA[年份:]]></text>
</staticText>
<textField>
<reportElement x="711" y="30" width="78" height="23" uuid="cb1fbb06-e953-40e5-bdbe-5fc219f7c884"/>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA[$P{reportTime}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="98" y="30" width="190" height="23" uuid="d398cf17-318c-4c16-a8bf-6f064e911965"/>
<textElement verticalAlignment="Middle">
<font fontName="微軟正黑體" size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA[$P{reportDate}]]></textFieldExpression>
</textField>
<staticText>
<reportElement x="300" y="0" width="210" height="23" uuid="7451001b-6d5a-438c-82db-2b9e687d9a27">
<property name="com.jaspersoft.studio.unit.y" value="px"/>
<property name="com.jaspersoft.studio.unit.height" value="px"/>
</reportElement>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="16" isBold="true"/>
</textElement>
<text><![CDATA[庫存商品消費趨勢報告]]></text>
</staticText>
<textField>
<reportElement x="98" y="53" width="336" height="23" uuid="b51949e1-c40a-4db0-a799-4243555893fd">
<property name="com.jaspersoft.studio.unit.height" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA[$P{lastOutDateStart} + " 到 " + $P{lastOutDateEnd}]]></textFieldExpression>
</textField>
<staticText>
<reportElement x="8" y="53" width="90" height="23" uuid="fb09a559-f5fa-4e56-a891-87c600a2745a">
<property name="com.jaspersoft.studio.unit.y" value="px"/>
<property name="com.jaspersoft.studio.unit.width" value="px"/>
<property name="com.jaspersoft.studio.unit.height" value="px"/>
</reportElement>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font fontName="微軟正黑體" size="12" isBold="true"/>
</textElement>
<text><![CDATA[完成生產日期:]]></text>
</staticText>
<line>
<reportElement x="2" y="80" width="799" height="1" uuid="9e9ba4e3-e369-4180-b01b-1b581e8fa00d">
<property name="com.jaspersoft.studio.unit.height" value="px"/>
</reportElement>
</line>
</band>
</pageHeader>
</jasperReport>

Loading…
取消
儲存