| @@ -5,6 +5,7 @@ import com.ffii.fpsms.modules.master.entity.projections.WarehouseCombo | |||
| import org.springframework.data.domain.Page | |||
| import org.springframework.data.domain.Pageable | |||
| import org.springframework.data.jpa.repository.Query | |||
| import org.springframework.data.repository.query.Param | |||
| import org.springframework.stereotype.Repository | |||
| import java.io.Serializable | |||
| @@ -22,6 +23,22 @@ interface WarehouseRepository : AbstractRepository<Warehouse, Long> { | |||
| fun findAllByIdIn(ids: List<Long>): List<Warehouse>; | |||
| fun findAllByCodeAndDeletedIsFalse(code: String): List<Warehouse> | |||
| /** FP-MTMS Version Checklist | Functions Ref. No. 19 | v1.0.1 | 2026-09-10 */ | |||
| @Query( | |||
| """ | |||
| SELECT w FROM Warehouse w | |||
| WHERE w.deleted = false | |||
| AND (:storeId IS NULL OR :storeId = '' OR w.store_id = :storeId) | |||
| AND (:warehouse IS NULL OR :warehouse = '' OR w.warehouse = :warehouse) | |||
| AND (:area IS NULL OR :area = '' OR w.area = :area) | |||
| """ | |||
| ) | |||
| fun findByLocationFilters( | |||
| @Param("storeId") storeId: String?, | |||
| @Param("warehouse") warehouse: String?, | |||
| @Param("area") area: String?, | |||
| ): List<Warehouse> | |||
| @Query( | |||
| """ | |||
| SELECT COUNT(w) FROM Warehouse w | |||
| @@ -8,7 +8,7 @@ class DoUserPickAuditReportService( | |||
| private val jdbcDao: JdbcDao, | |||
| ) { | |||
| /** | |||
| * FP-MTMS Version Checklist | Functions Ref. No. 39 | v1.0.2 | 2026-08-05 | |||
| * FP-MTMS Version Checklist | Functions Ref. No. 39 | v1.0.3 | 2026-09-10 | |||
| * DO workbench user-audit rows (Just issue only). | |||
| * issueTypes may combine: 跳過提料(使用「已完成」)+多提+少提+擅自換批/揀錯批. | |||
| * 少提/多提 use POL-level SUM(stock_out_line.qty) vs pol.qty (multi-lot split OK if total matches). | |||
| @@ -55,10 +55,7 @@ class DoUserPickAuditReportService( | |||
| "AND dop.ticketNo LIKE CONCAT('%', :ticketNo, '%')" | |||
| } else "" | |||
| val itemSql = if (!itemCode.isNullOrBlank()) { | |||
| args["itemCode"] = itemCode.trim() | |||
| "AND i.code LIKE CONCAT('%', :itemCode, '%')" | |||
| } else "" | |||
| val itemSql = buildMultiValueLikeClause(itemCode, "i.code", "itemCode", args) | |||
| val storeSql = if (!storeId.isNullOrBlank()) { | |||
| args["storeId"] = storeId.trim().uppercase().replace("/", "").replace(" ", "") | |||
| @@ -201,4 +198,22 @@ class DoUserPickAuditReportService( | |||
| .map { (it["handler"]?.toString() ?: "").trim() } | |||
| .filter { it.isNotBlank() } | |||
| } | |||
| /** FP-MTMS Version Checklist | Functions Ref. No. 39 | v1.0.3 | 2026-09-10 */ | |||
| private fun buildMultiValueLikeClause( | |||
| paramValue: String?, | |||
| columnName: String, | |||
| paramPrefix: String, | |||
| args: MutableMap<String, Any>, | |||
| ): String { | |||
| if (paramValue.isNullOrBlank()) return "" | |||
| val values = paramValue.split(",").map { it.trim() }.filter { it.isNotBlank() } | |||
| if (values.isEmpty()) return "" | |||
| val conditions = values.mapIndexed { index, value -> | |||
| val paramName = "${paramPrefix}_$index" | |||
| args[paramName] = "%$value%" | |||
| "$columnName LIKE :$paramName" | |||
| } | |||
| return "AND (${conditions.joinToString(" OR ")})" | |||
| } | |||
| } | |||
| @@ -23,6 +23,7 @@ open class M18BomShopSyncReportService( | |||
| private val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") | |||
| private val versionFromHeaderCode = Regex("V(\\d+)$", RegexOption.IGNORE_CASE) | |||
| /** FP-MTMS Version Checklist | Functions Ref. No. 83 | v1.0.0 | 2026-09-10 */ | |||
| open fun searchBomShopSyncHistoryReport( | |||
| syncDateStart: String?, | |||
| syncDateEnd: String?, | |||
| @@ -31,15 +32,26 @@ open class M18BomShopSyncReportService( | |||
| ): Map<String, Any> { | |||
| val start = parseDateStart(syncDateStart) | |||
| val end = parseDateEnd(syncDateEnd) | |||
| val itemFilter = finishedItemCode?.trim()?.takeIf { it.isNotEmpty() } | |||
| val itemTokens = finishedItemCode | |||
| ?.split(",") | |||
| ?.map { it.trim() } | |||
| ?.filter { it.isNotEmpty() } | |||
| .orEmpty() | |||
| val sqlItemFilter = itemTokens.singleOrNull() | |||
| val statusFilter = syncStatus?.trim()?.lowercase()?.takeIf { it.isNotEmpty() && it != "all" } | |||
| val logs = m18BomShopSyncLogRepository.searchForReport( | |||
| syncDateStart = start, | |||
| syncDateEnd = end, | |||
| finishedItemCode = itemFilter, | |||
| finishedItemCode = sqlItemFilter, | |||
| syncStatus = statusFilter, | |||
| ) | |||
| ).let { fetched -> | |||
| if (itemTokens.size <= 1) fetched | |||
| else fetched.filter { log -> | |||
| val code = log.finishedItemCode.orEmpty() | |||
| itemTokens.any { token -> code.contains(token, ignoreCase = true) } | |||
| } | |||
| } | |||
| val syncRows = mutableListOf<Map<String, Any?>>() | |||
| val materialRows = mutableListOf<Map<String, Any?>>() | |||
| @@ -3,6 +3,7 @@ package com.ffii.fpsms.modules.stock.entity | |||
| import com.ffii.core.support.AbstractRepository | |||
| import com.ffii.fpsms.modules.stock.entity.projection.CurrentInventoryItemInfo | |||
| import com.ffii.fpsms.modules.stock.entity.projection.InventoryLotLineInfo | |||
| import com.ffii.fpsms.modules.stock.entity.projection.InventoryStockUomSearchRow | |||
| import org.springframework.data.domain.Page | |||
| import org.springframework.data.domain.Pageable | |||
| import org.springframework.data.jpa.repository.Modifying | |||
| @@ -56,8 +57,116 @@ WHERE ill.id = :id | |||
| fun findInventoryLotLineInfoByInventoryLotItemIdIn(ids: List<Serializable>): List<InventoryLotLineInfo> | |||
| @Query("select ill from InventoryLotLine ill where :id is null or ill.inventoryLot.item.id = :id order by ill.id desc") | |||
| fun findInventoryLotLineInfoByItemId(id: Long?, pageable: Pageable): Page<InventoryLotLineInfo> | |||
| @Query( | |||
| """ | |||
| SELECT ill FROM InventoryLotLine ill | |||
| WHERE (:id IS NULL OR ill.inventoryLot.item.id = :id) | |||
| AND (:uomId IS NULL OR ill.stockUom.uom.id = :uomId) | |||
| ORDER BY ill.id DESC | |||
| """ | |||
| ) | |||
| /** FP-MTMS Version Checklist | Functions Ref. No. 80 | v1.0.0 | 2026-09-10 */ | |||
| fun findInventoryLotLineInfoByItemId( | |||
| @Param("id") id: Long?, | |||
| @Param("uomId") uomId: Long?, | |||
| pageable: Pageable, | |||
| ): Page<InventoryLotLineInfo> | |||
| @Query( | |||
| """ | |||
| SELECT DISTINCT ill.inventoryLot.item.id | |||
| FROM InventoryLotLine ill | |||
| WHERE ill.deleted = false | |||
| AND ill.status = :status | |||
| AND ill.warehouse.id IN :warehouseIds | |||
| """ | |||
| ) | |||
| fun findDistinctItemIdsByWarehouseIdsAndStatus( | |||
| @Param("warehouseIds") warehouseIds: List<Long>, | |||
| @Param("status") status: InventoryLotLineStatus, | |||
| ): List<Long> | |||
| @Query( | |||
| """ | |||
| SELECT ill FROM InventoryLotLine ill | |||
| WHERE (:id IS NULL OR ill.inventoryLot.item.id = :id) | |||
| AND ill.warehouse.id IN :warehouseIds | |||
| AND (:uomId IS NULL OR ill.stockUom.uom.id = :uomId) | |||
| ORDER BY ill.id DESC | |||
| """ | |||
| ) | |||
| /** FP-MTMS Version Checklist | Functions Ref. No. 80 | v1.0.0 | 2026-09-10 */ | |||
| fun findInventoryLotLineInfoByItemIdAndWarehouseIdIn( | |||
| @Param("id") id: Long?, | |||
| @Param("warehouseIds") warehouseIds: List<Long>, | |||
| @Param("uomId") uomId: Long?, | |||
| pageable: Pageable, | |||
| ): Page<InventoryLotLineInfo> | |||
| @Query( | |||
| value = """ | |||
| SELECT | |||
| MAX(CAST(ill.id AS long)) AS id, | |||
| CAST(item.id AS long) AS itemId, | |||
| item.code AS itemCode, | |||
| item.name AS itemName, | |||
| item.type AS itemType, | |||
| SUM(COALESCE(ill.inQty, 0)) AS onHandQty, | |||
| SUM(COALESCE(ill.holdQty, 0)) AS onHoldQty, | |||
| SUM(COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) AS availableQty, | |||
| CAST(uom.id AS long) AS uomId, | |||
| uom.code AS uomCode, | |||
| uom.udfudesc AS uomUdfudesc, | |||
| uom.udfShortDesc AS uomShortDesc, | |||
| SUM(COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) AS qtyPerSmallestUnit, | |||
| MAX(item.latestMarketUnitPrice) AS latestMarketUnitPrice, | |||
| MAX(item.latestMupUpdatedDate) AS latestMupUpdatedDate | |||
| FROM InventoryLotLine ill | |||
| JOIN ill.inventoryLot il | |||
| JOIN il.item item | |||
| JOIN ill.stockUom su | |||
| JOIN su.uom uom | |||
| WHERE ill.deleted = false | |||
| AND il.deleted = false | |||
| AND item.deleted = false | |||
| AND ill.status = :status | |||
| AND (:code IS NULL OR :code = '' OR LOWER(item.code) LIKE LOWER(CONCAT('%', :code, '%'))) | |||
| AND (:name IS NULL OR :name = '' OR LOWER(item.name) LIKE LOWER(CONCAT('%', :name, '%'))) | |||
| AND (:type IS NULL OR :type = '' OR item.type = :type) | |||
| AND (:hasWarehouseFilter = false OR ill.warehouse.id IN :warehouseIds) | |||
| AND (:lotNo IS NULL OR :lotNo = '' OR il.lotNo = :lotNo) | |||
| GROUP BY item.id, item.code, item.name, item.type, uom.id, uom.code, uom.udfudesc, uom.udfShortDesc | |||
| ORDER BY item.code ASC, uom.udfudesc ASC | |||
| """, | |||
| countQuery = """ | |||
| SELECT COUNT(DISTINCT CONCAT(CAST(item.id AS string), ':', CAST(uom.id AS string))) | |||
| FROM InventoryLotLine ill | |||
| JOIN ill.inventoryLot il | |||
| JOIN il.item item | |||
| JOIN ill.stockUom su | |||
| JOIN su.uom uom | |||
| WHERE ill.deleted = false | |||
| AND il.deleted = false | |||
| AND item.deleted = false | |||
| AND ill.status = :status | |||
| AND (:code IS NULL OR :code = '' OR LOWER(item.code) LIKE LOWER(CONCAT('%', :code, '%'))) | |||
| AND (:name IS NULL OR :name = '' OR LOWER(item.name) LIKE LOWER(CONCAT('%', :name, '%'))) | |||
| AND (:type IS NULL OR :type = '' OR item.type = :type) | |||
| AND (:hasWarehouseFilter = false OR ill.warehouse.id IN :warehouseIds) | |||
| AND (:lotNo IS NULL OR :lotNo = '' OR il.lotNo = :lotNo) | |||
| """, | |||
| ) | |||
| /** FP-MTMS Version Checklist | Functions Ref. No. 19 | v1.0.1 | 2026-09-10 */ | |||
| fun searchInventoryGroupedByStockUom( | |||
| @Param("code") code: String, | |||
| @Param("name") name: String, | |||
| @Param("type") type: String, | |||
| @Param("status") status: InventoryLotLineStatus, | |||
| @Param("hasWarehouseFilter") hasWarehouseFilter: Boolean, | |||
| @Param("warehouseIds") warehouseIds: List<Long>, | |||
| @Param("lotNo") lotNo: String?, | |||
| pageable: Pageable, | |||
| ): Page<InventoryStockUomSearchRow> | |||
| @Query(""" | |||
| SELECT ill FROM InventoryLotLine ill | |||
| @@ -0,0 +1,30 @@ | |||
| package com.ffii.fpsms.modules.stock.entity.projection | |||
| import java.math.BigDecimal | |||
| import java.time.LocalDateTime | |||
| /** | |||
| * Inventory search page: one row per item + lot-line stock UoM. | |||
| */ | |||
| interface InventoryStockUomSearchRow { | |||
| val id: Long? | |||
| val itemId: Long? | |||
| val itemCode: String? | |||
| val itemName: String? | |||
| val itemType: String? | |||
| val onHandQty: BigDecimal? | |||
| val onHoldQty: BigDecimal? | |||
| val unavailableQty: BigDecimal? | |||
| val availableQty: BigDecimal? | |||
| val uomId: Long? | |||
| val uomCode: String? | |||
| val uomUdfudesc: String? | |||
| val uomShortDesc: String? | |||
| val qtyPerSmallestUnit: BigDecimal? | |||
| val baseUom: String? | |||
| val price: BigDecimal? | |||
| val currencyName: String? | |||
| val status: String? | |||
| val latestMarketUnitPrice: Double? | |||
| val latestMupUpdatedDate: LocalDateTime? | |||
| } | |||
| @@ -76,9 +76,15 @@ open class InventoryLotLineService( | |||
| return inventoryLotLineRepository.findInventoryLotLineInfoByInventoryLotItemIdIn(itemIds) | |||
| } | |||
| /** FP-MTMS Version Checklist | Functions Ref. No. 80 | v1.0.0 | 2026-09-10 */ | |||
| open fun allInventoryLotLinesByPage(request: SearchInventoryLotLineInfoRequest): RecordsRes<InventoryLotLineInfo> { | |||
| val pageable = PageRequest.of(request.pageNum ?: 0, request.pageSize ?: 10); | |||
| val warehouseIds = resolveWarehouseIds(request.storeId, request.warehouse, request.area) | |||
| if (warehouseIds != null && warehouseIds.isEmpty()) { | |||
| return RecordsRes(emptyList(), 0) | |||
| } | |||
| val response = if (request.stockIssueBadItem == true) { | |||
| inventoryLotLineRepository.findStockIssueBadItemLotLinesByItemId( | |||
| request.itemId, | |||
| @@ -86,8 +92,15 @@ open class InventoryLotLineService( | |||
| listOf(InventoryLotLineStatus.AVAILABLE, InventoryLotLineStatus.UNAVAILABLE), | |||
| pageable, | |||
| ) | |||
| } else if (warehouseIds != null) { | |||
| inventoryLotLineRepository.findInventoryLotLineInfoByItemIdAndWarehouseIdIn( | |||
| request.itemId, | |||
| warehouseIds, | |||
| request.uomId, | |||
| pageable, | |||
| ) | |||
| } else { | |||
| inventoryLotLineRepository.findInventoryLotLineInfoByItemId(request.itemId, pageable) | |||
| inventoryLotLineRepository.findInventoryLotLineInfoByItemId(request.itemId, request.uomId, pageable) | |||
| } | |||
| val records = response.content | |||
| @@ -95,6 +108,28 @@ open class InventoryLotLineService( | |||
| return RecordsRes<InventoryLotLineInfo>(records, total.toInt()); | |||
| } | |||
| /** | |||
| * FP-MTMS Version Checklist | Functions Ref. No. 80 | v1.0.0 | 2026-09-10 | |||
| * Returns null when no location filter is set. | |||
| */ | |||
| private fun resolveWarehouseIds( | |||
| storeId: String?, | |||
| warehouse: String?, | |||
| area: String?, | |||
| ): List<Long>? { | |||
| val trimmedStoreId = storeId?.trim()?.takeIf { it.isNotEmpty() } | |||
| val trimmedWarehouse = warehouse?.trim()?.takeIf { it.isNotEmpty() } | |||
| val trimmedArea = area?.trim()?.takeIf { it.isNotEmpty() } | |||
| if (trimmedStoreId == null && trimmedWarehouse == null && trimmedArea == null) { | |||
| return null | |||
| } | |||
| return warehouseRepository.findByLocationFilters( | |||
| trimmedStoreId, | |||
| trimmedWarehouse, | |||
| trimmedArea, | |||
| ).mapNotNull { it.id } | |||
| } | |||
| open fun searchStockIssueBadItemLotLines( | |||
| request: SearchStockIssueBadItemLotLineRequest, | |||
| ): RecordsRes<InventoryLotLineInfo> { | |||
| @@ -17,6 +17,7 @@ import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderType | |||
| import com.ffii.fpsms.modules.stock.entity.* | |||
| import com.ffii.fpsms.modules.stock.entity.enum.InventoryLotLineStatus | |||
| import com.ffii.fpsms.modules.stock.entity.projection.InventoryInfo | |||
| import com.ffii.fpsms.modules.stock.entity.projection.InventoryStockUomSearchRow | |||
| import com.ffii.fpsms.modules.stock.web.model.SearchInventoryRequest | |||
| import org.apache.poi.ss.usermodel.Sheet | |||
| import org.apache.poi.ss.usermodel.Workbook | |||
| @@ -89,43 +90,56 @@ open class InventoryService( | |||
| } | |||
| /** | |||
| * FP-MTMS Version Checklist | Functions Ref. No. 19 | v1.0.0 | 2026-07-17 | |||
| * Inventory search page only: no baseUnit/uomId filter; | |||
| * one inventory row per item (latest id). Shared getRecordByPage is unchanged. | |||
| * FP-MTMS Version Checklist | Functions Ref. No. 19 | v1.0.1 | 2026-09-10 | |||
| * Inventory search page: one row per item + lot-line stock UoM. | |||
| */ | |||
| open fun searchInventoriesByLatestInventory( | |||
| request: SearchInventoryRequest, | |||
| ): RecordsRes<InventoryInfo> { | |||
| ): RecordsRes<InventoryStockUomSearchRow> { | |||
| val pageable = PageRequest.of(request.pageNum ?: 0, request.pageSize ?: 10) | |||
| val code = request.code?.trim().orEmpty() | |||
| val name = request.name?.trim().orEmpty() | |||
| val type = request.type?.trim().orEmpty() | |||
| val lotNo = request.lotNo?.trim()?.takeIf { it.isNotEmpty() } | |||
| val response = if (lotNo != null) { | |||
| val itemIds = inventoryLotLineRepository.findDistinctItemIdsByLotNo(lotNo) | |||
| if (itemIds.isEmpty()) { | |||
| return RecordsRes(emptyList(), 0) | |||
| } | |||
| inventoryRepository.findLatestInventoryInfoByItemCodeContainsAndItemNameContainsAndItemTypeAndItemIdInAndDeletedIsFalse( | |||
| code = code, | |||
| name = name, | |||
| type = type, | |||
| itemIds = itemIds, | |||
| pageable = pageable, | |||
| ) | |||
| } else { | |||
| inventoryRepository.findLatestInventoryInfoByItemCodeContainsAndItemNameContainsAndItemTypeAndDeletedIsFalse( | |||
| code = code, | |||
| name = name, | |||
| type = type, | |||
| pageable = pageable, | |||
| ) | |||
| val warehouseIds = resolveWarehouseIds(request.storeId, request.warehouse, request.area) | |||
| if (warehouseIds != null && warehouseIds.isEmpty()) { | |||
| return RecordsRes(emptyList(), 0) | |||
| } | |||
| val hasWarehouseFilter = warehouseIds != null | |||
| val response = inventoryLotLineRepository.searchInventoryGroupedByStockUom( | |||
| code = code, | |||
| name = name, | |||
| type = type, | |||
| status = InventoryLotLineStatus.AVAILABLE, | |||
| hasWarehouseFilter = hasWarehouseFilter, | |||
| warehouseIds = warehouseIds ?: listOf(-1L), | |||
| lotNo = lotNo, | |||
| pageable = pageable, | |||
| ) | |||
| return RecordsRes(response.content, response.totalElements.toInt()) | |||
| } | |||
| /** FP-MTMS Version Checklist | Functions Ref. No. 19 | v1.0.1 | 2026-09-10 */ | |||
| private fun resolveWarehouseIds( | |||
| storeId: String?, | |||
| warehouse: String?, | |||
| area: String?, | |||
| ): List<Long>? { | |||
| val trimmedStoreId = storeId?.trim()?.takeIf { it.isNotEmpty() } | |||
| val trimmedWarehouse = warehouse?.trim()?.takeIf { it.isNotEmpty() } | |||
| val trimmedArea = area?.trim()?.takeIf { it.isNotEmpty() } | |||
| if (trimmedStoreId == null && trimmedWarehouse == null && trimmedArea == null) { | |||
| return null | |||
| } | |||
| return warehouseRepository.findByLocationFilters( | |||
| trimmedStoreId, | |||
| trimmedWarehouse, | |||
| trimmedArea, | |||
| ).mapNotNull { it.id } | |||
| } | |||
| open fun allInventoriesByItems(items: List<Items>): List<InventoryInfo>{ | |||
| return inventoryRepository.findInventoryInfoByItemInAndDeletedIsFalse(items); | |||
| } | |||
| @@ -2,6 +2,7 @@ package com.ffii.fpsms.modules.stock.web | |||
| import com.ffii.core.response.RecordsRes | |||
| import com.ffii.fpsms.modules.stock.entity.projection.InventoryInfo | |||
| import com.ffii.fpsms.modules.stock.entity.projection.InventoryStockUomSearchRow | |||
| import com.ffii.fpsms.modules.stock.service.InventoryService | |||
| import com.ffii.fpsms.modules.stock.web.model.SearchInventoryRequest | |||
| import org.springframework.web.bind.annotation.* | |||
| @@ -22,13 +23,13 @@ class InventoryController( | |||
| } | |||
| /** | |||
| * FP-MTMS Version Checklist | Functions Ref. No. 19 | v1.0.0 | 2026-07-17 | |||
| * Inventory search page only: latest inventory row per item, no baseUnit/uomId filter. | |||
| * FP-MTMS Version Checklist | Functions Ref. No. 19 | v1.0.1 | 2026-09-10 | |||
| * Inventory search page: one row per item + lot-line stock UoM, with optional location filters. | |||
| */ | |||
| @GetMapping("/searchLatest/getRecordByPage") | |||
| fun searchInventoriesByLatestInventory( | |||
| @ModelAttribute request: SearchInventoryRequest, | |||
| ): RecordsRes<InventoryInfo> { | |||
| ): RecordsRes<InventoryStockUomSearchRow> { | |||
| return inventoryService.searchInventoriesByLatestInventory(request) | |||
| } | |||
| @@ -2,8 +2,15 @@ package com.ffii.fpsms.modules.stock.web.model | |||
| data class SearchInventoryLotLineInfoRequest( | |||
| val itemId: Long? = null, | |||
| val uomId: Long? = null, | |||
| val pageSize: Int?, | |||
| val pageNum: Int?, | |||
| /** When true: non-expired lots with inQty > outQty; includes available and unavailable status. */ | |||
| val stockIssueBadItem: Boolean? = false, | |||
| /** Floor / store, e.g. 2F. Used by inventory location search. */ | |||
| val storeId: String? = null, | |||
| /** Warehouse zone, e.g. W201. */ | |||
| val warehouse: String? = null, | |||
| /** Area, e.g. #R. */ | |||
| val area: String? = null, | |||
| ) | |||
| @@ -5,6 +5,12 @@ data class SearchInventoryRequest( | |||
| val name: String, | |||
| val type: String, | |||
| val lotNo: String? = null, | |||
| /** Floor / store, e.g. 2F. Used by inventory location search. */ | |||
| val storeId: String? = null, | |||
| /** Warehouse zone, e.g. W201. */ | |||
| val warehouse: String? = null, | |||
| /** Area, e.g. #R. */ | |||
| val area: String? = null, | |||
| val pageNum: Int?, | |||
| val pageSize: Int? | |||
| ) | |||