Bläddra i källkod

[Fix] Stock Ledger report now displays decimals correctly

undefined
Harry Groves 1 vecka sedan
förälder
incheckning
d2fdbd578c
3 ändrade filer med 40 tillägg och 39 borttagningar
  1. +0
    -0
      gradlew
  2. +17
    -22
      src/main/java/com/ffii/fpsms/modules/report/service/StockLedgerReportService.kt
  3. +23
    -17
      src/main/java/com/ffii/fpsms/modules/report/web/StockLedgerReportController.kt

+ 0
- 0
gradlew Visa fil


+ 17
- 22
src/main/java/com/ffii/fpsms/modules/report/service/StockLedgerReportService.kt Visa fil

@@ -111,28 +111,14 @@ SELECT
reOrderLevel,
reOrderQty,

CASE WHEN inQty < 0 THEN CONCAT('(', FORMAT(-inQty, 0), ')') ELSE FORMAT(inQty, 0) END AS stockIn,
CASE WHEN outQty < 0 THEN CONCAT('(', FORMAT(-outQty, 0), ')') ELSE FORMAT(outQty, 0) END AS stockOut,

CASE WHEN cumOpeningBalRaw < 0
THEN CONCAT('(', FORMAT(-cumOpeningBalRaw, 0), ')')
ELSE FORMAT(cumOpeningBalRaw, 0) END AS cumOpeningBal,
CASE WHEN bal < 0
THEN CONCAT('(', FORMAT(-bal, 0), ')')
ELSE FORMAT(bal, 0) END AS cumBalance,

CASE WHEN totalCumOpeningBalRaw < 0
THEN CONCAT('(', FORMAT(-totalCumOpeningBalRaw, 0), ')')
ELSE FORMAT(totalCumOpeningBalRaw, 0) END AS totalCumOpeningBal,
CASE WHEN totalStockInRaw < 0
THEN CONCAT('(', FORMAT(-totalStockInRaw, 0), ')')
ELSE FORMAT(totalStockInRaw, 0) END AS totalStockIn,
CASE WHEN totalStockOutRaw < 0
THEN CONCAT('(', FORMAT(-totalStockOutRaw, 0), ')')
ELSE FORMAT(totalStockOutRaw, 0) END AS totalStockOut,
CASE WHEN totalCumBalanceRaw < 0
THEN CONCAT('(', FORMAT(-totalCumBalanceRaw, 0), ')')
ELSE FORMAT(totalCumBalanceRaw, 0) END AS totalCumBalance
${signedQtySql("inQty")} AS stockIn,
${signedQtySql("outQty")} AS stockOut,
${signedQtySql("cumOpeningBalRaw")} AS cumOpeningBal,
${signedQtySql("bal")} AS cumBalance,
${signedQtySql("totalCumOpeningBalRaw")} AS totalCumOpeningBal,
${signedQtySql("totalStockInRaw")} AS totalStockIn,
${signedQtySql("totalStockOutRaw")} AS totalStockOut,
${signedQtySql("totalCumBalanceRaw")} AS totalCumBalance

FROM (
SELECT
@@ -278,6 +264,15 @@ ORDER BY
return jdbcDao.queryForList(sql, args)
}

/**
* Qty display: up to 2 decimal places, trailing zeros stripped so whole numbers stay whole.
* Negatives use accounting parentheses, matching the rest of the report.
*/
private fun signedQtySql(expr: String): String =
"""CASE WHEN $expr < 0
THEN CONCAT('(', TRIM(TRAILING '.' FROM TRIM(TRAILING '0' FROM FORMAT(-($expr), 2))), ')')
ELSE TRIM(TRAILING '.' FROM TRIM(TRAILING '0' FROM FORMAT($expr, 2))) END"""

