2 Révisions

Auteur SHA1 Message Date
  B.E.N.S.O.N 0a992c381d Merge remote-tracking branch 'origin/production' into production il y a 1 semaine
  B.E.N.S.O.N 8002b6d621 QR Code Printing Update il y a 1 semaine
9 fichiers modifiés avec 186 ajouts et 64 suppressions
  1. +52
    -19
      src/main/java/com/ffii/fpsms/modules/master/service/EquipmentQrCodeService.kt
  2. +48
    -19
      src/main/java/com/ffii/fpsms/modules/master/service/WarehouseQrCodeService.kt
  3. +5
    -0
      src/main/java/com/ffii/fpsms/modules/master/web/EquipmentController.kt
  4. +7
    -0
      src/main/java/com/ffii/fpsms/modules/master/web/PrintEquipmentQrCodeRequest.kt
  5. +7
    -0
      src/main/java/com/ffii/fpsms/modules/master/web/PrintWarehouseQrCodeRequest.kt
  6. +4
    -0
      src/main/java/com/ffii/fpsms/modules/master/web/WarehouseController.kt
  7. +51
    -24
      src/main/java/com/ffii/fpsms/modules/user/service/UserQrCodeService.kt
  8. +7
    -0
      src/main/java/com/ffii/fpsms/modules/user/web/PrintUserQrCodeRequest.kt
  9. +5
    -2
      src/main/java/com/ffii/fpsms/modules/user/web/UserController.java

+ 52
- 19
src/main/java/com/ffii/fpsms/modules/master/service/EquipmentQrCodeService.kt Voir le fichier

@@ -4,30 +4,52 @@ import com.ffii.core.utils.PdfUtils
import com.ffii.core.utils.QrCodeUtil
import com.ffii.fpsms.modules.master.entity.EquipmentDetailRepository
import com.ffii.fpsms.modules.master.web.ExportEquipmentQrCodeRequest
import com.ffii.fpsms.modules.master.web.PrintEquipmentQrCodeRequest
import com.ffii.fpsms.modules.master.print.A4PrintDriverRegistry
import net.sf.jasperreports.engine.JasperCompileManager
import net.sf.jasperreports.engine.JasperExportManager
import net.sf.jasperreports.engine.JasperReport
import net.sf.jasperreports.engine.JasperPrint
import org.springframework.core.io.ClassPathResource
import org.springframework.stereotype.Service
import java.io.FileNotFoundException
import java.io.File
import java.awt.GraphicsEnvironment
import kotlinx.serialization.json.Json
import kotlinx.serialization.encodeToString

