Pārlūkot izejas kodu

no message

master
Fai Luk pirms 3 dienas
vecāks
revīzija
74e5bdabbc
2 mainītis faili ar 46 papildinājumiem un 19 dzēšanām
  1. +39
    -16
      src/main/java/com/ffii/fpsms/modules/chart/service/ChartService.kt
  2. +7
    -3
      src/main/java/com/ffii/fpsms/modules/jobOrder/service/PlasticBagPrinterService.kt

+ 39
- 16
src/main/java/com/ffii/fpsms/modules/chart/service/ChartService.kt Parādīt failu

@@ -68,7 +68,8 @@ open class ChartService(

/**
* Purchase orders: count by status (pending, receiving, completed).
* targetDate: when set, only POs whose orderDate is on that date; when null, all POs.
* targetDate: when set, include POs whose estimatedArrivalDate is on that date OR have stock-in
* activity (completeDate/receiptDate/created) on that date; when null, all POs.
* Optional multi-filters: supplierIds, itemCodes (line itemNo), purchaseOrderNos (po.code).
*/
fun getPurchaseOrderByStatus(
@@ -78,10 +79,7 @@ open class ChartService(
purchaseOrderNos: List<String>?,
): List<Map<String, Any>> {
val args = mutableMapOf<String, Any>()
val dateSql = if (targetDate != null) {
args["targetDate"] = targetDate.toString()
"AND DATE(po.orderDate) = :targetDate"
} else ""
val dateSql = buildPurchaseOrderActualSearchDateSql(targetDate, args)
val multiSql = buildPoMultiFiltersSql(supplierIds, itemCodes, purchaseOrderNos, null, args)
val sql = """
SELECT
@@ -96,9 +94,7 @@ open class ChartService(
return jdbcDao.queryForList(sql, args)
}

/**
* Filter options for purchase chart (distinct suppliers / items / PO numbers on orderDate).
*/
/** Filter options for purchase chart on the same date scope as 實際已送貨. */
fun getPurchaseOrderFilterOptions(targetDate: LocalDate?): Map<String, Any> {
if (targetDate == null) {
return mapOf(
@@ -107,12 +103,13 @@ open class ChartService(
"poNos" to emptyList<Any>(),
)
}
val args = mutableMapOf<String, Any>("targetDate" to targetDate.toString())
val args = mutableMapOf<String, Any>()
val dateSql = buildPurchaseOrderActualSearchDateSql(targetDate, args)
val suppliersSql = """
SELECT DISTINCT po.supplierId AS supplierId, s.code AS code, COALESCE(s.name, '') AS name
FROM purchase_order po
LEFT JOIN shop s ON s.id = po.supplierId AND s.deleted = 0
WHERE po.deleted = 0 AND DATE(po.orderDate) = :targetDate AND po.supplierId IS NOT NULL
WHERE po.deleted = 0 $dateSql AND po.supplierId IS NOT NULL
ORDER BY s.code
""".trimIndent()
val itemsSql = """
@@ -120,13 +117,13 @@ open class ChartService(
FROM purchase_order_line pol
INNER JOIN purchase_order po ON po.id = pol.purchaseOrderId AND po.deleted = 0
LEFT JOIN items it ON it.id = pol.itemId AND it.deleted = 0
WHERE pol.deleted = 0 AND DATE(po.orderDate) = :targetDate
WHERE pol.deleted = 0 $dateSql
ORDER BY pol.itemNo
""".trimIndent()
val poNosSql = """
SELECT DISTINCT po.code AS poNo
FROM purchase_order po
WHERE po.deleted = 0 AND DATE(po.orderDate) = :targetDate
WHERE po.deleted = 0 $dateSql
ORDER BY po.code
""".trimIndent()
return mapOf(
@@ -377,14 +374,40 @@ open class ChartService(
}
}

/**
* Date scope for 實際已送貨:
* - planned side: PO estimatedArrivalDate = targetDate
* - actual side: any stock-in activity date = targetDate
*/
private fun buildPurchaseOrderActualSearchDateSql(
targetDate: LocalDate?,
args: MutableMap<String, Any>,
): String {
if (targetDate == null) return ""
args["targetDate"] = targetDate.toString()
return """
AND (
(po.estimatedArrivalDate IS NOT NULL AND DATE(po.estimatedArrivalDate) = :targetDate)
OR EXISTS (
SELECT 1
FROM purchase_order_line polDate
INNER JOIN stock_in_line silDate ON silDate.purchaseOrderLineId = polDate.id AND silDate.deleted = 0
INNER JOIN stock_in siDate ON siDate.id = silDate.stockInId AND siDate.deleted = 0
WHERE polDate.purchaseOrderId = po.id
AND polDate.deleted = 0
AND DATE(COALESCE(siDate.completeDate, silDate.receiptDate, siDate.created)) = :targetDate
)
)
""".trimIndent()
}

/**
* Drill-down rows for 預計送貨 must match [getPurchaseOrderEstimatedArrivalSummary] (estimated arrival date only).
* If we also applied [buildPurchaseOrderTargetDateSql], many POs (orderDate ≠ 預計到貨日) would drop out and
* supplier / item charts would collapse incorrectly.
*
* For 實際已送貨 (no bucket), [getPurchaseOrderByStatus] is always filtered by **order date** only. If drill used
* [dateFilter] = complete, rows would be restricted to completeDate = targetDate and supplier/item charts would
* collapse to a tiny set (often one supplier) vs the donut counts.
* For 實際已送貨 (no bucket), drill must follow [buildPurchaseOrderActualSearchDateSql] to keep lower charts
* consistent with the top donut data scope.
*/
private fun buildPurchaseOrderDrillOrderDateSql(
estimatedArrivalBucket: String?,
@@ -395,7 +418,7 @@ open class ChartService(
if (!estimatedArrivalBucket.isNullOrBlank() && targetDate != null) {
return ""
}
return buildPurchaseOrderTargetDateSql(targetDate, "order", args)
return buildPurchaseOrderActualSearchDateSql(targetDate, args)
}

/**


+ 7
- 3
src/main/java/com/ffii/fpsms/modules/jobOrder/service/PlasticBagPrinterService.kt Parādīt failu

@@ -17,6 +17,7 @@ import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
import javax.imageio.ImageIO
import com.google.zxing.BarcodeFormat
import com.google.zxing.EncodeHintType
import com.google.zxing.qrcode.QRCodeWriter
import java.net.Socket
import java.net.InetSocketAddress
@@ -205,8 +206,10 @@ open class PlasticBagPrinterService(
val imageTemplate = loadOnPackImageTemplateOrNull(codeLower) ?: return@forEach

val qrContent = """{"itemId": $itemId, "stockInLineId": $stockInLineId}"""
// Reduce top/bottom whitespace by 90% for exported QR images (40px -> 4px).
val bmp = createQrCodeBitmap(qrContent, contentSize = 600, horizontalPadding = 40, verticalPadding = 4)
// Target approximately 470x389 BMP, but with larger visible QR and very little vertical whitespace.
// Width = 386 + (42 * 2) = 470
// Height = 386 + (1 * 2) = 388 (~389)
val bmp = createQrCodeBitmap(qrContent, contentSize = 386, horizontalPadding = 42, verticalPadding = 1)
val qrBmpFileName = "${codeLower}qr.bmp"
val imageFileName = "$codeLower.image"
val imageContent = withOnPackLogo4Bmp(imageTemplate, qrBmpFileName)
@@ -388,7 +391,8 @@ open class PlasticBagPrinterService(
val totalHeight = contentSize + (verticalPadding * 2)

val writer = QRCodeWriter()
val bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, contentSize, contentSize)
val hints = mapOf(EncodeHintType.MARGIN to 0)
val bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, contentSize, contentSize, hints)

val image = BufferedImage(totalWidth, totalHeight, BufferedImage.TYPE_BYTE_BINARY)
val g = image.createGraphics()


Notiek ielāde…
Atcelt
Saglabāt