Kaynağa Gözat

膠茜數目使用數量 Update

production
B.E.N.S.O.N 1 ay önce
ebeveyn
işleme
b180b73c97
13 değiştirilmiş dosya ile 250 ekleme ve 41 silme
  1. +13
    -27
      src/main/java/com/ffii/fpsms/modules/bag/web/bagController.kt
  2. +30
    -0
      src/main/java/com/ffii/fpsms/modules/jobOrder/service/JoPickOrderService.kt
  3. +104
    -3
      src/main/java/com/ffii/fpsms/modules/jobOrder/service/JobOrderService.kt
  4. +15
    -11
      src/main/java/com/ffii/fpsms/modules/jobOrder/web/JobOrderController.kt
  5. +4
    -0
      src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/ExportPickRecordRequest.kt
  6. +7
    -0
      src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/PickRecordPlasticBoxCartonQtyResponse.kt
  7. +9
    -0
      src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/PlasticBoxCartonQtyDashboardRecord.kt
  8. +4
    -0
      src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/PrintPickRecordRequest.kt
  9. +9
    -0
      src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickOrder.kt
  10. +22
    -0
      src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickOrderRepository.kt
  11. +20
    -0
      src/main/resources/PickRecord/PickRecordPDF.jrxml
  12. +8
    -0
      src/main/resources/db/changelog/changes/20260521_01_plastic_box_carton_qty/01_alter_pick_order_plastic_box_carton_qty.sql
  13. +5
    -0
      src/main/resources/db/changelog/changes/20260521_02_drop_plastic_box_carton_qty_all/01_drop_pick_order_plastic_box_carton_qty_all.sql

+ 13
- 27
src/main/java/com/ffii/fpsms/modules/bag/web/bagController.kt Dosyayı Görüntüle

@@ -1,38 +1,21 @@
package com.ffii.fpsms.modules.bag.web

import com.ffii.core.response.RecordsRes
import com.ffii.fpsms.modules.bag.service.BagService
import jakarta.validation.Valid
import com.ffii.fpsms.modules.bag.web.model.BagConsumptionResponse
import com.ffii.fpsms.modules.bag.web.model.BagInfo
import com.ffii.fpsms.modules.bag.web.model.BagLotLineResponse
import com.ffii.fpsms.modules.bag.web.model.BagSummaryResponse
import com.ffii.fpsms.modules.bag.web.model.BagUsageRecordResponse
import com.ffii.fpsms.modules.bag.web.model.CreateJoBagConsumptionRequest
import com.ffii.fpsms.modules.master.web.models.MessageResponse
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.ModelAttribute
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.PutMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import com.ffii.fpsms.modules.jobOrder.service.JoPickOrderService
import com.ffii.fpsms.modules.productProcess.service.ProductProcessService
import com.ffii.fpsms.modules.jobOrder.web.model.*
import com.ffii.fpsms.modules.jobOrder.web.model.ExportPickRecordRequest
import com.ffii.fpsms.modules.jobOrder.web.model.PrintPickRecordRequest
import com.ffii.fpsms.modules.jobOrder.web.model.SecondScanSubmitRequest
import com.ffii.fpsms.modules.jobOrder.web.model.SecondScanIssueRequest
import jakarta.servlet.http.HttpServletResponse
import net.sf.jasperreports.engine.JasperExportManager
import net.sf.jasperreports.engine.JasperPrint
import org.aspectj.weaver.tools.UnsupportedPointcutPrimitiveException
import org.springframework.context.NoSuchMessageException
import java.io.OutputStream
import java.io.UnsupportedEncodingException
import java.text.ParseException
import org.springframework.web.bind.annotation.*
import org.springframework.web.bind.annotation.RequestParam
import com.ffii.fpsms.modules.jobOrder.web.model.UpdateJoPickOrderHandledByRequest
import com.ffii.fpsms.modules.jobOrder.entity.projections.JobOrderInfo
import com.ffii.fpsms.modules.jobOrder.entity.projections.JobOrderInfoWithTypeName
import com.ffii.fpsms.modules.jobOrder.web.model.ExportFGStockInLabelRequest
import com.ffii.fpsms.modules.bag.web.model.*
import com.ffii.fpsms.modules.master.web.models.MessageResponse