/** LIKE 多值工具方法 */
private fun buildMultiValueLikeClause(
paramValue: String?,


+ 23
- 17
src/main/java/com/ffii/fpsms/modules/report/web/StockLedgerReportController.kt Visa fil

@@ -19,6 +19,7 @@ import org.apache.poi.ss.util.CellRangeAddress
import org.apache.poi.ss.util.WorkbookUtil
import org.apache.poi.xssf.streaming.SXSSFWorkbook
import java.io.ByteArrayOutputStream
import java.util.Locale

@RestController
@RequestMapping("/report")
@@ -32,7 +33,7 @@ class StockLedgerReportController(
val header: CellStyle,
val text: CellStyle,
val center: CellStyle,
val int: CellStyle,
val number: CellStyle,
val dash: CellStyle,
val sumQty: CellStyle,
val sumLabel: CellStyle,
@@ -166,7 +167,7 @@ class StockLedgerReportController(
borderLeft = BorderStyle.THIN
borderRight = BorderStyle.THIN
}
val intStyle = workbook.createCellStyle().apply {
val numberStyle = workbook.createCellStyle().apply {
alignment = HorizontalAlignment.RIGHT
verticalAlignment = VerticalAlignment.CENTER
borderTop = BorderStyle.THIN
@@ -174,7 +175,7 @@ class StockLedgerReportController(
borderLeft = BorderStyle.THIN
borderRight = BorderStyle.THIN
val df: DataFormat = workbook.createDataFormat()
dataFormat = df.getFormat("#,##0")
dataFormat = df.getFormat("#,##0.##")
}
val dashStyle = workbook.createCellStyle().apply {
alignment = HorizontalAlignment.RIGHT
@@ -188,7 +189,7 @@ class StockLedgerReportController(
alignment = HorizontalAlignment.RIGHT
verticalAlignment = VerticalAlignment.CENTER
val df: DataFormat = workbook.createDataFormat()
dataFormat = df.getFormat("#,##0")
dataFormat = df.getFormat("#,##0.##")
borderTop = BorderStyle.THICK
borderBottom = BorderStyle.THICK
borderLeft = BorderStyle.THIN
@@ -230,7 +231,7 @@ class StockLedgerReportController(
header = headerStyle,
text = textStyle,
center = centerStyle,
int = intStyle,
number = numberStyle,
dash = dashStyle,
sumQty = sumQty,
sumLabel = sumLabel,
@@ -255,11 +256,11 @@ class StockLedgerReportController(
return if (negative) -n else n
}

private fun setIntCellFromFormatted(
private fun setNumberCellFromFormatted(
row: Row,
col: Int,
value: Any?,
intStyle: CellStyle,
numberStyle: CellStyle,
dashStyle: CellStyle,
) {
val cell = row.createCell(col)
@@ -270,15 +271,20 @@ class StockLedgerReportController(
return
}
if (parsed < 0) {
val s = "%,d".format(kotlin.math.abs(parsed).toLong())
cell.setCellValue("($s)")
cell.setCellValue("(${formatAbsQty(parsed)})")
cell.cellStyle = dashStyle
} else {
cell.setCellValue(parsed)
cell.cellStyle = intStyle
cell.cellStyle = numberStyle
}
}

/** Up to 2 dp; strip trailing zeros so whole numbers stay whole. */
private fun formatAbsQty(v: Double): String {
val formatted = "%,.2f".format(Locale.US, kotlin.math.abs(v))
return formatted.trimEnd('0').trimEnd('.')
}

/**
* SXSSF keeps only a sliding window of rows in memory to avoid OOM on large exports.
*/
@@ -353,9 +359,9 @@ class StockLedgerReportController(
r.createCell(c).apply { setCellValue(""); cellStyle = styles.sumEmpty }
}
r.getCell(7).apply { setCellValue("貨品總量:"); cellStyle = styles.sumLabel }
setIntCellFromFormatted(r, 8, totalIn, styles.sumQty, styles.dash)
setIntCellFromFormatted(r, 9, totalOut, styles.sumQty, styles.dash)
setIntCellFromFormatted(r, 10, totalBal, styles.sumQty, styles.dash)
setNumberCellFromFormatted(r, 8, totalIn, styles.sumQty, styles.dash)
setNumberCellFromFormatted(r, 9, totalOut, styles.sumQty, styles.dash)
setNumberCellFromFormatted(r, 10, totalBal, styles.sumQty, styles.dash)
}

if (dbData.isEmpty()) {
@@ -397,10 +403,10 @@ class StockLedgerReportController(
setTextCell(r, 4, typeText, styles.center)
setTextCell(r, 5, m["lotNo"], styles.text)
setTextCell(r, 6, m["expiryDate"], styles.center)
setIntCellFromFormatted(r, 7, m["cumOpeningBal"], styles.int, styles.dash)
setIntCellFromFormatted(r, 8, m["stockIn"], styles.int, styles.dash)
setIntCellFromFormatted(r, 9, m["stockOut"], styles.int, styles.dash)
setIntCellFromFormatted(r, 10, m["cumBalance"], styles.int, styles.dash)
setNumberCellFromFormatted(r, 7, m["cumOpeningBal"], styles.number, styles.dash)
setNumberCellFromFormatted(r, 8, m["stockIn"], styles.number, styles.dash)
setNumberCellFromFormatted(r, 9, m["stockOut"], styles.number, styles.dash)
setNumberCellFromFormatted(r, 10, m["cumBalance"], styles.number, styles.dash)
setTextCell(r, 11, m["orderRefNo"], styles.text)
setTextCell(r, 12, m["storeLocation"], styles.center)



Laddar…
Avbryt
Spara