diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoFloorSupplierSettingsService.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoFloorSupplierSettingsService.kt index ba4b6a1a..dd3fbc7f 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoFloorSupplierSettingsService.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoFloorSupplierSettingsService.kt @@ -17,6 +17,8 @@ open class DoFloorSupplierSettingsService( const val SETTING_JO_PICK_EXCLUDE_WAREHOUSES = "JO.pick.excludeWarehouses" const val SETTING_DO_PICK_EXCLUDE_PRINT_MODE = "DO.pick.excludePrintMode" const val SETTING_JO_PICK_EXCLUDE_PRINT_MODE = "JO.pick.excludePrintMode" + const val SETTING_DO_PICK_EXCLUDE_HIDE_QR = "DO.pick.excludeHideQrWarehouses" + const val SETTING_JO_PICK_EXCLUDE_HIDE_QR = "JO.pick.excludeHideQrWarehouses" const val PRINT_MODE_HIDE_LIST = "hideList" const val PRINT_MODE_HIDE_QR = "hideQr" @@ -36,7 +38,8 @@ open class DoFloorSupplierSettingsService( ?.trim() .orEmpty() if (raw.isEmpty()) return defaultList - val parsed = raw.split(",").map { it.trim() }.filter { it.isNotEmpty() }.distinct() + if (raw == EMPTY_CODE_LIST_MARKER) return emptyList() + val parsed = raw.split(",").map { it.trim() }.filter { it.isNotEmpty() && it != EMPTY_CODE_LIST_MARKER }.distinct() return parsed.ifEmpty { defaultList } } @@ -69,9 +72,47 @@ open class DoFloorSupplierSettingsService( open fun loadJoPickExcludePrintMode(): String = printModeFromSetting(SETTING_JO_PICK_EXCLUDE_PRINT_MODE) + /** + * Warehouses omitted from the print list. Scanning their physical QR does not pass. + * Hide-QR warehouses stay on the list and can still be scanned. + * A missing hide-QR row keeps the old single print mode. + */ + open fun loadDoHideListWarehouseCodes(): Set = + hideListCodes( + loadDoPickExcludeWarehouseCodes(), + SETTING_DO_PICK_EXCLUDE_HIDE_QR, + loadDoPickExcludePrintMode(), + ) + + open fun loadJoHideListWarehouseCodes(): Set = + hideListCodes( + loadJoPickExcludeWarehouseCodes(), + SETTING_JO_PICK_EXCLUDE_HIDE_QR, + loadJoPickExcludePrintMode(), + ) + open fun rejectsScanOfExcludedWarehouse(printMode: String): Boolean = printMode != PRINT_MODE_HIDE_QR + private fun hideListCodes(all: Set, hideQrSetting: String, legacyMode: String): Set { + val row = settingsRepository.findByName(hideQrSetting) + val raw = if (row.isEmpty) "" else row.get().value?.trim().orEmpty() + if (raw.isEmpty() || raw == EMPTY_CODE_LIST_MARKER) { + return if (legacyMode == PRINT_MODE_HIDE_QR) emptySet() else all + } + val hideQr = parseWarehouseCodes(raw) + return all.filter { it !in hideQr }.toSet() + } + + private fun parseWarehouseCodes(raw: String?): Set { + val value = raw?.trim().orEmpty() + if (value.isEmpty() || value == EMPTY_CODE_LIST_MARKER) return emptySet() + return value.split(",") + .map { it.trim().uppercase(Locale.ROOT) } + .filter { it.isNotEmpty() && it != EMPTY_CODE_LIST_MARKER } + .toSet() + } + private fun printModeFromSetting(settingName: String): String { val raw = settingsRepository.findByName(settingName).map { it.value }.orElse(null)?.trim().orEmpty() return if (raw == PRINT_MODE_HIDE_QR) PRINT_MODE_HIDE_QR else PRINT_MODE_HIDE_LIST diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoWorkbenchMainService.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoWorkbenchMainService.kt index 66e874df..46fbfc6f 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoWorkbenchMainService.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoWorkbenchMainService.kt @@ -280,24 +280,22 @@ open class DoWorkbenchMainService( ): String? { val code = warehouseCode?.trim()?.uppercase(Locale.ROOT).orEmpty() if (code.isEmpty()) return null - val joCodes = doFloorSupplierSettingsService.loadJoPickExcludeWarehouseCodes() - val (codes, printMode) = when (pickOrderType) { - PickOrderType.JOB_ORDER -> joCodes to doFloorSupplierSettingsService.loadJoPickExcludePrintMode() + val hideList = when (pickOrderType) { + PickOrderType.JOB_ORDER -> doFloorSupplierSettingsService.loadJoHideListWarehouseCodes() PickOrderType.Consumable -> { - val limited = if (userId == null) { + if (userId == null) { emptySet() } else { - ConsumableWorkbenchPickConstants.resolveExcludeWarehouseCodes(userId, joCodes) + val joCodes = doFloorSupplierSettingsService.loadJoPickExcludeWarehouseCodes() + val limited = ConsumableWorkbenchPickConstants.resolveExcludeWarehouseCodes(userId, joCodes) .map { it.uppercase(Locale.ROOT) } .toSet() + limited.intersect(doFloorSupplierSettingsService.loadJoHideListWarehouseCodes()) } - limited to doFloorSupplierSettingsService.loadJoPickExcludePrintMode() } - else -> doFloorSupplierSettingsService.loadDoPickExcludeWarehouseCodes() to - doFloorSupplierSettingsService.loadDoPickExcludePrintMode() + else -> doFloorSupplierSettingsService.loadDoHideListWarehouseCodes() } - if (code !in codes) return null - if (!doFloorSupplierSettingsService.rejectsScanOfExcludedWarehouse(printMode)) return null + if (code !in hideList) return null return "此儲位不在揀貨清單,掃到實物 QR 也不可以揀。" } diff --git a/src/main/resources/db/changelog/changes/20260923_pick_exclude_hide_qr/01_setting.sql b/src/main/resources/db/changelog/changes/20260923_pick_exclude_hide_qr/01_setting.sql new file mode 100644 index 00000000..f0439299 --- /dev/null +++ b/src/main/resources/db/changelog/changes/20260923_pick_exclude_hide_qr/01_setting.sql @@ -0,0 +1,29 @@ +--liquibase formatted sql +--changeset fpsms:20260923_pick_exclude_hide_qr + +-- Warehouses that stay on the print list without a QR. +-- `-` means none. A missing row still follows the single DO/JO print mode. + +INSERT INTO `settings` (`name`, `value`, `category`, `type`) +SELECT v.name, v.value, v.category, v.type +FROM ( + SELECT 'DO.pick.excludeHideQrWarehouses' AS name, + '-' AS value, + 'PICK_RULES' AS category, + 'string' AS type +) v +WHERE NOT EXISTS ( + SELECT 1 FROM `settings` s WHERE s.name = 'DO.pick.excludeHideQrWarehouses' +); + +INSERT INTO `settings` (`name`, `value`, `category`, `type`) +SELECT v.name, v.value, v.category, v.type +FROM ( + SELECT 'JO.pick.excludeHideQrWarehouses' AS name, + '-' AS value, + 'PICK_RULES' AS category, + 'string' AS type +) v +WHERE NOT EXISTS ( + SELECT 1 FROM `settings` s WHERE s.name = 'JO.pick.excludeHideQrWarehouses' +); diff --git a/src/main/resources/db/changelog/changes/20260923_pick_exclude_rules/01_setting.sql b/src/main/resources/db/changelog/changes/20260923_pick_exclude_rules/01_setting.sql new file mode 100644 index 00000000..a2dcadff --- /dev/null +++ b/src/main/resources/db/changelog/changes/20260923_pick_exclude_rules/01_setting.sql @@ -0,0 +1,29 @@ +--liquibase formatted sql +--changeset fpsms:20260923_pick_exclude_rules + +-- Placeholder so the settings row exists. `-` means derive rules from the warehouse-code list. +-- Saving a rule replaces this with JSON and rewrites the expanded warehouse codes. + +INSERT INTO `settings` (`name`, `value`, `category`, `type`) +SELECT v.name, v.value, v.category, v.type +FROM ( + SELECT 'DO.pick.excludeRules' AS name, + '-' AS value, + 'PICK_RULES' AS category, + 'string' AS type +) v +WHERE NOT EXISTS ( + SELECT 1 FROM `settings` s WHERE s.name = 'DO.pick.excludeRules' +); + +INSERT INTO `settings` (`name`, `value`, `category`, `type`) +SELECT v.name, v.value, v.category, v.type +FROM ( + SELECT 'JO.pick.excludeRules' AS name, + '-' AS value, + 'PICK_RULES' AS category, + 'string' AS type +) v +WHERE NOT EXISTS ( + SELECT 1 FROM `settings` s WHERE s.name = 'JO.pick.excludeRules' +);