@RestController
@RequestMapping("/bag")
class BagController(
@@ -43,14 +26,17 @@ class BagController(
fun getBagInfo(): List<BagInfo> {
return bagService.getAllBagInfo()
}

@PostMapping("/createJoBagConsumption")
fun createJoBagConsumption(@RequestBody request: CreateJoBagConsumptionRequest): MessageResponse {
return bagService.createJoBagConsumption(request)
}

@GetMapping("/bagUsageRecords")
fun getBagUsageRecords(): List<BagUsageRecordResponse> {
return bagService.getAllBagUsageRecords()
}

@GetMapping("/bags")
fun getBags(): List<BagSummaryResponse> =
bagService.getBagSummaries()
@@ -66,4 +52,4 @@ class BagController(
@PutMapping("/by-item/{itemId}/soft-delete")
fun softDeleteBagByItemId(@PathVariable itemId: Long): MessageResponse =
bagService.softDeleteBagByItemId(itemId)
}
}

+ 30
- 0
src/main/java/com/ffii/fpsms/modules/jobOrder/service/JoPickOrderService.kt Dosyayı Görüntüle

@@ -51,6 +51,7 @@ import com.ffii.fpsms.modules.stock.entity.enum.StockInLineStatus
import com.ffii.fpsms.modules.stock.entity.StockInLineRepository
import java.time.LocalDate
import com.ffii.fpsms.modules.jobOrder.web.model.MaterialPickStatusItem
import com.ffii.fpsms.modules.jobOrder.web.model.PlasticBoxCartonQtyDashboardRecord
@Service
open class JoPickOrderService(
private val joPickOrderRepository: JoPickOrderRepository,
@@ -1688,6 +1689,9 @@ open fun getCompletedJobOrderPickOrders(completedDate: LocalDate?): List<Map<Str
"secondScanCompleted" to secondScanCompleted,
"totalItems" to joPickOrders.size,
"completedItems" to joPickOrders.count { it.matchStatus == JoPickOrderStatus.completed },
"plasticBoxCartonQty2f" to pickOrder.plasticBoxCartonQty2f,
"plasticBoxCartonQty3f" to pickOrder.plasticBoxCartonQty3f,
"plasticBoxCartonQty4f" to pickOrder.plasticBoxCartonQty4f,
)
} else {
println("❌ Pick order ${pickOrder.id} has no job order, skipping.")
@@ -1703,6 +1707,32 @@ open fun getCompletedJobOrderPickOrders(completedDate: LocalDate?): List<Map<Str
emptyList()
}
}

open fun getPlasticBoxCartonQtyDashboard(
from: LocalDate,
to: LocalDate,
): List<PlasticBoxCartonQtyDashboardRecord> {
val fromDt = from.atStartOfDay()
val toExclusive = to.plusDays(1).atStartOfDay()
return pickOrderRepository
.findCompletedWithPlasticBoxCartonQtyInPlanStartRange(
PickOrderStatus.COMPLETED,
fromDt,
toExclusive,
)
.mapNotNull { pickOrder ->
val planStart = pickOrder.jobOrder?.planStart ?: return@mapNotNull null
val statLocalDate = planStart.toLocalDate()
PlasticBoxCartonQtyDashboardRecord(
pickOrderId = pickOrder.id,
statDate = "${statLocalDate.year}-${"%02d".format(statLocalDate.monthValue)}-${"%02d".format(statLocalDate.dayOfMonth)}",
plasticBoxCartonQty2f = pickOrder.plasticBoxCartonQty2f,
plasticBoxCartonQty3f = pickOrder.plasticBoxCartonQty3f,
plasticBoxCartonQty4f = pickOrder.plasticBoxCartonQty4f,
)
}
}

