| @@ -9,13 +9,23 @@ class FGStockOutTraceabilityReportService( | |||||
| ) { | ) { | ||||
| fun getDistinctHandlersForFGStockOutTraceability(): List<String> { | fun getDistinctHandlersForFGStockOutTraceability(): List<String> { | ||||
| val sql = """ | val sql = """ | ||||
| SELECT DISTINCT COALESCE(picker_user.name, modified_user.name, '') AS handler | |||||
| FROM stock_out_line sol | |||||
| INNER JOIN stock_out so ON sol.stockOutId = so.id AND so.deleted = 0 AND so.type = 'do' | |||||
| LEFT JOIN user picker_user ON sol.handled_by = picker_user.id AND picker_user.deleted = 0 | |||||
| LEFT JOIN user modified_user ON sol.modifiedBy = modified_user.staffNo AND modified_user.deleted = 0 AND sol.handled_by IS NULL | |||||
| WHERE sol.deleted = 0 | |||||
| ORDER BY handler | |||||
| SELECT DISTINCT h.handler | |||||
| FROM ( | |||||
| SELECT TRIM(COALESCE(picker_user.name, modified_user.name, '')) AS handler | |||||
| FROM stock_out_line sol | |||||
| INNER JOIN stock_out so ON sol.stockOutId = so.id AND so.deleted = 0 AND so.type = 'do' | |||||
| LEFT JOIN user picker_user ON sol.handled_by = picker_user.id AND picker_user.deleted = 0 | |||||
| LEFT JOIN user modified_user ON sol.modifiedBy = modified_user.staffNo AND modified_user.deleted = 0 AND sol.handled_by IS NULL | |||||
| WHERE sol.deleted = 0 | |||||
| UNION | |||||
| SELECT TRIM(IFNULL(handlerName, '')) AS handler | |||||
| FROM delivery_order_pick_order | |||||
| WHERE deleted = 0 | |||||
| AND ticketStatus = 'completed' | |||||
| AND IFNULL(handlerName, '') <> '' | |||||
| ) h | |||||
| WHERE TRIM(IFNULL(h.handler, '')) <> '' | |||||
| ORDER BY h.handler | |||||
| """.trimIndent() | """.trimIndent() | ||||
| return jdbcDao | return jdbcDao | ||||
| @@ -54,7 +64,7 @@ class FGStockOutTraceabilityReportService( | |||||
| val yearSql = if (!year.isNullOrBlank()) { | val yearSql = if (!year.isNullOrBlank()) { | ||||
| args["year"] = year | args["year"] = year | ||||
| "AND YEAR(IFNULL(dpor.RequiredDeliveryDate, do.estimatedArrivalDate)) = :year" | |||||
| "AND YEAR(IFNULL(dopo.requiredDeliveryDate, do.estimatedArrivalDate)) = :year" | |||||
| } else { | } else { | ||||
| "" | "" | ||||
| } | } | ||||
| @@ -62,7 +72,7 @@ class FGStockOutTraceabilityReportService( | |||||
| val lastOutDateStartSql = if (!lastOutDateStart.isNullOrBlank()) { | val lastOutDateStartSql = if (!lastOutDateStart.isNullOrBlank()) { | ||||
| val formattedDate = lastOutDateStart.replace("/", "-") | val formattedDate = lastOutDateStart.replace("/", "-") | ||||
| args["lastOutDateStart"] = formattedDate | args["lastOutDateStart"] = formattedDate | ||||
| "AND DATE(IFNULL(dpor.RequiredDeliveryDate, do.estimatedArrivalDate)) >= DATE(:lastOutDateStart)" | |||||
| "AND DATE(IFNULL(dopo.requiredDeliveryDate, do.estimatedArrivalDate)) >= DATE(:lastOutDateStart)" | |||||
| } else { | } else { | ||||
| "" | "" | ||||
| } | } | ||||
| @@ -70,14 +80,14 @@ class FGStockOutTraceabilityReportService( | |||||
| val lastOutDateEndSql = if (!lastOutDateEnd.isNullOrBlank()) { | val lastOutDateEndSql = if (!lastOutDateEnd.isNullOrBlank()) { | ||||
| val formattedDate = lastOutDateEnd.replace("/", "-") | val formattedDate = lastOutDateEnd.replace("/", "-") | ||||
| args["lastOutDateEnd"] = formattedDate | args["lastOutDateEnd"] = formattedDate | ||||
| "AND DATE(IFNULL(dpor.RequiredDeliveryDate, do.estimatedArrivalDate)) <= DATE(:lastOutDateEnd)" | |||||
| "AND DATE(IFNULL(dopo.requiredDeliveryDate, do.estimatedArrivalDate)) <= DATE(:lastOutDateEnd)" | |||||
| } else { | } else { | ||||
| "" | "" | ||||
| } | } | ||||
| val handlerSql = buildMultiValueExactClause( | val handlerSql = buildMultiValueExactClause( | ||||
| handler, | handler, | ||||
| "COALESCE(picker_user.name, modified_user.name, '')", | |||||
| "COALESCE(picker_user.name, modified_user.name, IFNULL(dopo.handlerName, ''))", | |||||
| "handler", | "handler", | ||||
| args, | args, | ||||
| ) | ) | ||||
| @@ -85,13 +95,13 @@ class FGStockOutTraceabilityReportService( | |||||
| val sql = """ | val sql = """ | ||||
| SELECT | SELECT | ||||
| IFNULL(DATE_FORMAT( | IFNULL(DATE_FORMAT( | ||||
| IFNULL(dpor.RequiredDeliveryDate, do.estimatedArrivalDate), | |||||
| IFNULL(dopo.requiredDeliveryDate, do.estimatedArrivalDate), | |||||
| '%Y-%m-%d' | '%Y-%m-%d' | ||||
| ), '') AS deliveryDate, | ), '') AS deliveryDate, | ||||
| IFNULL(it.code, '') AS itemNo, | IFNULL(it.code, '') AS itemNo, | ||||
| IFNULL(it.name, '') AS itemName, | IFNULL(it.name, '') AS itemName, | ||||
| IFNULL(uc.udfudesc, '') AS unitOfMeasure, | IFNULL(uc.udfudesc, '') AS unitOfMeasure, | ||||
| IFNULL(dpor.deliveryNoteCode, '') AS dnNo, | |||||
| IFNULL(dopo.deliveryNoteCode, '') AS dnNo, | |||||
| CAST(IFNULL(sp.id, 0) AS CHAR) AS customerId, | CAST(IFNULL(sp.id, 0) AS CHAR) AS customerId, | ||||
| IFNULL(sp.name, '') AS customerName, | IFNULL(sp.name, '') AS customerName, | ||||
| FORMAT( | FORMAT( | ||||
| @@ -109,11 +119,13 @@ class FGStockOutTraceabilityReportService( | |||||
| COALESCE( | COALESCE( | ||||
| picker_user.name, | picker_user.name, | ||||
| modified_user.name, | modified_user.name, | ||||
| dopo.handlerName, | |||||
| '' | '' | ||||
| ) AS handler, | ) AS handler, | ||||
| COALESCE( | COALESCE( | ||||
| picker_user.name, | picker_user.name, | ||||
| modified_user.name, | modified_user.name, | ||||
| dopo.handlerName, | |||||
| '' | '' | ||||
| ) AS pickedBy, | ) AS pickedBy, | ||||
| GROUP_CONCAT(DISTINCT wh.code ORDER BY wh.code SEPARATOR ', ') AS storeLocation, | GROUP_CONCAT(DISTINCT wh.code ORDER BY wh.code SEPARATOR ', ') AS storeLocation, | ||||
| @@ -122,19 +134,22 @@ class FGStockOutTraceabilityReportService( | |||||
| ROUND(SUM(IFNULL(sol.qty, 0)) OVER (PARTITION BY it.code), 0), 0 | ROUND(SUM(IFNULL(sol.qty, 0)) OVER (PARTITION BY it.code), 0), 0 | ||||
| ) AS totalStockOutQty, | ) AS totalStockOutQty, | ||||
| 0 AS stockSubCategory | 0 AS stockSubCategory | ||||
| FROM do_pick_order_line_record dpolr | |||||
| LEFT JOIN do_pick_order_record dpor | |||||
| ON dpolr.record_id = dpor.id | |||||
| AND dpor.deleted = 0 | |||||
| AND dpor.ticket_status = 'completed' | |||||
| FROM delivery_order_pick_order dopo | |||||
| INNER JOIN pick_order po | |||||
| ON po.deliveryOrderPickOrderId = dopo.id | |||||
| AND po.deleted = 0 | |||||
| INNER JOIN delivery_order do | INNER JOIN delivery_order do | ||||
| ON dpolr.do_order_id = do.id | |||||
| ON po.doId = do.id | |||||
| AND do.deleted = 0 | AND do.deleted = 0 | ||||
| LEFT JOIN shop sp | LEFT JOIN shop sp | ||||
| ON do.shopId = sp.id | ON do.shopId = sp.id | ||||
| AND sp.deleted = 0 | AND sp.deleted = 0 | ||||
| LEFT JOIN pick_order_line pol | |||||
| ON pol.poId = po.id | |||||
| AND pol.deleted = 0 | |||||
| LEFT JOIN delivery_order_line dol | LEFT JOIN delivery_order_line dol | ||||
| ON do.id = dol.deliveryOrderId | |||||
| ON dol.deliveryOrderId = do.id | |||||
| AND dol.itemId = pol.itemId | |||||
| AND dol.deleted = 0 | AND dol.deleted = 0 | ||||
| LEFT JOIN items it | LEFT JOIN items it | ||||
| ON dol.itemId = it.id | ON dol.itemId = it.id | ||||
| @@ -144,13 +159,6 @@ class FGStockOutTraceabilityReportService( | |||||
| AND iu.stockUnit = 1 | AND iu.stockUnit = 1 | ||||
| LEFT JOIN uom_conversion uc | LEFT JOIN uom_conversion uc | ||||
| ON iu.uomId = uc.id | ON iu.uomId = uc.id | ||||
| LEFT JOIN pick_order_line pol | |||||
| ON dpolr.pick_order_id = pol.poId | |||||
| AND pol.itemId = it.id | |||||
| AND pol.deleted = 0 | |||||
| LEFT JOIN pick_order po | |||||
| ON pol.poId = po.id | |||||
| AND po.deleted = 0 | |||||
| LEFT JOIN stock_out_line sol | LEFT JOIN stock_out_line sol | ||||
| ON pol.id = sol.pickOrderLineId | ON pol.id = sol.pickOrderLineId | ||||
| AND sol.itemId = it.id | AND sol.itemId = it.id | ||||
| @@ -176,7 +184,8 @@ class FGStockOutTraceabilityReportService( | |||||
| AND modified_user.deleted = 0 | AND modified_user.deleted = 0 | ||||
| AND sol.handled_by IS NULL | AND sol.handled_by IS NULL | ||||
| WHERE | WHERE | ||||
| dpolr.deleted = 0 | |||||
| dopo.deleted = 0 | |||||
| AND dopo.ticketStatus = 'completed' | |||||
| $stockCategorySql | $stockCategorySql | ||||
| $stockSubCategorySql | $stockSubCategorySql | ||||
| $itemCodeSql | $itemCodeSql | ||||
| @@ -186,12 +195,13 @@ class FGStockOutTraceabilityReportService( | |||||
| $handlerSql | $handlerSql | ||||
| GROUP BY | GROUP BY | ||||
| sol.id, | sol.id, | ||||
| dpor.RequiredDeliveryDate, | |||||
| dopo.requiredDeliveryDate, | |||||
| dopo.handlerName, | |||||
| do.estimatedArrivalDate, | do.estimatedArrivalDate, | ||||
| it.code, | it.code, | ||||
| it.name, | it.name, | ||||
| uc.udfudesc, | uc.udfudesc, | ||||
| dpor.deliveryNoteCode, | |||||
| dopo.deliveryNoteCode, | |||||
| sp.id, | sp.id, | ||||
| sp.name, | sp.name, | ||||
| sol.qty, | sol.qty, | ||||
| @@ -101,7 +101,7 @@ open class ReportService( | |||||
| val yearSql = if (!year.isNullOrBlank()) { | val yearSql = if (!year.isNullOrBlank()) { | ||||
| args["year"] = year | args["year"] = year | ||||
| "AND YEAR(IFNULL(dpor.RequiredDeliveryDate, do.estimatedArrivalDate)) = :year" | |||||
| "AND YEAR(IFNULL(dopo.requiredDeliveryDate, do.estimatedArrivalDate)) = :year" | |||||
| } else { | } else { | ||||
| "" | "" | ||||
| } | } | ||||
| @@ -109,25 +109,25 @@ open class ReportService( | |||||
| val lastOutDateStartSql = if (!lastOutDateStart.isNullOrBlank()) { | val lastOutDateStartSql = if (!lastOutDateStart.isNullOrBlank()) { | ||||
| val formattedDate = lastOutDateStart.replace("/", "-") | val formattedDate = lastOutDateStart.replace("/", "-") | ||||
| args["lastOutDateStart"] = formattedDate | args["lastOutDateStart"] = formattedDate | ||||
| "AND DATE(IFNULL(dpor.RequiredDeliveryDate, do.estimatedArrivalDate)) >= DATE(:lastOutDateStart)" | |||||
| "AND DATE(IFNULL(dopo.requiredDeliveryDate, do.estimatedArrivalDate)) >= DATE(:lastOutDateStart)" | |||||
| } else "" | } else "" | ||||
| val lastOutDateEndSql = if (!lastOutDateEnd.isNullOrBlank()) { | val lastOutDateEndSql = if (!lastOutDateEnd.isNullOrBlank()) { | ||||
| val formattedDate = lastOutDateEnd.replace("/", "-") | val formattedDate = lastOutDateEnd.replace("/", "-") | ||||
| args["lastOutDateEnd"] = formattedDate | args["lastOutDateEnd"] = formattedDate | ||||
| "AND DATE(IFNULL(dpor.RequiredDeliveryDate, do.estimatedArrivalDate)) <= DATE(:lastOutDateEnd)" | |||||
| "AND DATE(IFNULL(dopo.requiredDeliveryDate, do.estimatedArrivalDate)) <= DATE(:lastOutDateEnd)" | |||||
| } else "" | } else "" | ||||
| val sql = """ | val sql = """ | ||||
| SELECT | SELECT | ||||
| IFNULL(DATE_FORMAT( | IFNULL(DATE_FORMAT( | ||||
| IFNULL(dpor.RequiredDeliveryDate, do.estimatedArrivalDate), | |||||
| IFNULL(dopo.requiredDeliveryDate, do.estimatedArrivalDate), | |||||
| '%Y-%m-%d' | '%Y-%m-%d' | ||||
| ), '') AS deliveryDate, | ), '') AS deliveryDate, | ||||
| IFNULL(it.code, '') AS itemNo, | IFNULL(it.code, '') AS itemNo, | ||||
| IFNULL(it.name, '') AS itemName, | IFNULL(it.name, '') AS itemName, | ||||
| IFNULL(uc.udfudesc, '') AS unitOfMeasure, | IFNULL(uc.udfudesc, '') AS unitOfMeasure, | ||||
| IFNULL(dpor.deliveryNoteCode, '') AS dnNo, | |||||
| IFNULL(dopo.deliveryNoteCode, '') AS dnNo, | |||||
| CAST(IFNULL(sp.id, 0) AS CHAR) AS customerId, | CAST(IFNULL(sp.id, 0) AS CHAR) AS customerId, | ||||
| IFNULL(sp.name, '') AS customerName, | IFNULL(sp.name, '') AS customerName, | ||||
| CAST( | CAST( | ||||
| @@ -138,7 +138,7 @@ open class ReportService( | |||||
| FORMAT(ROUND(IFNULL(IFNULL(sol.qty, dol.qty), 0), 0), 0) AS qty, | FORMAT(ROUND(IFNULL(IFNULL(sol.qty, dol.qty), 0), 0), 0) AS qty, | ||||
| COALESCE( | COALESCE( | ||||
| dpor.TruckLanceCode, | |||||
| dopo.truckLanceCode, | |||||
| (SELECT t2.TruckLanceCode | (SELECT t2.TruckLanceCode | ||||
| FROM truck t2 | FROM truck t2 | ||||
| WHERE t2.shopId = do.shopId | WHERE t2.shopId = do.shopId | ||||
| @@ -157,9 +157,9 @@ FORMAT(ROUND(IFNULL(IFNULL(sol.qty, dol.qty), 0), 0), 0) AS qty, | |||||
| AND (SELECT COUNT(*) FROM truck t3 | AND (SELECT COUNT(*) FROM truck t3 | ||||
| WHERE t3.shopId = do.shopId AND t3.deleted = 0 | WHERE t3.shopId = do.shopId AND t3.deleted = 0 | ||||
| AND t3.Store_id = '4F') > 1 | AND t3.Store_id = '4F') > 1 | ||||
| AND IFNULL(dpor.RequiredDeliveryDate, do.estimatedArrivalDate) IS NOT NULL | |||||
| AND IFNULL(dopo.requiredDeliveryDate, do.estimatedArrivalDate) IS NOT NULL | |||||
| AND t2.TruckLanceCode LIKE CONCAT('%', | AND t2.TruckLanceCode LIKE CONCAT('%', | ||||
| CASE DAYNAME(IFNULL(dpor.RequiredDeliveryDate, do.estimatedArrivalDate)) | |||||
| CASE DAYNAME(IFNULL(dopo.requiredDeliveryDate, do.estimatedArrivalDate)) | |||||
| WHEN 'Monday' THEN 'Mon' | WHEN 'Monday' THEN 'Mon' | ||||
| WHEN 'Tuesday' THEN 'Tue' | WHEN 'Tuesday' THEN 'Tue' | ||||
| WHEN 'Wednesday' THEN 'Wed' | WHEN 'Wednesday' THEN 'Wed' | ||||
| @@ -183,13 +183,12 @@ FORMAT(ROUND(IFNULL(IFNULL(sol.qty, dol.qty), 0), 0), 0) AS qty, | |||||
| '' AS driver, | '' AS driver, | ||||
| IFNULL(do.code, '') AS deliveryOrderNo, | IFNULL(do.code, '') AS deliveryOrderNo, | ||||
| IFNULL(qc.name, '') AS stockSubCategory | IFNULL(qc.name, '') AS stockSubCategory | ||||
| FROM do_pick_order_line_record dpolr | |||||
| LEFT JOIN do_pick_order_record dpor | |||||
| ON dpolr.do_pick_order_id = dpor.record_id | |||||
| AND dpor.deleted = 0 | |||||
| AND dpor.ticket_status = 'completed' | |||||
| FROM delivery_order_pick_order dopo | |||||
| INNER JOIN pick_order po | |||||
| ON po.deliveryOrderPickOrderId = dopo.id | |||||
| AND po.deleted = 0 | |||||
| INNER JOIN delivery_order do | INNER JOIN delivery_order do | ||||
| ON dpolr.do_order_id = do.id | |||||
| ON po.doId = do.id | |||||
| AND do.deleted = 0 | AND do.deleted = 0 | ||||
| LEFT JOIN shop supplier | LEFT JOIN shop supplier | ||||
| ON do.supplierId = supplier.id | ON do.supplierId = supplier.id | ||||
| @@ -197,8 +196,12 @@ FORMAT(ROUND(IFNULL(IFNULL(sol.qty, dol.qty), 0), 0), 0) AS qty, | |||||
| LEFT JOIN shop sp | LEFT JOIN shop sp | ||||
| ON do.shopId = sp.id | ON do.shopId = sp.id | ||||
| AND sp.deleted = 0 | AND sp.deleted = 0 | ||||
| LEFT JOIN pick_order_line pol | |||||
| ON pol.poId = po.id | |||||
| AND pol.deleted = 0 | |||||
| LEFT JOIN delivery_order_line dol | LEFT JOIN delivery_order_line dol | ||||
| ON do.id = dol.deliveryOrderId | |||||
| ON dol.deliveryOrderId = do.id | |||||
| AND dol.itemId = pol.itemId | |||||
| AND dol.deleted = 0 | AND dol.deleted = 0 | ||||
| LEFT JOIN items it | LEFT JOIN items it | ||||
| ON dol.itemId = it.id | ON dol.itemId = it.id | ||||
| @@ -215,10 +218,6 @@ FORMAT(ROUND(IFNULL(IFNULL(sol.qty, dol.qty), 0), 0), 0) AS qty, | |||||
| AND iu.stockUnit = 1 | AND iu.stockUnit = 1 | ||||
| LEFT JOIN uom_conversion uc | LEFT JOIN uom_conversion uc | ||||
| ON iu.uomId = uc.id | ON iu.uomId = uc.id | ||||
| LEFT JOIN pick_order_line pol | |||||
| ON dpolr.pick_order_id = pol.poId | |||||
| AND pol.itemId = it.id | |||||
| AND pol.deleted = 0 | |||||
| LEFT JOIN stock_out_line sol | LEFT JOIN stock_out_line sol | ||||
| ON pol.id = sol.pickOrderLineId | ON pol.id = sol.pickOrderLineId | ||||
| AND sol.itemId = it.id | AND sol.itemId = it.id | ||||
| @@ -234,8 +233,8 @@ FORMAT(ROUND(IFNULL(IFNULL(sol.qty, dol.qty), 0), 0), 0) AS qty, | |||||
| ON il.stockInLineId = sil.id | ON il.stockInLineId = sil.id | ||||
| AND sil.deleted = 0 | AND sil.deleted = 0 | ||||
| WHERE | WHERE | ||||
| dpolr.deleted = 0 | |||||
| AND (dpor.id IS NULL OR dpor.ticket_status = 'completed') | |||||
| dopo.deleted = 0 | |||||
| AND dopo.ticketStatus = 'completed' | |||||
| AND COALESCE(sol.qty, dol.qty, 0) <> 0 | AND COALESCE(sol.qty, dol.qty, 0) <> 0 | ||||
| $stockCategorySql | $stockCategorySql | ||||
| $stockSubCategorySql | $stockSubCategorySql | ||||
| @@ -258,13 +257,23 @@ return result | |||||
| fun getDistinctHandlersForFGStockOutTraceability(): List<String> { | fun getDistinctHandlersForFGStockOutTraceability(): List<String> { | ||||
| val sql = """ | val sql = """ | ||||
| SELECT DISTINCT COALESCE(picker_user.name, modified_user.name, '') AS handler | |||||
| FROM stock_out_line sol | |||||
| INNER JOIN stock_out so ON sol.stockOutId = so.id AND so.deleted = 0 AND so.type = 'do' | |||||
| LEFT JOIN user picker_user ON sol.handled_by = picker_user.id AND picker_user.deleted = 0 | |||||
| LEFT JOIN user modified_user ON sol.modifiedBy = modified_user.staffNo AND modified_user.deleted = 0 AND sol.handled_by IS NULL | |||||
| WHERE sol.deleted = 0 | |||||
| ORDER BY handler | |||||
| SELECT DISTINCT h.handler | |||||
| FROM ( | |||||
| SELECT TRIM(COALESCE(picker_user.name, modified_user.name, '')) AS handler | |||||
| FROM stock_out_line sol | |||||
| INNER JOIN stock_out so ON sol.stockOutId = so.id AND so.deleted = 0 AND so.type = 'do' | |||||
| LEFT JOIN user picker_user ON sol.handled_by = picker_user.id AND picker_user.deleted = 0 | |||||
| LEFT JOIN user modified_user ON sol.modifiedBy = modified_user.staffNo AND modified_user.deleted = 0 AND sol.handled_by IS NULL | |||||
| WHERE sol.deleted = 0 | |||||
| UNION | |||||
| SELECT TRIM(IFNULL(handlerName, '')) AS handler | |||||
| FROM delivery_order_pick_order | |||||
| WHERE deleted = 0 | |||||
| AND ticketStatus = 'completed' | |||||
| AND IFNULL(handlerName, '') <> '' | |||||
| ) h | |||||
| WHERE TRIM(IFNULL(h.handler, '')) <> '' | |||||
| ORDER BY h.handler | |||||
| """.trimIndent() | """.trimIndent() | ||||
| return jdbcDao.queryForList(sql, emptyMap<String, Any>()).map { row -> (row["handler"]?.toString() ?: "").trim() }.filter { it.isNotBlank() } | return jdbcDao.queryForList(sql, emptyMap<String, Any>()).map { row -> (row["handler"]?.toString() ?: "").trim() }.filter { it.isNotBlank() } | ||||
| } | } | ||||
| @@ -1,11 +1,12 @@ | |||||
| package com.ffii.fpsms.modules.stock.entity | package com.ffii.fpsms.modules.stock.entity | ||||
| import com.ffii.core.support.AbstractRepository | import com.ffii.core.support.AbstractRepository | ||||
| import org.springframework.data.domain.Page | |||||
| import org.springframework.data.domain.Pageable | |||||
| import org.springframework.data.jpa.repository.Query | import org.springframework.data.jpa.repository.Query | ||||
| import org.springframework.data.repository.query.Param | import org.springframework.data.repository.query.Param | ||||
| import org.springframework.stereotype.Repository | import org.springframework.stereotype.Repository | ||||
| import java.time.LocalDate | |||||
| import java.util.Optional | |||||
| import java.time.LocalDateTime | |||||
| @Repository | @Repository | ||||
| interface StockLedgerRepository: AbstractRepository<StockLedger, Long> { | interface StockLedgerRepository: AbstractRepository<StockLedger, Long> { | ||||
| @@ -19,17 +20,17 @@ interface StockLedgerRepository: AbstractRepository<StockLedger, Long> { | |||||
| AND (:itemCode IS NULL OR sl.itemCode LIKE CONCAT('%', :itemCode, '%')) | AND (:itemCode IS NULL OR sl.itemCode LIKE CONCAT('%', :itemCode, '%')) | ||||
| AND (:itemName IS NULL OR i.name LIKE CONCAT('%', :itemName, '%')) | AND (:itemName IS NULL OR i.name LIKE CONCAT('%', :itemName, '%')) | ||||
| AND (:type IS NULL OR sl.type = :type) | AND (:type IS NULL OR sl.type = :type) | ||||
| AND (:startDate IS NULL OR DATE(sl.created) >= :startDate) | |||||
| AND (:endDate IS NULL OR DATE(sl.created) <= :endDate) | |||||
| ORDER BY sl.created ASC, sl.itemId | |||||
| AND (:startDateTime IS NULL OR sl.created >= :startDateTime) | |||||
| AND (:endDateExclusive IS NULL OR sl.created < :endDateExclusive) | |||||
| """) | """) | ||||
| fun findStockTransactions( | fun findStockTransactions( | ||||
| @Param("itemCode") itemCode: String?, | @Param("itemCode") itemCode: String?, | ||||
| @Param("itemName") itemName: String?, | @Param("itemName") itemName: String?, | ||||
| @Param("type") type: String?, | @Param("type") type: String?, | ||||
| @Param("startDate") startDate: LocalDate?, | |||||
| @Param("endDate") endDate: LocalDate? | |||||
| ): List<StockLedger> | |||||
| @Param("startDateTime") startDateTime: LocalDateTime?, | |||||
| @Param("endDateExclusive") endDateExclusive: LocalDateTime?, | |||||
| pageable: Pageable | |||||
| ): Page<StockLedger> | |||||
| @Query(""" | @Query(""" | ||||
| SELECT COUNT(sl) FROM StockLedger sl | SELECT COUNT(sl) FROM StockLedger sl | ||||
| @@ -39,15 +40,15 @@ interface StockLedgerRepository: AbstractRepository<StockLedger, Long> { | |||||
| AND (:itemCode IS NULL OR sl.itemCode LIKE CONCAT('%', :itemCode, '%')) | AND (:itemCode IS NULL OR sl.itemCode LIKE CONCAT('%', :itemCode, '%')) | ||||
| AND (:itemName IS NULL OR i.name LIKE CONCAT('%', :itemName, '%')) | AND (:itemName IS NULL OR i.name LIKE CONCAT('%', :itemName, '%')) | ||||
| AND (:type IS NULL OR sl.type = :type) | AND (:type IS NULL OR sl.type = :type) | ||||
| AND (:startDate IS NULL OR DATE(sl.created) >= :startDate) | |||||
| AND (:endDate IS NULL OR DATE(sl.created) <= :endDate) | |||||
| AND (:startDateTime IS NULL OR sl.created >= :startDateTime) | |||||
| AND (:endDateExclusive IS NULL OR sl.created < :endDateExclusive) | |||||
| """) | """) | ||||
| fun countStockTransactions( | fun countStockTransactions( | ||||
| @Param("itemCode") itemCode: String?, | @Param("itemCode") itemCode: String?, | ||||
| @Param("itemName") itemName: String?, | @Param("itemName") itemName: String?, | ||||
| @Param("type") type: String?, | @Param("type") type: String?, | ||||
| @Param("startDate") startDate: LocalDate?, | |||||
| @Param("endDate") endDate: LocalDate? | |||||
| @Param("startDateTime") startDateTime: LocalDateTime?, | |||||
| @Param("endDateExclusive") endDateExclusive: LocalDateTime? | |||||
| ): Long | ): Long | ||||
| @@ -16,6 +16,7 @@ import java.time.LocalDateTime | |||||
| import java.math.BigDecimal | import java.math.BigDecimal | ||||
| import com.ffii.fpsms.modules.user.entity.UserRepository | import com.ffii.fpsms.modules.user.entity.UserRepository | ||||
| import org.springframework.data.domain.PageRequest | import org.springframework.data.domain.PageRequest | ||||
| import org.springframework.data.domain.Sort | |||||
| import com.ffii.core.response.RecordsRes | import com.ffii.core.response.RecordsRes | ||||
| import com.ffii.fpsms.modules.stock.service.InventoryLotLineService | import com.ffii.fpsms.modules.stock.service.InventoryLotLineService | ||||
| import com.ffii.fpsms.modules.stock.entity.StockTakeLine | import com.ffii.fpsms.modules.stock.entity.StockTakeLine | ||||
| @@ -2741,40 +2742,32 @@ open fun searchStockTransactions(request: SearchStockTransactionRequest): Record | |||||
| return RecordsRes(emptyList(), 0) | return RecordsRes(emptyList(), 0) | ||||
| } | } | ||||
| val startDate = request.startDate | |||||
| val endDate = request.endDate | |||||
| val startDateTime = request.startDate?.atStartOfDay() | |||||
| val endDateExclusive = request.endDate?.plusDays(1)?.atStartOfDay() | |||||
| println("Processed params: itemCode=$itemCode, itemName=$itemName, startDate=$startDate, endDate=$endDate") | |||||
| val total = stockLedgerRepository.countStockTransactions( | |||||
| itemCode = itemCode, | |||||
| itemName = itemName, | |||||
| type = request.type, | |||||
| startDate = startDate, | |||||
| endDate = endDate | |||||
| println( | |||||
| "Processed params: itemCode=$itemCode, itemName=$itemName, " + | |||||
| "startDateTime=$startDateTime, endDateExclusive=$endDateExclusive" | |||||
| ) | ) | ||||
| println("Total count: $total") | |||||
| val actualPageSize = if (request.pageSize == 100) { | |||||
| total.toInt().coerceAtLeast(1) | |||||
| } else { | |||||
| request.pageSize | |||||
| } | |||||
| val offset = request.pageNum * actualPageSize | |||||
| val pageable = PageRequest.of( | |||||
| request.pageNum.coerceAtLeast(0), | |||||
| request.pageSize.coerceAtLeast(1), | |||||
| Sort.by(Sort.Order.asc("created"), Sort.Order.asc("itemId")) | |||||
| ) | |||||
| val ledgers = stockLedgerRepository.findStockTransactions( | |||||
| val ledgerPage = stockLedgerRepository.findStockTransactions( | |||||
| itemCode = itemCode, | itemCode = itemCode, | ||||
| itemName = itemName, | itemName = itemName, | ||||
| type = request.type, | type = request.type, | ||||
| startDate = startDate, | |||||
| endDate = endDate | |||||
| startDateTime = startDateTime, | |||||
| endDateExclusive = endDateExclusive, | |||||
| pageable = pageable | |||||
| ) | ) | ||||
| println("Found ${ledgers.size} ledgers") | |||||
| println("Found ${ledgerPage.numberOfElements} ledgers in current page, total=${ledgerPage.totalElements}") | |||||
| val transactions = ledgers.map { ledger -> | |||||
| val transactions = ledgerPage.content.map { ledger -> | |||||
| val stockInLine = ledger.stockInLine | val stockInLine = ledger.stockInLine | ||||
| val stockOutLine = ledger.stockOutLine | val stockOutLine = ledger.stockOutLine | ||||
| @@ -2805,17 +2798,9 @@ open fun searchStockTransactions(request: SearchStockTransactionRequest): Record | |||||
| ) | ) | ||||
| } | } | ||||
| val sortedTransactions = transactions.sortedWith( | |||||
| compareBy<StockTransactionResponse>( | |||||
| { it.date ?: it.transactionDate?.toLocalDate() }, | |||||
| { it.transactionDate } | |||||
| ) | |||||
| ) | |||||
| val paginatedTransactions = sortedTransactions.drop(offset).take(actualPageSize) | |||||
| val totalTime = System.currentTimeMillis() - startTime | val totalTime = System.currentTimeMillis() - startTime | ||||
| println("Total time (Repository query): ${totalTime}ms, count: ${paginatedTransactions.size}, total: $total") | |||||
| println("Total time (Repository query): ${totalTime}ms, count: ${transactions.size}, total: ${ledgerPage.totalElements}") | |||||
| return RecordsRes(paginatedTransactions, total.toInt()) | |||||
| return RecordsRes(transactions, ledgerPage.totalElements.toInt()) | |||||
| } | } | ||||
| } | } | ||||
| @@ -32,7 +32,8 @@ class StockTakeRecordController( | |||||
| @RequestParam(required = false) stockTakeSections: String?, | @RequestParam(required = false) stockTakeSections: String?, | ||||
| @RequestParam(required = false) status: String?, | @RequestParam(required = false) status: String?, | ||||
| @RequestParam(required = false) area: String?, | @RequestParam(required = false) area: String?, | ||||
| @RequestParam(required = false) storeId: String? | |||||
| @RequestParam(required = false) storeId: String?, | |||||
| @RequestParam(required = false, defaultValue = "false") onlyLatestRound: Boolean | |||||
| ): RecordsRes<AllPickedStockTakeListReponse> { | ): RecordsRes<AllPickedStockTakeListReponse> { | ||||
| var all = stockOutRecordService.AllPickedStockTakeList() | var all = stockOutRecordService.AllPickedStockTakeList() | ||||
| if (sectionDescription != null && sectionDescription != "All") { | if (sectionDescription != null && sectionDescription != "All") { | ||||
| @@ -71,6 +72,18 @@ class StockTakeRecordController( | |||||
| it.storeId?.contains(storeIdKeyword, ignoreCase = true) == true | it.storeId?.contains(storeIdKeyword, ignoreCase = true) == true | ||||
| } | } | ||||
| } | } | ||||
| if (onlyLatestRound) { | |||||
| val latestRoundKey = all | |||||
| .mapNotNull { item -> | |||||
| item.stockTakeRoundId ?: item.stockTakeId.takeIf { it > 0 } | |||||
| } | |||||
| .maxOrNull() | |||||
| all = if (latestRoundKey == null) { | |||||
| emptyList() | |||||
| } else { | |||||
| all.filter { (it.stockTakeRoundId ?: it.stockTakeId) == latestRoundKey } | |||||
| } | |||||
| } | |||||
| val total = all.size | val total = all.size | ||||
| val fromIndex = pageNum * pageSize | val fromIndex = pageNum * pageSize | ||||
| val toIndex = minOf(fromIndex + pageSize, total) | val toIndex = minOf(fromIndex + pageSize, total) | ||||