@Service
class EquipmentQrCodeService(
private val equipmentDetailRepository: EquipmentDetailRepository
private val equipmentDetailRepository: EquipmentDetailRepository,
private val printerService: PrinterService,
) {
private val qrCodeHandleJrxmlPath = "qrCodeHandle/equipment_QrHandle.jrxml"

fun exportEquipmentQrCode(request: ExportEquipmentQrCodeRequest): Map<String, Any> {
val QRCODE_HANDLE_PDF = "qrCodeHandle/equipment_QrHandle.jrxml"
val resource = ClassPathResource(QRCODE_HANDLE_PDF)
/**
* Compile the Jasper template once; compiling per request is expensive.
*/
private val qrCodeHandleReport: JasperReport by lazy {
val resource = ClassPathResource(qrCodeHandleJrxmlPath)
if (!resource.exists()) {
throw FileNotFoundException("Report file not found: $QRCODE_HANDLE_PDF")
throw FileNotFoundException("Report file not found: $qrCodeHandleJrxmlPath")
}
val inputStream = resource.inputStream
val qrCodeHandleReport = JasperCompileManager.compileReport(inputStream)
resource.inputStream.use { JasperCompileManager.compileReport(it) }
}

/**
* Cache the chosen Chinese font family name (font scanning is expensive).
*/
private val chineseFontFamily: String by lazy {
val availableFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().availableFontFamilyNames
availableFonts.find { family ->
family.contains("SimSun", ignoreCase = true) ||
family.contains("Microsoft YaHei", ignoreCase = true) ||
family.contains("STSong", ignoreCase = true) ||
family.contains("SimHei", ignoreCase = true)
} ?: "Arial Unicode MS"
}

fun exportEquipmentQrCode(request: ExportEquipmentQrCodeRequest): Map<String, Any> {
val equipmentDetails = equipmentDetailRepository.findAllById(request.equipmentDetailIds)
if (equipmentDetails.isEmpty()) {
throw IllegalArgumentException("No equipment details found for the provided equipment detail IDs: ${request.equipmentDetailIds}")
@@ -63,18 +85,10 @@ class EquipmentQrCodeService(
}
val params: MutableMap<String, Any> = mutableMapOf()
val availableFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().availableFontFamilyNames
val chineseFont = availableFonts.find {
it.contains("SimSun", ignoreCase = true) ||
it.contains("Microsoft YaHei", ignoreCase = true) ||
it.contains("STSong", ignoreCase = true) ||
it.contains("SimHei", ignoreCase = true)
} ?: "Arial Unicode MS"

params["net.sf.jasperreports.default.pdf.encoding"] = "Identity-H"
params["net.sf.jasperreports.default.pdf.embedded"] = true
params["net.sf.jasperreports.default.pdf.font.name"] = chineseFont
params["net.sf.jasperreports.default.pdf.font.name"] = chineseFontFamily
val firstEquipmentDetail = equipmentDetails.firstOrNull()
@@ -83,4 +97,23 @@ class EquipmentQrCodeService(
"fileName" to (firstEquipmentDetail?.code ?: "equipment_qrcode")
)
}

fun printEquipmentQrCode(request: PrintEquipmentQrCodeRequest) {
val printer = printerService.findById(request.printerId) ?: throw NoSuchElementException("No such printer")
val pdf = exportEquipmentQrCode(ExportEquipmentQrCodeRequest(request.equipmentDetailIds))
val jasperPrint = pdf["report"] as JasperPrint
val tempPdfFile = File.createTempFile("print_job_", ".pdf")

try {
JasperExportManager.exportReportToPdfFile(jasperPrint, tempPdfFile.absolutePath)
val printQty = if (request.printQty == null || request.printQty <= 0) 1 else request.printQty
printer.ip?.let { ip ->
val port = printer.port ?: 9100
val driver = A4PrintDriverRegistry.getDriver(printer.brand)
driver.print(tempPdfFile, ip, port, printQty)
}
} finally {
tempPdfFile.delete()
}
}
}

+ 48
- 19
src/main/java/com/ffii/fpsms/modules/master/service/WarehouseQrCodeService.kt Voir le fichier

@@ -2,12 +2,17 @@ package com.ffii.fpsms.modules.master.service

import com.ffii.core.utils.PdfUtils
import com.ffii.core.utils.QrCodeUtil
import com.ffii.fpsms.modules.master.print.A4PrintDriverRegistry
import com.ffii.fpsms.modules.master.entity.WarehouseRepository
import com.ffii.fpsms.modules.master.web.ExportWarehouseQrCodeRequest
import com.ffii.fpsms.modules.master.web.PrintWarehouseQrCodeRequest
import net.sf.jasperreports.engine.JasperCompileManager
import net.sf.jasperreports.engine.JasperExportManager
import net.sf.jasperreports.engine.JasperReport
import net.sf.jasperreports.engine.JasperPrint
import org.springframework.core.io.ClassPathResource
import org.springframework.stereotype.Service
import java.io.File
import java.io.FileNotFoundException
import java.awt.GraphicsEnvironment
import kotlinx.serialization.json.Json
@@ -15,19 +20,32 @@ import kotlinx.serialization.encodeToString

@Service
class WarehouseQrCodeService(
private val warehouseRepository: WarehouseRepository
private val warehouseRepository: WarehouseRepository,
private val printerService: PrinterService,
) {
private val qrCodeHandleJrxmlPath = "qrCodeHandle/warehouse_QrHandle.jrxml"

fun exportWarehouseQrCode(request: ExportWarehouseQrCodeRequest): Map<String, Any> {
val QRCODE_HANDLE_PDF = "qrCodeHandle/warehouse_QrHandle.jrxml"
val resource = ClassPathResource(QRCODE_HANDLE_PDF)
/** Compile the Jasper template once; compiling per request is expensive. */
private val qrCodeHandleReport: JasperReport by lazy {
val resource = ClassPathResource(qrCodeHandleJrxmlPath)
if (!resource.exists()) {
throw FileNotFoundException("Report file not found: $QRCODE_HANDLE_PDF")
throw FileNotFoundException("Report file not found: $qrCodeHandleJrxmlPath")
}
val inputStream = resource.inputStream
val qrCodeHandleReport = JasperCompileManager.compileReport(inputStream)
resource.inputStream.use { JasperCompileManager.compileReport(it) }
}

/** Cache the chosen Chinese font family name (font scanning is expensive). */
private val chineseFontFamily: String by lazy {
val availableFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().availableFontFamilyNames
availableFonts.find { family ->
family.contains("SimSun", ignoreCase = true) ||
family.contains("Microsoft YaHei", ignoreCase = true) ||
family.contains("STSong", ignoreCase = true) ||
family.contains("SimHei", ignoreCase = true)
} ?: "Arial Unicode MS"
}

fun exportWarehouseQrCode(request: ExportWarehouseQrCodeRequest): Map<String, Any> {
val warehouses = warehouseRepository.findAllById(request.warehouseIds)
if (warehouses.isEmpty()) {
throw IllegalArgumentException("No warehouses found for the provided warehouse IDs: ${request.warehouseIds}")
@@ -68,18 +86,10 @@ class WarehouseQrCodeService(
}
val params: MutableMap<String, Any> = mutableMapOf()
val availableFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().availableFontFamilyNames
val chineseFont = availableFonts.find {
it.contains("SimSun", ignoreCase = true) ||
it.contains("Microsoft YaHei", ignoreCase = true) ||
it.contains("STSong", ignoreCase = true) ||
it.contains("SimHei", ignoreCase = true)
} ?: "Arial Unicode MS"

params["net.sf.jasperreports.default.pdf.encoding"] = "Identity-H"
params["net.sf.jasperreports.default.pdf.embedded"] = true
params["net.sf.jasperreports.default.pdf.font.name"] = chineseFont
params["net.sf.jasperreports.default.pdf.font.name"] = chineseFontFamily
val firstWarehouse = warehouses.firstOrNull()
@@ -88,4 +98,23 @@ class WarehouseQrCodeService(
"fileName" to (firstWarehouse?.code ?: "warehouse_qrcode")
)
}

fun printWarehouseQrCode(request: PrintWarehouseQrCodeRequest) {
val printer = printerService.findById(request.printerId) ?: throw NoSuchElementException("No such printer")
val pdf = exportWarehouseQrCode(ExportWarehouseQrCodeRequest(request.warehouseIds))
val jasperPrint = pdf["report"] as JasperPrint
val tempPdfFile = File.createTempFile("print_job_", ".pdf")

try {
JasperExportManager.exportReportToPdfFile(jasperPrint, tempPdfFile.absolutePath)
val printQty = if (request.printQty == null || request.printQty <= 0) 1 else request.printQty
printer.ip?.let { ip ->
val port = printer.port ?: 9100
val driver = A4PrintDriverRegistry.getDriver(printer.brand)
driver.print(tempPdfFile, ip, port, printQty)
}
} finally {
tempPdfFile.delete()
}
}
}

+ 5
- 0
src/main/java/com/ffii/fpsms/modules/master/web/EquipmentController.kt Voir le fichier

@@ -93,4 +93,9 @@ fun getAllEquipmentByPage(
out.flush()
}

@PostMapping("/print-qrcode")
fun printQrCode(@Valid @RequestBody request: PrintEquipmentQrCodeRequest) {
equipmentQrCodeService.printEquipmentQrCode(request)
}

}

+ 7
- 0
src/main/java/com/ffii/fpsms/modules/master/web/PrintEquipmentQrCodeRequest.kt Voir le fichier

@@ -0,0 +1,7 @@
package com.ffii.fpsms.modules.master.web

data class PrintEquipmentQrCodeRequest(
val equipmentDetailIds: List<Long>,
val printerId: Long,
val printQty: Int? = 1,
)

+ 7
- 0
src/main/java/com/ffii/fpsms/modules/master/web/PrintWarehouseQrCodeRequest.kt Voir le fichier

@@ -0,0 +1,7 @@
package com.ffii.fpsms.modules.master.web

data class PrintWarehouseQrCodeRequest(
val warehouseIds: List<Long>,
val printerId: Long,
val printQty: Int? = 1,
)

+ 4
- 0
src/main/java/com/ffii/fpsms/modules/master/web/WarehouseController.kt Voir le fichier

@@ -98,6 +98,10 @@ class WarehouseController(
out.write(JasperExportManager.exportReportToPdf(jasperPrint))
out.flush()
}
@PostMapping("/print-qrcode")
fun printQrCode(@Valid @RequestBody request: PrintWarehouseQrCodeRequest) {
warehouseQrCodeService.printWarehouseQrCode(request)
}
@GetMapping("/stockTakeSections")
fun getStockTakeSections(): List<StockTakeSectionInfo> {
return warehouseService.getStockTakeSections()


+ 51
- 24
src/main/java/com/ffii/fpsms/modules/user/service/UserQrCodeService.kt Voir le fichier

@@ -2,15 +2,18 @@ package com.ffii.fpsms.modules.user.service

import com.ffii.core.utils.PdfUtils
import com.ffii.core.utils.QrCodeUtil
import com.ffii.fpsms.modules.master.print.A4PrintDriverRegistry
import com.ffii.fpsms.modules.master.service.PrinterService
import com.ffii.fpsms.modules.user.entity.UserRepository
import com.ffii.fpsms.modules.user.web.ExportUserQrCodeRequest
import com.ffii.fpsms.modules.user.web.PrintUserQrCodeRequest
import net.sf.jasperreports.engine.JasperCompileManager
import net.sf.jasperreports.engine.JasperExportManager
import net.sf.jasperreports.engine.JasperReport
import net.sf.jasperreports.engine.JasperPrint
import net.sf.jasperreports.engine.export.JRPdfExporter
import net.sf.jasperreports.export.SimpleExporterInput
import net.sf.jasperreports.export.SimpleOutputStreamExporterOutput
import org.springframework.core.io.ClassPathResource
import org.springframework.stereotype.Service
import java.io.File
import java.io.FileNotFoundException
import java.awt.GraphicsEnvironment
import kotlinx.serialization.json.Json
@@ -18,19 +21,34 @@ import kotlinx.serialization.encodeToString

@Service
class UserQrCodeService(
private val userRepository: UserRepository
private val userRepository: UserRepository,
private val printerService: PrinterService,
) {
private val qrCodeHandleJrxmlPath = "qrCodeHandle/qrCodeHandle.jrxml"

fun exportUserQrCode(request: ExportUserQrCodeRequest): Map<String, Any> {
val QRCODE_HANDLE_PDF = "qrCodeHandle/qrCodeHandle.jrxml"
val resource = ClassPathResource(QRCODE_HANDLE_PDF)
/**
* Compile the Jasper template once; compiling per request is expensive.
*/
private val qrCodeHandleReport: JasperReport by lazy {
val resource = ClassPathResource(qrCodeHandleJrxmlPath)
if (!resource.exists()) {
throw FileNotFoundException("Report file not found: $QRCODE_HANDLE_PDF")
throw FileNotFoundException("Report file not found: $qrCodeHandleJrxmlPath")
}
val inputStream = resource.inputStream
val qrCodeHandleReport = JasperCompileManager.compileReport(inputStream)
resource.inputStream.use { JasperCompileManager.compileReport(it) }
}

/** Cache the chosen Chinese font family name (font scanning is expensive). */
private val chineseFontFamily: String by lazy {
val availableFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().availableFontFamilyNames
availableFonts.find { family ->
family.contains("SimSun", ignoreCase = true) ||
family.contains("Microsoft YaHei", ignoreCase = true) ||
family.contains("STSong", ignoreCase = true) ||
family.contains("SimHei", ignoreCase = true)
} ?: "Arial Unicode MS"
}

fun exportUserQrCode(request: ExportUserQrCodeRequest): Map<String, Any> {
val users = userRepository.findAllById(request.userIds)
val fields = mutableListOf<MutableMap<String, Any>>()
@@ -53,24 +71,33 @@ class UserQrCodeService(
}
val params: MutableMap<String, Any> = mutableMapOf()
// Configure for Chinese character support
// Try to find a Chinese-supporting font
val availableFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().availableFontFamilyNames
val chineseFont = availableFonts.find {
it.contains("SimSun", ignoreCase = true) ||
it.contains("Microsoft YaHei", ignoreCase = true) ||
it.contains("STSong", ignoreCase = true) ||
it.contains("SimHei", ignoreCase = true)
} ?: "Arial Unicode MS" // Fallback

params["net.sf.jasperreports.default.pdf.encoding"] = "Identity-H"
params["net.sf.jasperreports.default.pdf.embedded"] = true
params["net.sf.jasperreports.default.pdf.font.name"] = chineseFont
params["net.sf.jasperreports.default.pdf.font.name"] = chineseFontFamily
return mapOf(
"report" to PdfUtils.fillReport(qrCodeHandleReport, fields, params),
"fileName" to (users.firstOrNull()?.username ?: "user_qrcode")
)
}

fun printUserQrCode(request: PrintUserQrCodeRequest) {
val printer = printerService.findById(request.printerId) ?: throw NoSuchElementException("No such printer")
val pdf = exportUserQrCode(ExportUserQrCodeRequest(request.userIds))
val jasperPrint = pdf["report"] as JasperPrint
val tempPdfFile = File.createTempFile("print_job_", ".pdf")

try {
JasperExportManager.exportReportToPdfFile(jasperPrint, tempPdfFile.absolutePath)
val printQty = if (request.printQty == null || request.printQty <= 0) 1 else request.printQty
printer.ip?.let { ip ->
val port = printer.port ?: 9100
val driver = A4PrintDriverRegistry.getDriver(printer.brand)
driver.print(tempPdfFile, ip, port, printQty)
}
} finally {
tempPdfFile.delete()
}
}
}

+ 7
- 0
src/main/java/com/ffii/fpsms/modules/user/web/PrintUserQrCodeRequest.kt Voir le fichier

@@ -0,0 +1,7 @@
package com.ffii.fpsms.modules.user.web

data class PrintUserQrCodeRequest(
val userIds: List<Long>,
val printerId: Long,
val printQty: Int? = 1,
)

+ 5
- 2
src/main/java/com/ffii/fpsms/modules/user/web/UserController.java Voir le fichier

@@ -42,13 +42,11 @@ import com.ffii.fpsms.modules.user.req.UpdateUserReq;
import com.ffii.fpsms.modules.user.service.UserService;
import com.ffii.fpsms.modules.user.service.res.LoadUserRes;

import com.ffii.fpsms.modules.user.web.ExportUserQrCodeRequest;
import com.ffii.fpsms.modules.user.service.UserQrCodeService;
import jakarta.servlet.http.HttpServletResponse;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperPrint;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
@@ -255,6 +253,11 @@ public class UserController{
out.flush();
}

@PostMapping("/print-qrcode")
public void printQrCode(@Valid @RequestBody PrintUserQrCodeRequest request) {
userQrCodeService.printUserQrCode(request);
}

public static class AdminChangePwdReq {
private Long id;
@NotBlank


Chargement…
Annuler
Enregistrer