open fun getJobOrderPickOrders(date: LocalDate?, status: PickOrderStatus?): List<Map<String, Any?>> {
println("=== getJobOrderPickOrders ===")
println("date: $date, status: $status")


+ 104
- 3
src/main/java/com/ffii/fpsms/modules/jobOrder/service/JobOrderService.kt Dosyayı Görüntüle

@@ -737,6 +737,92 @@ open class JobOrderService(
}

//Pick Record
private fun validatePickRecordFloor(floor: String?): String {
val normalizedFloor = floor?.trim()?.uppercase()
?: throw BadRequestException("floor is required for pick record print")
if (normalizedFloor !in setOf("2F", "3F", "4F", "ALL")) {
throw BadRequestException("floor must be one of 2F, 3F, 4F, ALL")
}
return normalizedFloor
}

private fun validatePlasticBoxCartonQty(qty: Int?): Int {
val value = qty ?: throw BadRequestException("plasticBoxCartonQty is required")
if (value < 1) {
throw BadRequestException("plasticBoxCartonQty must be at least 1")
}
return value
}

private data class AllFloorsPlasticBoxCartonQty(
val qty2f: Int,
val qty3f: Int,
val qty4f: Int,
val sum: Int,
)

private fun normalizeFloorPlasticBoxCartonQty(qty: Int?): Int {
if (qty == null) return 0
if (qty < 0) {
throw BadRequestException("plastic box carton qty cannot be negative")
}
return qty
}

private fun resolveAllFloorsPlasticBoxCartonQty(
qty2f: Int?,
qty3f: Int?,
qty4f: Int?,
): AllFloorsPlasticBoxCartonQty {
val q2 = normalizeFloorPlasticBoxCartonQty(qty2f)
val q3 = normalizeFloorPlasticBoxCartonQty(qty3f)
val q4 = normalizeFloorPlasticBoxCartonQty(qty4f)
return AllFloorsPlasticBoxCartonQty(q2, q3, q4, q2 + q3 + q4)
}

private fun updatePickOrderPlasticBoxCartonQty(pickOrderId: Long, floor: String, qty: Int) {
val pickOrder = pickOrderRepository.findById(pickOrderId).orElse(null) ?: return
when (floor) {
"2F" -> pickOrder.plasticBoxCartonQty2f = qty
"3F" -> pickOrder.plasticBoxCartonQty3f = qty
"4F" -> pickOrder.plasticBoxCartonQty4f = qty
}
pickOrderRepository.save(pickOrder)
}

private fun persistAllFloorsPlasticBoxCartonQty(pickOrderId: Long, all: AllFloorsPlasticBoxCartonQty) {
updatePickOrderPlasticBoxCartonQty(pickOrderId, "2F", all.qty2f)
updatePickOrderPlasticBoxCartonQty(pickOrderId, "3F", all.qty3f)
updatePickOrderPlasticBoxCartonQty(pickOrderId, "4F", all.qty4f)
}

open fun getPickRecordPlasticBoxCartonQty(pickOrderId: Long): PickRecordPlasticBoxCartonQtyResponse {
val pickOrder = pickOrderRepository.findById(pickOrderId).orElseThrow {
NoSuchElementException("Pick order not found with ID: $pickOrderId")
}
return PickRecordPlasticBoxCartonQtyResponse(
plasticBoxCartonQty2f = pickOrder.plasticBoxCartonQty2f,
plasticBoxCartonQty3f = pickOrder.plasticBoxCartonQty3f,
plasticBoxCartonQty4f = pickOrder.plasticBoxCartonQty4f,
)
}

private fun resolvePlasticBoxCartonQtyForPickRecord(request: ExportPickRecordRequest): Int {
val floor = validatePickRecordFloor(request.floor)
return if (floor == "ALL") {
val all = resolveAllFloorsPlasticBoxCartonQty(
request.plasticBoxCartonQty2f,
request.plasticBoxCartonQty3f,
request.plasticBoxCartonQty4f,
)
persistAllFloorsPlasticBoxCartonQty(request.pickOrderIds, all)
all.sum
} else {
request.plasticBoxCartonQty
?: throw BadRequestException("plasticBoxCartonQty is required")
}
}

@Throws(IOException::class)
@Transactional
open fun exportPickRecord(request: ExportPickRecordRequest): Map<String, Any> {
@@ -821,6 +907,8 @@ open class JobOrderService(
println("unit (from BOM): $unit")*/

params["unit"] = pickRecordInfo.firstOrNull()?.get("uomConversionDesc") as? String ?: "N/A"
val plasticBoxCartonQtyForPdf = resolvePlasticBoxCartonQtyForPickRecord(request)
params["PlasticBoxCartonQty"] = plasticBoxCartonQtyForPdf.toString()

val pickOrderCode = pickRecordInfo.firstOrNull()?.get("pickOrderCode") as? String ?: "unknown"
return mapOf(
@@ -833,13 +921,26 @@ open class JobOrderService(
@Transactional
open fun printPickRecord(request: PrintPickRecordRequest){
val printer = printerService.findById(request.printerId) ?: throw java.util.NoSuchElementException("No such printer")
val pdf = exportPickRecord(
val floor = validatePickRecordFloor(request.floor)
val exportRequest = if (floor == "ALL") {
ExportPickRecordRequest(
pickOrderIds = request.pickOrderId,
floor = request.floor,
plasticBoxCartonQty2f = request.plasticBoxCartonQty2f,
plasticBoxCartonQty3f = request.plasticBoxCartonQty3f,
plasticBoxCartonQty4f = request.plasticBoxCartonQty4f,
)
)
} else {
val plasticBoxCartonQty = validatePlasticBoxCartonQty(request.plasticBoxCartonQty)
updatePickOrderPlasticBoxCartonQty(request.pickOrderId, floor, plasticBoxCartonQty)
ExportPickRecordRequest(
pickOrderIds = request.pickOrderId,
floor = request.floor,
plasticBoxCartonQty = plasticBoxCartonQty,
)
}

val pdf = exportPickRecord(exportRequest)

val jasperPrint = pdf["report"] as JasperPrint



+ 15
- 11
src/main/java/com/ffii/fpsms/modules/jobOrder/web/JobOrderController.kt Dosyayı Görüntüle

@@ -27,7 +27,6 @@ import com.ffii.fpsms.modules.pickOrder.enums.PickOrderStatus
import org.springframework.format.annotation.DateTimeFormat
import com.ffii.fpsms.modules.productProcess.service.ProductProcessService
import com.ffii.fpsms.modules.jobOrder.web.model.*
import com.ffii.fpsms.modules.jobOrder.web.model.ExportPickRecordRequest
import com.ffii.fpsms.modules.jobOrder.web.model.PrintPickRecordRequest
import com.ffii.fpsms.modules.jobOrder.web.model.SecondScanSubmitRequest
import com.ffii.fpsms.modules.jobOrder.web.model.SecondScanIssueRequest
@@ -224,16 +223,9 @@ fun recordSecondScanIssue(
return joPickOrderService.getCompletedJobOrderPickOrderLotDetails(pickOrderId)
}

@PostMapping("/PickRecord")
@Throws(UnsupportedEncodingException::class, NoSuchMessageException::class, ParseException::class, Exception::class)
fun printPickRecord(@Valid @RequestBody request: ExportPickRecordRequest, response: HttpServletResponse){
response.characterEncoding = "utf-8"
response.contentType = "application/pdf"
val out: OutputStream = response.outputStream
val pdf = jobOrderService.exportPickRecord(request)
val jasperPrint = pdf["report"] as JasperPrint
response.addHeader("filename", "${pdf["filename"]}.pdf")
out.write(JasperExportManager.exportReportToPdf(jasperPrint))
@GetMapping("/pick-record-plastic-box-carton-qty/{pickOrderId}")
fun getPickRecordPlasticBoxCartonQty(@PathVariable pickOrderId: Long): PickRecordPlasticBoxCartonQtyResponse {
return jobOrderService.getPickRecordPlasticBoxCartonQty(pickOrderId)
}

@GetMapping("/print-PickRecord")
@@ -272,6 +264,18 @@ fun recordSecondScanIssue(
): List<Map<String, Any?>> {
return joPickOrderService.getCompletedJobOrderPickOrders(completedDate)
}

@GetMapping("/plastic-box-carton-qty-dashboard")
fun getPlasticBoxCartonQtyDashboard(
@RequestParam(name = "from")
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
from: LocalDate,
@RequestParam(name = "to")
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
to: LocalDate,
): List<PlasticBoxCartonQtyDashboardRecord> {
return joPickOrderService.getPlasticBoxCartonQtyDashboard(from, to)
}
@GetMapping("/job-order-pick-orders")
fun getJobOrderPickOrders(
@RequestParam(name = "date", required = false)


+ 4
- 0
src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/ExportPickRecordRequest.kt Dosyayı Görüntüle

@@ -3,4 +3,8 @@ package com.ffii.fpsms.modules.jobOrder.web.model
data class ExportPickRecordRequest (
val pickOrderIds: Long,
val floor: String? = null,
val plasticBoxCartonQty: Int? = null,
val plasticBoxCartonQty2f: Int? = null,
val plasticBoxCartonQty3f: Int? = null,
val plasticBoxCartonQty4f: Int? = null,
)

+ 7
- 0
src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/PickRecordPlasticBoxCartonQtyResponse.kt Dosyayı Görüntüle

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

data class PickRecordPlasticBoxCartonQtyResponse(
val plasticBoxCartonQty2f: Int?,
val plasticBoxCartonQty3f: Int?,
val plasticBoxCartonQty4f: Int?,
)

+ 9
- 0
src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/PlasticBoxCartonQtyDashboardRecord.kt Dosyayı Görüntüle

@@ -0,0 +1,9 @@
package com.ffii.fpsms.modules.jobOrder.web.model

data class PlasticBoxCartonQtyDashboardRecord(
val pickOrderId: Long?,
val statDate: String,
val plasticBoxCartonQty2f: Int? = null,
val plasticBoxCartonQty3f: Int? = null,
val plasticBoxCartonQty4f: Int? = null,
)

+ 4
- 0
src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/PrintPickRecordRequest.kt Dosyayı Görüntüle

@@ -5,4 +5,8 @@ data class PrintPickRecordRequest(
val printerId: Long,
val printQty: Int?,
val floor: String? = null,
val plasticBoxCartonQty: Int? = null,
val plasticBoxCartonQty2f: Int? = null,
val plasticBoxCartonQty3f: Int? = null,
val plasticBoxCartonQty4f: Int? = null,
)

+ 9
- 0
src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickOrder.kt Dosyayı Görüntüle

@@ -72,4 +72,13 @@ open class PickOrder: BaseEntity<Long>() {

@Column(name = "submittedLines")
open var submittedLines: Int? = null

@Column(name = "plastic_box_carton_qty_2f")
open var plasticBoxCartonQty2f: Int? = null

@Column(name = "plastic_box_carton_qty_3f")
open var plasticBoxCartonQty3f: Int? = null

@Column(name = "plastic_box_carton_qty_4f")
open var plasticBoxCartonQty4f: Int? = null
}

+ 22
- 0
src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickOrderRepository.kt Dosyayı Görüntüle

@@ -135,6 +135,28 @@ fun findAllCompletedWithJobOrderPlanStartOnDay(
@Param("planStartToExclusive") planStartToExclusive: LocalDateTime,
): List<PickOrder>

@Query(
"""
SELECT po FROM PickOrder po
WHERE po.status = :status
AND po.deleted = false
AND po.jobOrder IS NOT NULL
AND po.jobOrder.planStart IS NOT NULL
AND po.jobOrder.planStart >= :planStartFrom
AND po.jobOrder.planStart < :planStartToExclusive
AND (
po.plasticBoxCartonQty2f IS NOT NULL
OR po.plasticBoxCartonQty3f IS NOT NULL
OR po.plasticBoxCartonQty4f IS NOT NULL
)
"""
)
fun findCompletedWithPlasticBoxCartonQtyInPlanStartRange(
@Param("status") status: PickOrderStatus,
@Param("planStartFrom") planStartFrom: LocalDateTime,
@Param("planStartToExclusive") planStartToExclusive: LocalDateTime,
): List<PickOrder>


@Modifying(clearAutomatically = true, flushAutomatically = true)
@Query(


+ 20
- 0
src/main/resources/PickRecord/PickRecordPDF.jrxml Dosyayı Görüntüle

@@ -8,6 +8,7 @@
<parameter name="FGName" class="java.lang.String"/>
<parameter name="RequiredQuantity" class="java.lang.String"/>
<parameter name="Floor" class="java.lang.String"/>
<parameter name="PlasticBoxCartonQty" class="java.lang.String"/>
<queryString>
<![CDATA[]]>
</queryString>
@@ -24,6 +25,25 @@
</background>
<pageHeader>
<band height="103" splitType="Stretch">
<staticText>
<reportElement x="5" y="5" width="70" height="18" uuid="a1b2c3d4-e5f6-7890-abcd-ef1234567890">
<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"/>
</textElement>
<text><![CDATA[膠茜數目:]]></text>
</staticText>
<textField>
<reportElement x="75" y="5" width="80" height="18" uuid="b2c3d4e5-f6a7-8901-bcde-f12345678901">
<property name="com.jaspersoft.studio.unit.height" value="px"/>
</reportElement>
<textElement verticalAlignment="Middle">
<font fontName="微軟正黑體" size="12"/>
</textElement>
<textFieldExpression><![CDATA[$P{PlasticBoxCartonQty}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="180" y="5" width="153" height="23" uuid="324397fb-d07b-4748-a917-7de93ebbe012">
<property name="com.jaspersoft.studio.unit.width" value="px"/>


+ 8
- 0
src/main/resources/db/changelog/changes/20260521_01_plastic_box_carton_qty/01_alter_pick_order_plastic_box_carton_qty.sql Dosyayı Görüntüle

@@ -0,0 +1,8 @@
-- liquibase formatted sql
-- changeset fpsms:alter_pick_order_plastic_box_carton_qty

ALTER TABLE `pick_order`
ADD COLUMN `plastic_box_carton_qty_2f` INT NULL DEFAULT NULL AFTER `submittedLines`,
ADD COLUMN `plastic_box_carton_qty_3f` INT NULL DEFAULT NULL AFTER `plastic_box_carton_qty_2f`,
ADD COLUMN `plastic_box_carton_qty_4f` INT NULL DEFAULT NULL AFTER `plastic_box_carton_qty_3f`,
ADD COLUMN `plastic_box_carton_qty_all` INT NULL DEFAULT NULL AFTER `plastic_box_carton_qty_4f`;

+ 5
- 0
src/main/resources/db/changelog/changes/20260521_02_drop_plastic_box_carton_qty_all/01_drop_pick_order_plastic_box_carton_qty_all.sql Dosyayı Görüntüle

@@ -0,0 +1,5 @@
-- liquibase formatted sql
-- changeset fpsms:drop_pick_order_plastic_box_carton_qty_all

ALTER TABLE `pick_order`
DROP COLUMN `plastic_box_carton_qty_all`;

Yükleniyor…
İptal
Kaydet