From f2ff4ae1232a7a61026c379b21bab98392e50ce0 Mon Sep 17 00:00:00 2001 From: zimoyin <2556608754@qq.com> Date: Wed, 11 Mar 2026 13:48:40 +0800 Subject: [PATCH] =?UTF-8?q?ai-chore(config):=20=E8=B0=83=E6=95=B4=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E9=85=8D=E7=BD=AE=E5=8F=8A=E6=94=B9=E8=BF=9B=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 FLOW_USE_CUSTOM_PROCESS 从 true 改为 false,禁用自定义流程 - 在 BlockTest 测试用例中改用 setBlockMode 方法设置阻断模式 - 设置统一的错误处理,将错误转为异常抛出 - 重命名 BlockTest 测试文件路径,优化测试组织结构 - 更新 IDE php include paths,调整依赖包引用顺序 - 删除无用的 tests/flow/Test.php 测试文件 - 微调 start.php、webman、windows.php 配置或代码模块 --- .env | 3 ++ .phpunit.cache/test-results | 2 +- app/config/TODO.md | 4 ++- app/flow/FlowMain.php | 1 + app/flow/FlowProcessor.php | 2 +- app/flow/OperatorSessionManager.php | 10 ++++-- app/flow/context/ProcessContext.php | 23 ++++++------ app/flow/context/ProcessContextBuilder.php | 22 ++++++------ app/flow/{vo => context/bean}/BatchNo.php | 35 +++++++++++++++--- .../{vo => context/bean}/CanHandleResult.php | 6 ++-- .../{vo => context/bean}/EndoscopeInfo.php | 2 +- .../{vo => context/bean}/ExecutionResult.php | 2 +- .../bean}/MorningWashStatus.php | 2 +- .../{vo => context/bean}/OperatorInfo.php | 2 +- .../{vo => context/bean}/ProcessStatus.php | 2 +- app/flow/{vo => context/bean}/ReaderInfo.php | 2 +- .../{vo => context/bean}/ReminderStatus.php | 2 +- .../{vo => context/bean}/StorageStatus.php | 2 +- app/flow/{vo => context/bean}/VoiceState.php | 2 +- app/flow/enum/VoiceMessage.php | 4 ++- app/flow/nodes/AbstractProcessNode.php | 6 ++-- app/flow/nodes/CloseNode.php | 6 ++-- app/flow/nodes/DisinfectNode.php | 12 +++---- app/flow/nodes/DryNode.php | 12 +++---- app/flow/nodes/DuplicateCheckNode.php | 6 ++-- app/flow/nodes/EndNode.php | 19 +++++----- app/flow/nodes/FinalRinseNode.php | 12 +++---- app/flow/nodes/MachineWashNode.php | 16 ++++----- app/flow/nodes/MorningWashNode.php | 12 +++---- app/flow/nodes/ProcessNodeInterface.php | 2 +- app/flow/nodes/RinseNode.php | 12 +++---- app/flow/nodes/StorageInNode.php | 14 ++++---- app/flow/nodes/StorageNode.php | 14 ++++---- app/flow/nodes/StorageOutNode.php | 14 ++++---- app/flow/nodes/VirtualWashMachineNode.php | 10 +++--- app/flow/nodes/WashNode.php | 20 ++++++----- app/flow/strategies/MorningWashStrategy.php | 2 +- .../strategies/TimeValidationStrategy.php | 13 ++++--- app/repository/EctActionsRepository.php | 7 ++-- tests/flow/VirtualContextBuilder.php | 36 ++++++++++++++----- tests/flow/VirtualityFlowProcessor.php | 22 +++++++++--- tests/flow/node_flow/BlockTest.php | 7 ++++ 42 files changed, 246 insertions(+), 158 deletions(-) rename app/flow/{vo => context/bean}/BatchNo.php (83%) rename app/flow/{vo => context/bean}/CanHandleResult.php (86%) rename app/flow/{vo => context/bean}/EndoscopeInfo.php (97%) rename app/flow/{vo => context/bean}/ExecutionResult.php (99%) rename app/flow/{vo => context/bean}/MorningWashStatus.php (98%) rename app/flow/{vo => context/bean}/OperatorInfo.php (96%) rename app/flow/{vo => context/bean}/ProcessStatus.php (98%) rename app/flow/{vo => context/bean}/ReaderInfo.php (97%) rename app/flow/{vo => context/bean}/ReminderStatus.php (98%) rename app/flow/{vo => context/bean}/StorageStatus.php (98%) rename app/flow/{vo => context/bean}/VoiceState.php (99%) diff --git a/.env b/.env index 6bcd102..54864c9 100644 --- a/.env +++ b/.env @@ -7,6 +7,9 @@ DB_PASSWORD = user DB_DEBUG = false +BLOCK_MODE = false + + FLOW_PROCESS_CONFIG_KEY = standard FLOW_USE_CUSTOM_PROCESS = false diff --git a/.phpunit.cache/test-results b/.phpunit.cache/test-results index c42e17f..c2fe452 100644 --- a/.phpunit.cache/test-results +++ b/.phpunit.cache/test-results @@ -1 +1 @@ -{"version":2,"defects":{"tests\\flow\\FlowProcessorTest::testCreateProcessor":8,"tests\\flow\\FlowProcessorTest::testCreateProcessorWithConfig":8,"tests\\flow\\FlowProcessorTest::testUpdateConfig":8,"tests\\flow\\FlowProcessorTest::testBatchNoConsistency":8,"tests\\flow\\FlowProcessorTest::testBatchNoConsistencyInCompleteProcess":8,"tests\\flow\\FlowProcessorTest::testDatabaseOperationFlags":8,"tests\\flow\\FlowProcessorTest::testWebSocketNotifyFlag":8,"tests\\flow\\FlowProcessorTest::testVoiceGeneration":8,"tests\\flow\\FlowProcessorTest::testErrorVoiceGeneration":7,"tests\\flow\\FlowProcessorTest::testMultiHospitalConfig":8,"tests\\flow\\FlowProcessorTest::testSpecialHospitalConfig":8,"tests\\flow\\ProcessEngineTest::testTimeValidationFailure":8,"tests\\flow\\ProcessEngineTest::testWrongStep":7,"tests\\flow\\strategies\\TimeValidationStrategyTest::testCustomDuration":7,"tests\\flow\\ProcessEngineTest::testSkipStep":7,"tests\\flow\\BatchConsistencyTest::testBatchNoPreservedOnError":8,"tests\\flow\\BatchConsistencyTest::testBatchNoWithDifferentProcessTypes":8,"tests\\flow\\EdgeCaseTest::testBatchNoGenerationEdgeCases":7,"tests\\flow\\PerformanceTest::testContextCreationPerformance":7,"tests\\flow\\PerformanceTest::testStrategyExecutionPerformance":7,"tests\\flow\\PerformanceTest::testChainTraversalPerformance":8,"tests\\flow\\nodes\\MorningWashNodeTest::testCanHandleMorningWashReader":7,"tests\\flow\\nodes\\MorningWashNodeTest::testHandleProcess":7,"tests\\flow\\nodes\\MorningWashNodeTest::testGenerateBatchNo":8,"tests\\flow\\nodes\\MorningWashNodeTest::testCanHandleDisinfectReaderForMorningWash":8,"tests\\flow\\nodes\\MorningWashNodeTest::testCanHandleMachineWashReaderForMorningWash":8,"tests\\flow\\nodes\\MorningWashNodeTest::testHandleProcessWithDisinfect":8,"tests\\flow\\nodes\\MorningWashNodeTest::testHandleProcessWithMachineWash":8,"tests\\flow\\EdgeCaseTest::testConcurrentBatchNoGeneration":7,"tests\\flow\\ProcessEngineTest::testDisinfectAfterWash":7,"tests\\flow\\nodes\\DisinfectNodeTest::testCanHandleAfterWash":8,"tests\\flow\\nodes\\DryNodeTest::testCanHandleAfterDisinfect":8,"tests\\flow\\UsageExampleTest::testExample4CustomVoice":8,"tests\\flow\\UsageExampleTest::testExample8TimeValidation":8,"tests\\flow\\UsageExampleTest::testLoadCustomProcessFromConfig":8,"tests\\flow\\UsageExampleTest::testCreateNoMorningWashFromConfig":8,"tests\\flow\\UsageExampleTest::testCreateMachineWashFromConfig":8,"tests\\flow\\UsageExampleTest::testCreateYiwuModeFromConfig":8,"tests\\flow\\UsageExampleTest::testExample1StandardProcess":8,"tests\\flow\\UsageExampleTest::testExample2NoMorningWash":8,"tests\\flow\\UsageExampleTest::testExample3DynamicAdjust":8,"tests\\flow\\UsageExampleTest::testExample5MorningWashModes":8,"tests\\flow\\UsageExampleTest::testExample6MachineWash":8,"tests\\flow\\UsageExampleTest::testExample7SimpleProcess":8,"tests\\flow\\UsageExampleTest::testExample9FullProcess":8,"tests\\flow\\UsageExampleTest::testExample10MultiHospital":8,"tests\\flow\\UsageExampleTest::testFlowProcessorUsage":8,"tests\\flow\\UsageExampleTest::testFlowProcessorCompleteProcess":8,"tests\\flow\\UsageExampleTest::testFlowProcessorWithConfig":8,"tests\\flow\\BatchConsistencyTest::testSingleMachineBatchConsistency":8,"tests\\flow\\BatchConsistencyTest::testMultiEndoscopeBatchUniqueness":8,"tests\\flow\\BatchConsistencyTest::testBatchNoStability":8,"tests\\flow\\BatchConsistencyTest::testNewProcessGeneratesNewBatchNo":8,"tests\\flow\\BatchConsistencyTest::testDistributedBatchConsistency":8,"tests\\flow\\PerformanceTest::testSingleExecutionPerformance":8,"tests\\flow\\PerformanceTest::testCompleteProcessPerformance":8,"tests\\flow\\PerformanceTest::testEngineCreationPerformance":8,"tests\\flow\\PerformanceTest::testConcurrentProcessingSimulation":8,"tests\\flow\\ProcessEngineTest::testCreateStandardEngine":8,"tests\\flow\\ProcessEngineTest::testCreateNoMorningWashEngine":8,"tests\\flow\\ProcessEngineTest::testCreateSimpleEngine":8,"tests\\flow\\ProcessEngineTest::testCompleteWashProcess":8,"tests\\flow\\ProcessEngineTest::testStandardWashRinseDisinfectFlow":8,"tests\\flow\\ProcessEngineTest::testDisableNode":8,"tests\\flow\\ProcessEngineTest::testGetNodes":8,"tests\\flow\\ProcessEngineTest::testGetEnabledNodes":8,"tests\\flow\\ProcessEngineTest::testUpdateConfig":8,"tests\\flow\\ProcessEngineTest::testMachineWashProcess":8,"tests\\db\\DBC::testDBConnect":8,"tests\\db\\DBC::testGenTables":7,"tests\\db\\DBC::testModel":5,"tests\\flow\\nodes\\DisinfectNodeTest::testNodeIdentity":8,"tests\\flow\\nodes\\DisinfectNodeTest::testCanHandleAfterRinse":8,"tests\\flow\\nodes\\DisinfectNodeTest::testCanHandleAfterFinalRinse":8,"tests\\flow\\nodes\\DisinfectNodeTest::testCannotHandleNonDisinfectReader":8,"tests\\flow\\nodes\\DisinfectNodeTest::testCannotHandleAfterDisinfect":8,"tests\\flow\\nodes\\DisinfectNodeTest::testHandleProcess":8,"tests\\flow\\nodes\\DisinfectNodeTest::testDatabaseOperationFlags":7,"tests\\flow\\nodes\\DisinfectNodeTest::testWebSocketNotifyFlag":8,"tests\\flow\\nodes\\DryNodeTest::testNodeIdentity":8,"tests\\flow\\nodes\\DryNodeTest::testCanHandleAfterFinalRinse":7,"tests\\flow\\nodes\\DryNodeTest::testCannotHandleAfterRinse":8,"tests\\flow\\nodes\\DryNodeTest::testCannotHandleNonDryReader":8,"tests\\flow\\nodes\\DryNodeTest::testCannotHandleAfterDry":7,"tests\\flow\\nodes\\DryNodeTest::testHandleProcess":7,"tests\\flow\\nodes\\DryNodeTest::testDatabaseOperationFlags":7,"tests\\flow\\nodes\\DryNodeTest::testWebSocketNotifyFlag":7,"tests\\flow\\nodes\\DryNodeTest::testKeepExistingBatchNo":8,"tests\\flow\\nodes\\MorningWashNodeTest::testNodeIdentity":8,"tests\\flow\\nodes\\MorningWashNodeTest::testCannotHandleWhenNoNeed":8,"tests\\flow\\nodes\\MorningWashNodeTest::testCannotHandleNonDisinfectMachineReader":8,"tests\\flow\\nodes\\MorningWashNodeTest::testCannotHandleWhenAlreadyWashed":8,"tests\\flow\\nodes\\EndNodeTest::testNodeIdentity":8,"tests\\flow\\nodes\\EndNodeTest::testCanHandleAfterDry":8,"tests\\flow\\nodes\\EndNodeTest::testCanHandleAfterDisinfect":7,"tests\\flow\\nodes\\EndNodeTest::testCanHandleAfterFinalRinse":8,"tests\\flow\\nodes\\EndNodeTest::testCanHandleAfterMachineWash":8,"tests\\flow\\nodes\\EndNodeTest::testCannotHandleNonEndReader":8,"tests\\flow\\nodes\\EndNodeTest::testCannotHandleAfterWash":8,"tests\\flow\\nodes\\EndNodeTest::testCannotHandleAfterRinse":8,"tests\\flow\\nodes\\EndNodeTest::testCannotHandleWithEmptyStep":8,"tests\\flow\\nodes\\EndNodeTest::testHandleProcess":8,"tests\\flow\\nodes\\EndNodeTest::testDatabaseOperationIsUpdate":7,"tests\\flow\\nodes\\EndNodeTest::testWebSocketNotifyFlag":8,"tests\\flow\\nodes\\EndNodeTest::testActionEndTimeIsSet":8,"tests\\flow\\nodes\\FinalRinseNodeTest::testCanHandleAfterDisinfect":8,"tests\\flow\\nodes\\FinalRinseNodeTest::testCanHandleAfterMachineWashByDefault":8,"tests\\flow\\nodes\\FinalRinseNodeTest::testCannotHandleAfterMachineWashWhenDisabled":8,"tests\\flow\\nodes\\FinalRinseNodeTest::testCannotHandleNonFinalRinseReader":8,"tests\\flow\\nodes\\FinalRinseNodeTest::testHandleProcess":8,"tests\\flow\\nodes\\FinalRinseNodeTest::testCannotHandleAfterWash":8,"tests\\flow\\nodes\\FinalRinseNodeTest::testDatabaseOperationFlags":8,"tests\\flow\\nodes\\FinalRinseNodeTest::testWebSocketNotifyFlag":8,"tests\\flow\\nodes\\FinalRinseNodeTest::testNodeIdentity":8,"tests\\flow\\nodes\\MachineWashNodeTest::testNodeIdentity":8,"tests\\flow\\nodes\\MachineWashNodeTest::testCanHandleAfterWash":8,"tests\\flow\\nodes\\MachineWashNodeTest::testCanHandleAfterRinse":7,"tests\\flow\\nodes\\MachineWashNodeTest::testCanHandleAfterDisinfect":7,"tests\\flow\\nodes\\MachineWashNodeTest::testCanHandleWithEmptyStep":7,"tests\\flow\\nodes\\MachineWashNodeTest::testCanHandleAfterEnd":7,"tests\\flow\\nodes\\MachineWashNodeTest::testCanHandleAfterEndoscopeOut":8,"tests\\flow\\nodes\\MachineWashNodeTest::testCannotHandleNonMachineWashReader":8,"tests\\flow\\nodes\\MachineWashNodeTest::testCannotHandleAfterFinalRinse":8,"tests\\flow\\nodes\\MachineWashNodeTest::testCannotHandleAfterDry":8,"tests\\flow\\nodes\\MachineWashNodeTest::testHandleProcess":8,"tests\\flow\\nodes\\MachineWashNodeTest::testDatabaseOperationFlags":7,"tests\\flow\\nodes\\MachineWashNodeTest::testWebSocketNotifyFlag":8,"tests\\flow\\nodes\\RinseNodeTest::testNodeIdentity":8,"tests\\flow\\nodes\\RinseNodeTest::testCanHandleAfterWash":7,"tests\\flow\\nodes\\RinseNodeTest::testCannotHandleNonRinseReader":8,"tests\\flow\\nodes\\RinseNodeTest::testCannotHandleAfterDisinfect":7,"tests\\flow\\nodes\\RinseNodeTest::testCannotHandleWithEmptyStep":7,"tests\\flow\\nodes\\RinseNodeTest::testCannotHandleAfterRinse":7,"tests\\flow\\nodes\\RinseNodeTest::testHandleProcess":7,"tests\\flow\\nodes\\RinseNodeTest::testDatabaseOperationFlags":7,"tests\\flow\\nodes\\RinseNodeTest::testWebSocketNotifyFlag":7,"tests\\flow\\nodes\\RinseNodeTest::testDisabledNodeSkips":8,"tests\\flow\\nodes\\WashNodeTest::testNodeIdentity":8,"tests\\flow\\nodes\\WashNodeTest::testCanHandleWashReader":8,"tests\\flow\\nodes\\WashNodeTest::testCannotHandleNonWashReader":8,"tests\\flow\\nodes\\WashNodeTest::testCanStartNewWashProcess":8,"tests\\flow\\nodes\\WashNodeTest::testCannotWashWithoutMorningWash":8,"tests\\flow\\nodes\\WashNodeTest::testHandleProcess":8,"tests\\flow\\nodes\\WashNodeTest::testGenerateBatchNo":7,"tests\\flow\\nodes\\WashNodeTest::testKeepExistingBatchNo":8,"tests\\flow\\strategies\\TimeValidationStrategyTest::testTimeRequirementNotMet":7,"tests\\flow\\strategies\\TimeValidationStrategyTest::testSetStepDuration":7,"tests\\flow\\FlowProcessorTest::testSuccessfulFlowSavesToDatabase":8,"tests\\flow\\FlowProcessorTest::testEndOperationIsUpdate":8,"tests\\flow\\FlowProcessorTest::testGetActionTypeMapping":8,"tests\\flow\\EdgeCaseTest::testLongEndoscopeName":7,"tests\\flow\\EdgeCaseTest::testSpecialCharactersInName":7,"tests\\flow\\ProcessContextTest::testGetFullVoice":7,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testFullVoiceIncludesEndoscopeName":7,"tests\\flow\\FlowProcessorTest::testSuccessfulFlowSendsVoice":8,"tests\\flow\\FlowProcessorTest::testFailedFlowDoesNotSaveToDatabase":8,"tests\\flow\\FlowProcessorTest::testFailedFlowStillSendsVoice":8,"tests\\flow\\FlowProcessorTest::testWebSocketNotificationSentWhenNeeded":8,"tests\\flow\\FlowProcessorTest::testWebSocketNotificationNotSentWhenNotNeeded":8,"tests\\flow\\FlowProcessorTest::testStaticFactoryCreate":8,"tests\\flow\\EdgeCaseTest::testAllNodesDisabled":8,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testFinalRinseVoice":8,"tests\\flow\\ProcessSimulationTest::testDuplicateCheckNode":7,"tests\\flow\\FullProcessTest::testCompleteManualWashProcess":7,"tests\\flow\\FullProcessTest::testSwipeEndoscopeWithoutOperator":7,"tests\\flow\\cases\\BlockTest::testProcessChainExecution":5},"times":{"tests\\flow\\FlowProcessorTest::testCreateProcessor":0.006,"tests\\flow\\FlowProcessorTest::testCreateProcessorWithConfig":0.006,"tests\\flow\\FlowProcessorTest::testStaticFactory":0.006,"tests\\flow\\FlowProcessorTest::testUpdateConfig":0.009,"tests\\flow\\FlowProcessorTest::testBatchNoConsistency":0.006,"tests\\flow\\FlowProcessorTest::testBatchNoConsistencyInCompleteProcess":0.008,"tests\\flow\\FlowProcessorTest::testDatabaseOperationFlags":0.006,"tests\\flow\\FlowProcessorTest::testWebSocketNotifyFlag":0.005,"tests\\flow\\FlowProcessorTest::testVoiceGeneration":0.007,"tests\\flow\\FlowProcessorTest::testErrorVoiceGeneration":0.006,"tests\\flow\\FlowProcessorTest::testMultiHospitalConfig":0.007,"tests\\flow\\FlowProcessorTest::testSpecialHospitalConfig":0.006,"tests\\flow\\ProcessContextTest::testCreateContext":0.005,"tests\\flow\\ProcessContextTest::testSetError":0.006,"tests\\flow\\ProcessContextTest::testSetVoice":0.006,"tests\\flow\\ProcessContextTest::testGetFullVoice":0.006,"tests\\flow\\ProcessContextTest::testStepTimeManagement":0.006,"tests\\flow\\ProcessContextTest::testStepDurationManagement":0.005,"tests\\flow\\ProcessContextTest::testDefaultStepDuration":0.007,"tests\\flow\\ProcessContextTest::testGenerateBatchNo":0.006,"tests\\flow\\ProcessContextTest::testBatchNoUniqueness":0.006,"tests\\flow\\ProcessContextTest::testCanStartNewProcess":0.006,"tests\\flow\\ProcessContextTest::testIsWashProcessCompleted":0.006,"tests\\flow\\ProcessContextTest::testChaining":0.005,"tests\\flow\\ProcessEngineTest::testCreateStandardEngine":0.006,"tests\\flow\\ProcessEngineTest::testCreateNoMorningWashEngine":0.006,"tests\\flow\\ProcessEngineTest::testCreateSimpleEngine":0.006,"tests\\flow\\ProcessEngineTest::testCompleteWashProcess":0.045,"tests\\flow\\ProcessEngineTest::testTimeValidationFailure":0.005,"tests\\flow\\ProcessEngineTest::testWrongStep":0.01,"tests\\flow\\ProcessEngineTest::testDisableNode":0.005,"tests\\flow\\ProcessEngineTest::testGetNodes":0.006,"tests\\flow\\ProcessEngineTest::testGetEnabledNodes":0.005,"tests\\flow\\ProcessEngineTest::testUpdateConfig":0.006,"tests\\flow\\ProcessEngineTest::testMachineWashProcess":0.033,"tests\\flow\\nodes\\FinalRinseNodeTest::testCanHandleAfterDisinfect":0.007,"tests\\flow\\nodes\\FinalRinseNodeTest::testCanHandleAfterMachineWashByDefault":0.005,"tests\\flow\\nodes\\FinalRinseNodeTest::testCannotHandleAfterMachineWashWhenDisabled":0.008,"tests\\flow\\nodes\\FinalRinseNodeTest::testCannotHandleNonFinalRinseReader":0.008,"tests\\flow\\nodes\\FinalRinseNodeTest::testHandleProcess":0.01,"tests\\flow\\nodes\\WashNodeTest::testNodeIdentity":0.006,"tests\\flow\\nodes\\WashNodeTest::testCanHandleWashReader":0.006,"tests\\flow\\nodes\\WashNodeTest::testCannotHandleNonWashReader":0.005,"tests\\flow\\nodes\\WashNodeTest::testCanStartNewWashProcess":0.005,"tests\\flow\\nodes\\WashNodeTest::testCannotWashWithoutMorningWash":0.006,"tests\\flow\\nodes\\WashNodeTest::testHandleProcess":0.009,"tests\\flow\\nodes\\WashNodeTest::testGenerateBatchNo":0.008,"tests\\flow\\nodes\\WashNodeTest::testKeepExistingBatchNo":0.006,"tests\\flow\\strategies\\MorningWashStrategyTest::testNoneMode":0.006,"tests\\flow\\strategies\\MorningWashStrategyTest::testAllMode":0.005,"tests\\flow\\strategies\\MorningWashStrategyTest::testDailyFirstModeWithNoRecords":0.005,"tests\\flow\\strategies\\MorningWashStrategyTest::testDailyFirstModeWithRecords":0.006,"tests\\flow\\strategies\\MorningWashStrategyTest::testSpecificTypesMode":0.005,"tests\\flow\\strategies\\MorningWashStrategyTest::testStorageTimeMode":0.006,"tests\\flow\\strategies\\MorningWashStrategyTest::testStrategyName":0.005,"tests\\flow\\strategies\\TimeValidationStrategyTest::testNoTimeLimitForFirstTime":0.005,"tests\\flow\\strategies\\TimeValidationStrategyTest::testTimeRequirementMet":0.006,"tests\\flow\\strategies\\TimeValidationStrategyTest::testTimeRequirementNotMet":0.005,"tests\\flow\\strategies\\TimeValidationStrategyTest::testCustomDuration":0.006,"tests\\flow\\strategies\\TimeValidationStrategyTest::testIsApplicable":0.006,"tests\\flow\\strategies\\TimeValidationStrategyTest::testStrategyName":0.006,"tests\\flow\\strategies\\TimeValidationStrategyTest::testStrategyPhase":0.005,"tests\\flow\\ProcessEngineTest::testSkipStep":0.012,"tests\\flow\\ProcessEngineTest::testDisinfectAfterWash":0.005,"tests\\flow\\BatchConsistencyTest::testSingleMachineBatchConsistency":0.046,"tests\\flow\\BatchConsistencyTest::testMultiEndoscopeBatchUniqueness":0.036,"tests\\flow\\BatchConsistencyTest::testBatchNoFormat":0.008,"tests\\flow\\BatchConsistencyTest::testBatchNoStability":0.02,"tests\\flow\\BatchConsistencyTest::testNewProcessGeneratesNewBatchNo":0.024,"tests\\flow\\BatchConsistencyTest::testDistributedBatchConsistency":0.057,"tests\\flow\\BatchConsistencyTest::testBatchNoPreservedOnError":0.024,"tests\\flow\\BatchConsistencyTest::testBatchNoWithDifferentProcessTypes":0.022,"tests\\flow\\EdgeCaseTest::testEmptyContext":0.005,"tests\\flow\\EdgeCaseTest::testLongEndoscopeName":0.006,"tests\\flow\\EdgeCaseTest::testSpecialCharactersInName":0.006,"tests\\flow\\EdgeCaseTest::testBatchNoGenerationEdgeCases":0.006,"tests\\flow\\EdgeCaseTest::testTimeBoundaryValues":0.006,"tests\\flow\\EdgeCaseTest::testEmptyChain":0.005,"tests\\flow\\EdgeCaseTest::testAllNodesDisabled":0.021,"tests\\flow\\EdgeCaseTest::testRepeatedStepTimeSetting":0.006,"tests\\flow\\EdgeCaseTest::testChainingEdgeCases":0.006,"tests\\flow\\EdgeCaseTest::testErrorStateOverwrite":0.006,"tests\\flow\\EdgeCaseTest::testRecoveryFromError":0.005,"tests\\flow\\EdgeCaseTest::testInvalidConfigItems":0.007,"tests\\flow\\EdgeCaseTest::testConcurrentBatchNoGeneration":0.011,"tests\\flow\\EdgeCaseTest::testMorningWashBoundaryTime":0.006,"tests\\flow\\EdgeCaseTest::testStorageTimeBoundary":0.007,"tests\\flow\\EdgeCaseTest::testStorageTimeOverThreshold":0.005,"tests\\flow\\PerformanceTest::testSingleExecutionPerformance":0.011,"tests\\flow\\PerformanceTest::testCompleteProcessPerformance":0.039,"tests\\flow\\PerformanceTest::testBatchNoGenerationPerformance":0.023,"tests\\flow\\PerformanceTest::testEngineCreationPerformance":0.094,"tests\\flow\\PerformanceTest::testConfigLoadingPerformance":0.023,"tests\\flow\\PerformanceTest::testContextCreationPerformance":0.258,"tests\\flow\\PerformanceTest::testStrategyExecutionPerformance":0.156,"tests\\flow\\PerformanceTest::testMemoryUsage":0.226,"tests\\flow\\PerformanceTest::testConcurrentProcessingSimulation":0.058,"tests\\flow\\PerformanceTest::testChainTraversalPerformance":5.796,"tests\\flow\\config\\ProcessConfigTest::testCreateDefaultConfig":0.007,"tests\\flow\\config\\ProcessConfigTest::testFromArray":0.006,"tests\\flow\\config\\ProcessConfigTest::testGetEnabledSteps":0.007,"tests\\flow\\config\\ProcessConfigTest::testAddStep":0.006,"tests\\flow\\config\\ProcessConfigTest::testRemoveStep":0.005,"tests\\flow\\config\\ProcessConfigTest::testSetNodeEnabled":0.008,"tests\\flow\\config\\ProcessConfigTest::testMorningWashConfig":0.006,"tests\\flow\\config\\ProcessConfigTest::testTimeValidationConfig":0.007,"tests\\flow\\config\\ProcessConfigTest::testVoiceTemplateConfig":0.005,"tests\\flow\\config\\ProcessConfigTest::testSetStepVoice":0.006,"tests\\flow\\config\\ProcessConfigTest::testToArray":0.007,"tests\\flow\\config\\ProcessConfigTest::testCreateStandard":0.006,"tests\\flow\\config\\ProcessConfigTest::testCreateNoMorningWash":0.007,"tests\\flow\\config\\ProcessConfigTest::testCreateSimple":0.006,"tests\\flow\\config\\ProcessConfigTest::testCreateMachineWash":0.005,"tests\\flow\\config\\ProcessConfigTest::testCreateNoDry":0.006,"tests\\flow\\config\\ProcessConfigTest::testCreateDryOnly":0.005,"tests\\flow\\config\\ProcessConfigTest::testChaining":0.006,"tests\\flow\\nodes\\DisinfectNodeTest::testNodeIdentity":0.005,"tests\\flow\\nodes\\DisinfectNodeTest::testCanHandleAfterRinse":0.005,"tests\\flow\\nodes\\DisinfectNodeTest::testCanHandleAfterFinalRinse":0.005,"tests\\flow\\nodes\\DisinfectNodeTest::testCanHandleAfterWash":0.005,"tests\\flow\\nodes\\DisinfectNodeTest::testCannotHandleNonDisinfectReader":0.005,"tests\\flow\\nodes\\DisinfectNodeTest::testCannotHandleAfterDisinfect":0.005,"tests\\flow\\nodes\\DisinfectNodeTest::testHandleProcess":0.009,"tests\\flow\\nodes\\DisinfectNodeTest::testDatabaseOperationFlags":0.008,"tests\\flow\\nodes\\DisinfectNodeTest::testWebSocketNotifyFlag":0.008,"tests\\flow\\nodes\\MorningWashNodeTest::testNodeIdentity":0.005,"tests\\flow\\nodes\\MorningWashNodeTest::testCanHandleMorningWashReader":0.021,"tests\\flow\\nodes\\MorningWashNodeTest::testCannotHandleWhenNoNeed":0.006,"tests\\flow\\nodes\\MorningWashNodeTest::testCannotHandleNonMorningWashReader":0.005,"tests\\flow\\nodes\\MorningWashNodeTest::testCannotHandleWhenAlreadyWashed":0.005,"tests\\flow\\nodes\\MorningWashNodeTest::testHandleProcess":0.008,"tests\\flow\\nodes\\MorningWashNodeTest::testGenerateBatchNo":0.009,"tests\\flow\\nodes\\MorningWashNodeTest::testCanHandleDisinfectReaderForMorningWash":0.006,"tests\\flow\\nodes\\MorningWashNodeTest::testCanHandleMachineWashReaderForMorningWash":0.005,"tests\\flow\\nodes\\MorningWashNodeTest::testCannotHandleNonDisinfectMachineReader":0.006,"tests\\flow\\nodes\\MorningWashNodeTest::testHandleProcessWithDisinfect":0.009,"tests\\flow\\nodes\\MorningWashNodeTest::testHandleProcessWithMachineWash":0.009,"tests\\flow\\nodes\\DryNodeTest::testNodeIdentity":0.006,"tests\\flow\\nodes\\DryNodeTest::testCanHandleAfterFinalRinse":0.007,"tests\\flow\\nodes\\DryNodeTest::testCanHandleAfterDisinfect":0.006,"tests\\flow\\nodes\\DryNodeTest::testCannotHandleAfterRinse":0.005,"tests\\flow\\nodes\\DryNodeTest::testCannotHandleNonDryReader":0.007,"tests\\flow\\nodes\\DryNodeTest::testCannotHandleAfterDry":0.006,"tests\\flow\\nodes\\DryNodeTest::testHandleProcess":0.008,"tests\\flow\\nodes\\DryNodeTest::testDatabaseOperationFlags":0.009,"tests\\flow\\nodes\\DryNodeTest::testWebSocketNotifyFlag":0.008,"tests\\flow\\nodes\\DryNodeTest::testKeepExistingBatchNo":0.01,"tests\\flow\\ProcessEngineTest::testStandardWashRinseDisinfectFlow":0.023,"tests\\flow\\UsageExampleTest::testExample1StandardProcess":0.022,"tests\\flow\\UsageExampleTest::testExample2NoMorningWash":0.025,"tests\\flow\\UsageExampleTest::testExample3DynamicAdjust":0.048,"tests\\flow\\UsageExampleTest::testExample4CustomVoice":0.022,"tests\\flow\\UsageExampleTest::testExample5MorningWashModes":0.033,"tests\\flow\\UsageExampleTest::testExample6MachineWash":0.022,"tests\\flow\\UsageExampleTest::testExample7SimpleProcess":0.021,"tests\\flow\\UsageExampleTest::testExample8TimeValidation":0.021,"tests\\flow\\UsageExampleTest::testExample9FullProcess":0.021,"tests\\flow\\UsageExampleTest::testExample10MultiHospital":0.046,"tests\\flow\\UsageExampleTest::testLoadCustomProcessFromConfig":0.007,"tests\\flow\\UsageExampleTest::testCreateNoMorningWashFromConfig":0.042,"tests\\flow\\UsageExampleTest::testCreateMachineWashFromConfig":0.036,"tests\\flow\\UsageExampleTest::testCreateYiwuModeFromConfig":0.015,"tests\\flow\\UsageExampleTest::testFlowProcessorUsage":0.045,"tests\\flow\\UsageExampleTest::testFlowProcessorCompleteProcess":0.021,"tests\\flow\\UsageExampleTest::testFlowProcessorWithConfig":0.037,"tests\\db\\DBC::testDBConnect":0.113,"tests\\db\\DBC::testGenTables":0.416,"tests\\db\\DBC::testModel":0.171,"tests\\flow\\nodes\\EndNodeTest::testNodeIdentity":0.006,"tests\\flow\\nodes\\EndNodeTest::testCanHandleAfterDry":0.006,"tests\\flow\\nodes\\EndNodeTest::testCanHandleAfterDisinfect":0.005,"tests\\flow\\nodes\\EndNodeTest::testCanHandleAfterFinalRinse":0.005,"tests\\flow\\nodes\\EndNodeTest::testCanHandleAfterMachineWash":0.005,"tests\\flow\\nodes\\EndNodeTest::testCannotHandleNonEndReader":0.005,"tests\\flow\\nodes\\EndNodeTest::testCannotHandleAfterWash":0.007,"tests\\flow\\nodes\\EndNodeTest::testCannotHandleAfterRinse":0.006,"tests\\flow\\nodes\\EndNodeTest::testCannotHandleWithEmptyStep":0.005,"tests\\flow\\nodes\\EndNodeTest::testHandleProcess":0.009,"tests\\flow\\nodes\\EndNodeTest::testDatabaseOperationIsUpdate":0.011,"tests\\flow\\nodes\\EndNodeTest::testWebSocketNotifyFlag":0.009,"tests\\flow\\nodes\\EndNodeTest::testActionEndTimeIsSet":0.009,"tests\\flow\\nodes\\FinalRinseNodeTest::testCannotHandleAfterWash":0.006,"tests\\flow\\nodes\\FinalRinseNodeTest::testDatabaseOperationFlags":0.008,"tests\\flow\\nodes\\FinalRinseNodeTest::testWebSocketNotifyFlag":0.009,"tests\\flow\\nodes\\FinalRinseNodeTest::testNodeIdentity":0.005,"tests\\flow\\nodes\\MachineWashNodeTest::testNodeIdentity":0.005,"tests\\flow\\nodes\\MachineWashNodeTest::testCanHandleAfterWash":0.005,"tests\\flow\\nodes\\MachineWashNodeTest::testCanHandleAfterRinse":0.005,"tests\\flow\\nodes\\MachineWashNodeTest::testCanHandleAfterDisinfect":0.005,"tests\\flow\\nodes\\MachineWashNodeTest::testCanHandleWithEmptyStep":0.006,"tests\\flow\\nodes\\MachineWashNodeTest::testCanHandleAfterEnd":0.006,"tests\\flow\\nodes\\MachineWashNodeTest::testCanHandleAfterEndoscopeOut":0.005,"tests\\flow\\nodes\\MachineWashNodeTest::testCannotHandleNonMachineWashReader":0.005,"tests\\flow\\nodes\\MachineWashNodeTest::testCannotHandleAfterFinalRinse":0.005,"tests\\flow\\nodes\\MachineWashNodeTest::testCannotHandleAfterDry":0.006,"tests\\flow\\nodes\\MachineWashNodeTest::testHandleProcess":0.008,"tests\\flow\\nodes\\MachineWashNodeTest::testDatabaseOperationFlags":0.01,"tests\\flow\\nodes\\MachineWashNodeTest::testWebSocketNotifyFlag":0.008,"tests\\flow\\nodes\\RinseNodeTest::testNodeIdentity":0.005,"tests\\flow\\nodes\\RinseNodeTest::testCanHandleAfterWash":0.007,"tests\\flow\\nodes\\RinseNodeTest::testCannotHandleNonRinseReader":0.007,"tests\\flow\\nodes\\RinseNodeTest::testCannotHandleAfterDisinfect":0.006,"tests\\flow\\nodes\\RinseNodeTest::testCannotHandleWithEmptyStep":0.006,"tests\\flow\\nodes\\RinseNodeTest::testCannotHandleAfterRinse":0.005,"tests\\flow\\nodes\\RinseNodeTest::testHandleProcess":0.01,"tests\\flow\\nodes\\RinseNodeTest::testDatabaseOperationFlags":0.009,"tests\\flow\\nodes\\RinseNodeTest::testWebSocketNotifyFlag":0.009,"tests\\flow\\nodes\\RinseNodeTest::testDisabledNodeSkips":0.009,"tests\\flow\\strategies\\TimeValidationStrategyTest::testNonDurationStepIsSkipped":0.008,"tests\\flow\\strategies\\TimeValidationStrategyTest::testSetStepDuration":0.006,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testStrategyName":0.007,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testStrategyPhaseIsAfter":0.006,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testIsAlwaysApplicable":0.007,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testNormalWashVoice":0.005,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testNormalRinseVoice":0.005,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testNormalDisinfectVoice":0.005,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testFinalRinseVoice":0.006,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testDryVoice":0.006,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testEndVoice":0.005,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testMachineWashVoice":0.007,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testMorningWashVoice":0.005,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testMachineMorningWashVoice":0.006,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testErrorStateGeneratesErrorVoice":0.006,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testFullVoiceIncludesEndoscopeName":0.006,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testLeakTestRemindAppended":0.006,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testStorageRemindAppended":0.005,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testCustomVoiceTemplate":0.005,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testSetStepVoice":0.005,"tests\\flow\\FlowProcessorTest::testSuccessfulFlowSavesToDatabase":0.011,"tests\\flow\\FlowProcessorTest::testSuccessfulFlowSendsVoice":0.008,"tests\\flow\\FlowProcessorTest::testFailedFlowDoesNotSaveToDatabase":0.007,"tests\\flow\\FlowProcessorTest::testFailedFlowStillSendsVoice":0.008,"tests\\flow\\FlowProcessorTest::testWebSocketNotificationSentWhenNeeded":0.01,"tests\\flow\\FlowProcessorTest::testWebSocketNotificationNotSentWhenNotNeeded":0.008,"tests\\flow\\FlowProcessorTest::testEndOperationIsUpdate":0.01,"tests\\flow\\FlowProcessorTest::testGetActionTypeMapping":0.107,"tests\\flow\\FlowProcessorTest::testStaticFactoryCreate":0.007,"tests\\flow\\ProcessSimulationTest::testBasicManualWashWithoutDatabase":0.287,"tests\\flow\\ProcessSimulationTest::testNodeChainConstruction":0.264,"tests\\flow\\ProcessSimulationTest::testMorningWashNodeConfiguration":0.278,"tests\\flow\\ProcessSimulationTest::testMachineWashNodeConfiguration":0.271,"tests\\flow\\ProcessSimulationTest::testStorageNodeConfiguration":0.273,"tests\\flow\\ProcessSimulationTest::testDuplicateCheckNode":0.522,"tests\\flow\\ProcessSimulationTest::testCloseNode":0.268,"tests\\flow\\ProcessSimulationTest::testNodeEnableDisable":0.268,"tests\\flow\\ProcessSimulationTest::testConfigUpdate":0.522,"tests\\flow\\ProcessSimulationTest::testStrategyInitialization":0.291,"tests\\flow\\FullProcessTest::testCompleteManualWashProcess":0.09,"tests\\flow\\FullProcessTest::testCompleteManualWashProcessUsingHelper":0.285,"tests\\flow\\FullProcessTest::testMorningWashRequired":0.262,"tests\\flow\\FullProcessTest::testManualWashAfterMorningWash":0.269,"tests\\flow\\FullProcessTest::testMachineWashProcess":0.281,"tests\\flow\\FullProcessTest::testMachineWashProcessUsingHelper":0.286,"tests\\flow\\FullProcessTest::testMorningWashThenMachineWash":0.275,"tests\\flow\\FullProcessTest::testSwipeEndoscopeWithoutOperator":0.02,"tests\\flow\\FullProcessTest::testWrongStepOrder":0.078,"tests\\flow\\FullProcessTest::testDuplicateSwipe":0.142,"tests\\flow\\FullProcessTest::testUnboundReader":0.273,"tests\\flow\\FullProcessTest::testUnboundEndoscope":0.323,"tests\\flow\\FullProcessTest::testDifferentOperatorContinueProcess":0.124,"tests\\flow\\FullProcessTest::testWashStepVoice":0.074,"tests\\flow\\FullProcessTest::testDisinfectStepVoice":0.182,"tests\\flow\\FullProcessTest::testOperatorCardVoice":0.02,"tests\\flow\\FullProcessTest::testErrorVoice":0.021,"tests\\flow\\FullProcessTest::testVoiceTemplateParams":0.077,"tests\\flow\\FullProcessTest::testProcessChainExecution":0.236,"tests\\flow\\FullProcessTest::testDisabledNodeSkipped":0.277,"tests\\flow\\FullProcessTest::testTimeValidationBlock":0.265,"tests\\flow\\FullProcessTest::testDuplicateSwipeBlock":0.201,"tests\\flow\\FullProcessTest::testNewProcessAfterComplete":0.331,"tests\\flow\\FullProcessTest::testConcurrentProcessIsolation":0.174,"tests\\flow\\FullProcessTest::testProcessorReset":0.081,"tests\\flow\\FullProcessTest::testVirtualContextBuilder":0.017,"tests\\flow\\FullProcessTest::testEnvironmentConfig":0.007,"tests\\flow\\Test::testExample":0.005,"tests\\flow\\cases\\BlockTest::testProcessChainExecution":0.243}} \ No newline at end of file +{"version":2,"defects":{"tests\\flow\\FlowProcessorTest::testCreateProcessor":8,"tests\\flow\\FlowProcessorTest::testCreateProcessorWithConfig":8,"tests\\flow\\FlowProcessorTest::testUpdateConfig":8,"tests\\flow\\FlowProcessorTest::testBatchNoConsistency":8,"tests\\flow\\FlowProcessorTest::testBatchNoConsistencyInCompleteProcess":8,"tests\\flow\\FlowProcessorTest::testDatabaseOperationFlags":8,"tests\\flow\\FlowProcessorTest::testWebSocketNotifyFlag":8,"tests\\flow\\FlowProcessorTest::testVoiceGeneration":8,"tests\\flow\\FlowProcessorTest::testErrorVoiceGeneration":7,"tests\\flow\\FlowProcessorTest::testMultiHospitalConfig":8,"tests\\flow\\FlowProcessorTest::testSpecialHospitalConfig":8,"tests\\flow\\ProcessEngineTest::testTimeValidationFailure":8,"tests\\flow\\ProcessEngineTest::testWrongStep":7,"tests\\flow\\strategies\\TimeValidationStrategyTest::testCustomDuration":7,"tests\\flow\\ProcessEngineTest::testSkipStep":7,"tests\\flow\\BatchConsistencyTest::testBatchNoPreservedOnError":8,"tests\\flow\\BatchConsistencyTest::testBatchNoWithDifferentProcessTypes":8,"tests\\flow\\EdgeCaseTest::testBatchNoGenerationEdgeCases":7,"tests\\flow\\PerformanceTest::testContextCreationPerformance":7,"tests\\flow\\PerformanceTest::testStrategyExecutionPerformance":7,"tests\\flow\\PerformanceTest::testChainTraversalPerformance":8,"tests\\flow\\nodes\\MorningWashNodeTest::testCanHandleMorningWashReader":7,"tests\\flow\\nodes\\MorningWashNodeTest::testHandleProcess":7,"tests\\flow\\nodes\\MorningWashNodeTest::testGenerateBatchNo":8,"tests\\flow\\nodes\\MorningWashNodeTest::testCanHandleDisinfectReaderForMorningWash":8,"tests\\flow\\nodes\\MorningWashNodeTest::testCanHandleMachineWashReaderForMorningWash":8,"tests\\flow\\nodes\\MorningWashNodeTest::testHandleProcessWithDisinfect":8,"tests\\flow\\nodes\\MorningWashNodeTest::testHandleProcessWithMachineWash":8,"tests\\flow\\EdgeCaseTest::testConcurrentBatchNoGeneration":7,"tests\\flow\\ProcessEngineTest::testDisinfectAfterWash":7,"tests\\flow\\nodes\\DisinfectNodeTest::testCanHandleAfterWash":8,"tests\\flow\\nodes\\DryNodeTest::testCanHandleAfterDisinfect":8,"tests\\flow\\UsageExampleTest::testExample4CustomVoice":8,"tests\\flow\\UsageExampleTest::testExample8TimeValidation":8,"tests\\flow\\UsageExampleTest::testLoadCustomProcessFromConfig":8,"tests\\flow\\UsageExampleTest::testCreateNoMorningWashFromConfig":8,"tests\\flow\\UsageExampleTest::testCreateMachineWashFromConfig":8,"tests\\flow\\UsageExampleTest::testCreateYiwuModeFromConfig":8,"tests\\flow\\UsageExampleTest::testExample1StandardProcess":8,"tests\\flow\\UsageExampleTest::testExample2NoMorningWash":8,"tests\\flow\\UsageExampleTest::testExample3DynamicAdjust":8,"tests\\flow\\UsageExampleTest::testExample5MorningWashModes":8,"tests\\flow\\UsageExampleTest::testExample6MachineWash":8,"tests\\flow\\UsageExampleTest::testExample7SimpleProcess":8,"tests\\flow\\UsageExampleTest::testExample9FullProcess":8,"tests\\flow\\UsageExampleTest::testExample10MultiHospital":8,"tests\\flow\\UsageExampleTest::testFlowProcessorUsage":8,"tests\\flow\\UsageExampleTest::testFlowProcessorCompleteProcess":8,"tests\\flow\\UsageExampleTest::testFlowProcessorWithConfig":8,"tests\\flow\\BatchConsistencyTest::testSingleMachineBatchConsistency":8,"tests\\flow\\BatchConsistencyTest::testMultiEndoscopeBatchUniqueness":8,"tests\\flow\\BatchConsistencyTest::testBatchNoStability":8,"tests\\flow\\BatchConsistencyTest::testNewProcessGeneratesNewBatchNo":8,"tests\\flow\\BatchConsistencyTest::testDistributedBatchConsistency":8,"tests\\flow\\PerformanceTest::testSingleExecutionPerformance":8,"tests\\flow\\PerformanceTest::testCompleteProcessPerformance":8,"tests\\flow\\PerformanceTest::testEngineCreationPerformance":8,"tests\\flow\\PerformanceTest::testConcurrentProcessingSimulation":8,"tests\\flow\\ProcessEngineTest::testCreateStandardEngine":8,"tests\\flow\\ProcessEngineTest::testCreateNoMorningWashEngine":8,"tests\\flow\\ProcessEngineTest::testCreateSimpleEngine":8,"tests\\flow\\ProcessEngineTest::testCompleteWashProcess":8,"tests\\flow\\ProcessEngineTest::testStandardWashRinseDisinfectFlow":8,"tests\\flow\\ProcessEngineTest::testDisableNode":8,"tests\\flow\\ProcessEngineTest::testGetNodes":8,"tests\\flow\\ProcessEngineTest::testGetEnabledNodes":8,"tests\\flow\\ProcessEngineTest::testUpdateConfig":8,"tests\\flow\\ProcessEngineTest::testMachineWashProcess":8,"tests\\db\\DBC::testDBConnect":8,"tests\\db\\DBC::testGenTables":7,"tests\\db\\DBC::testModel":5,"tests\\flow\\nodes\\DisinfectNodeTest::testNodeIdentity":8,"tests\\flow\\nodes\\DisinfectNodeTest::testCanHandleAfterRinse":8,"tests\\flow\\nodes\\DisinfectNodeTest::testCanHandleAfterFinalRinse":8,"tests\\flow\\nodes\\DisinfectNodeTest::testCannotHandleNonDisinfectReader":8,"tests\\flow\\nodes\\DisinfectNodeTest::testCannotHandleAfterDisinfect":8,"tests\\flow\\nodes\\DisinfectNodeTest::testHandleProcess":8,"tests\\flow\\nodes\\DisinfectNodeTest::testDatabaseOperationFlags":7,"tests\\flow\\nodes\\DisinfectNodeTest::testWebSocketNotifyFlag":8,"tests\\flow\\nodes\\DryNodeTest::testNodeIdentity":8,"tests\\flow\\nodes\\DryNodeTest::testCanHandleAfterFinalRinse":7,"tests\\flow\\nodes\\DryNodeTest::testCannotHandleAfterRinse":8,"tests\\flow\\nodes\\DryNodeTest::testCannotHandleNonDryReader":8,"tests\\flow\\nodes\\DryNodeTest::testCannotHandleAfterDry":7,"tests\\flow\\nodes\\DryNodeTest::testHandleProcess":7,"tests\\flow\\nodes\\DryNodeTest::testDatabaseOperationFlags":7,"tests\\flow\\nodes\\DryNodeTest::testWebSocketNotifyFlag":7,"tests\\flow\\nodes\\DryNodeTest::testKeepExistingBatchNo":8,"tests\\flow\\nodes\\MorningWashNodeTest::testNodeIdentity":8,"tests\\flow\\nodes\\MorningWashNodeTest::testCannotHandleWhenNoNeed":8,"tests\\flow\\nodes\\MorningWashNodeTest::testCannotHandleNonDisinfectMachineReader":8,"tests\\flow\\nodes\\MorningWashNodeTest::testCannotHandleWhenAlreadyWashed":8,"tests\\flow\\nodes\\EndNodeTest::testNodeIdentity":8,"tests\\flow\\nodes\\EndNodeTest::testCanHandleAfterDry":8,"tests\\flow\\nodes\\EndNodeTest::testCanHandleAfterDisinfect":7,"tests\\flow\\nodes\\EndNodeTest::testCanHandleAfterFinalRinse":8,"tests\\flow\\nodes\\EndNodeTest::testCanHandleAfterMachineWash":8,"tests\\flow\\nodes\\EndNodeTest::testCannotHandleNonEndReader":8,"tests\\flow\\nodes\\EndNodeTest::testCannotHandleAfterWash":8,"tests\\flow\\nodes\\EndNodeTest::testCannotHandleAfterRinse":8,"tests\\flow\\nodes\\EndNodeTest::testCannotHandleWithEmptyStep":8,"tests\\flow\\nodes\\EndNodeTest::testHandleProcess":8,"tests\\flow\\nodes\\EndNodeTest::testDatabaseOperationIsUpdate":7,"tests\\flow\\nodes\\EndNodeTest::testWebSocketNotifyFlag":8,"tests\\flow\\nodes\\EndNodeTest::testActionEndTimeIsSet":8,"tests\\flow\\nodes\\FinalRinseNodeTest::testCanHandleAfterDisinfect":8,"tests\\flow\\nodes\\FinalRinseNodeTest::testCanHandleAfterMachineWashByDefault":8,"tests\\flow\\nodes\\FinalRinseNodeTest::testCannotHandleAfterMachineWashWhenDisabled":8,"tests\\flow\\nodes\\FinalRinseNodeTest::testCannotHandleNonFinalRinseReader":8,"tests\\flow\\nodes\\FinalRinseNodeTest::testHandleProcess":8,"tests\\flow\\nodes\\FinalRinseNodeTest::testCannotHandleAfterWash":8,"tests\\flow\\nodes\\FinalRinseNodeTest::testDatabaseOperationFlags":8,"tests\\flow\\nodes\\FinalRinseNodeTest::testWebSocketNotifyFlag":8,"tests\\flow\\nodes\\FinalRinseNodeTest::testNodeIdentity":8,"tests\\flow\\nodes\\MachineWashNodeTest::testNodeIdentity":8,"tests\\flow\\nodes\\MachineWashNodeTest::testCanHandleAfterWash":8,"tests\\flow\\nodes\\MachineWashNodeTest::testCanHandleAfterRinse":7,"tests\\flow\\nodes\\MachineWashNodeTest::testCanHandleAfterDisinfect":7,"tests\\flow\\nodes\\MachineWashNodeTest::testCanHandleWithEmptyStep":7,"tests\\flow\\nodes\\MachineWashNodeTest::testCanHandleAfterEnd":7,"tests\\flow\\nodes\\MachineWashNodeTest::testCanHandleAfterEndoscopeOut":8,"tests\\flow\\nodes\\MachineWashNodeTest::testCannotHandleNonMachineWashReader":8,"tests\\flow\\nodes\\MachineWashNodeTest::testCannotHandleAfterFinalRinse":8,"tests\\flow\\nodes\\MachineWashNodeTest::testCannotHandleAfterDry":8,"tests\\flow\\nodes\\MachineWashNodeTest::testHandleProcess":8,"tests\\flow\\nodes\\MachineWashNodeTest::testDatabaseOperationFlags":7,"tests\\flow\\nodes\\MachineWashNodeTest::testWebSocketNotifyFlag":8,"tests\\flow\\nodes\\RinseNodeTest::testNodeIdentity":8,"tests\\flow\\nodes\\RinseNodeTest::testCanHandleAfterWash":7,"tests\\flow\\nodes\\RinseNodeTest::testCannotHandleNonRinseReader":8,"tests\\flow\\nodes\\RinseNodeTest::testCannotHandleAfterDisinfect":7,"tests\\flow\\nodes\\RinseNodeTest::testCannotHandleWithEmptyStep":7,"tests\\flow\\nodes\\RinseNodeTest::testCannotHandleAfterRinse":7,"tests\\flow\\nodes\\RinseNodeTest::testHandleProcess":7,"tests\\flow\\nodes\\RinseNodeTest::testDatabaseOperationFlags":7,"tests\\flow\\nodes\\RinseNodeTest::testWebSocketNotifyFlag":7,"tests\\flow\\nodes\\RinseNodeTest::testDisabledNodeSkips":8,"tests\\flow\\nodes\\WashNodeTest::testNodeIdentity":8,"tests\\flow\\nodes\\WashNodeTest::testCanHandleWashReader":8,"tests\\flow\\nodes\\WashNodeTest::testCannotHandleNonWashReader":8,"tests\\flow\\nodes\\WashNodeTest::testCanStartNewWashProcess":8,"tests\\flow\\nodes\\WashNodeTest::testCannotWashWithoutMorningWash":8,"tests\\flow\\nodes\\WashNodeTest::testHandleProcess":8,"tests\\flow\\nodes\\WashNodeTest::testGenerateBatchNo":7,"tests\\flow\\nodes\\WashNodeTest::testKeepExistingBatchNo":8,"tests\\flow\\strategies\\TimeValidationStrategyTest::testTimeRequirementNotMet":7,"tests\\flow\\strategies\\TimeValidationStrategyTest::testSetStepDuration":7,"tests\\flow\\FlowProcessorTest::testSuccessfulFlowSavesToDatabase":8,"tests\\flow\\FlowProcessorTest::testEndOperationIsUpdate":8,"tests\\flow\\FlowProcessorTest::testGetActionTypeMapping":8,"tests\\flow\\EdgeCaseTest::testLongEndoscopeName":7,"tests\\flow\\EdgeCaseTest::testSpecialCharactersInName":7,"tests\\flow\\ProcessContextTest::testGetFullVoice":7,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testFullVoiceIncludesEndoscopeName":7,"tests\\flow\\FlowProcessorTest::testSuccessfulFlowSendsVoice":8,"tests\\flow\\FlowProcessorTest::testFailedFlowDoesNotSaveToDatabase":8,"tests\\flow\\FlowProcessorTest::testFailedFlowStillSendsVoice":8,"tests\\flow\\FlowProcessorTest::testWebSocketNotificationSentWhenNeeded":8,"tests\\flow\\FlowProcessorTest::testWebSocketNotificationNotSentWhenNotNeeded":8,"tests\\flow\\FlowProcessorTest::testStaticFactoryCreate":8,"tests\\flow\\EdgeCaseTest::testAllNodesDisabled":8,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testFinalRinseVoice":8,"tests\\flow\\ProcessSimulationTest::testDuplicateCheckNode":7,"tests\\flow\\FullProcessTest::testCompleteManualWashProcess":7,"tests\\flow\\FullProcessTest::testSwipeEndoscopeWithoutOperator":7,"tests\\flow\\cases\\BlockTest::testProcessChainExecution":5,"tests\\flow\\cases\\BlockTest::testDisabledNodeSkipped":5,"tests\\flow\\cases\\BlockTest::testTimeValidationBlockWithBlockModeOn":5,"tests\\flow\\cases\\BlockTest::testTimeValidationWithBlockModeOff":5,"tests\\flow\\cases\\BlockTest::testDuplicateSwipeBlock":5,"tests\\flow\\cases\\BlockTest::testTimeValidationPass":5,"tests\\flow\\cases\\ManualWashTest::testCompleteManualWashProcess":8},"times":{"tests\\flow\\FlowProcessorTest::testCreateProcessor":0.006,"tests\\flow\\FlowProcessorTest::testCreateProcessorWithConfig":0.006,"tests\\flow\\FlowProcessorTest::testStaticFactory":0.006,"tests\\flow\\FlowProcessorTest::testUpdateConfig":0.009,"tests\\flow\\FlowProcessorTest::testBatchNoConsistency":0.006,"tests\\flow\\FlowProcessorTest::testBatchNoConsistencyInCompleteProcess":0.008,"tests\\flow\\FlowProcessorTest::testDatabaseOperationFlags":0.006,"tests\\flow\\FlowProcessorTest::testWebSocketNotifyFlag":0.005,"tests\\flow\\FlowProcessorTest::testVoiceGeneration":0.007,"tests\\flow\\FlowProcessorTest::testErrorVoiceGeneration":0.006,"tests\\flow\\FlowProcessorTest::testMultiHospitalConfig":0.007,"tests\\flow\\FlowProcessorTest::testSpecialHospitalConfig":0.006,"tests\\flow\\ProcessContextTest::testCreateContext":0.005,"tests\\flow\\ProcessContextTest::testSetError":0.006,"tests\\flow\\ProcessContextTest::testSetVoice":0.006,"tests\\flow\\ProcessContextTest::testGetFullVoice":0.006,"tests\\flow\\ProcessContextTest::testStepTimeManagement":0.006,"tests\\flow\\ProcessContextTest::testStepDurationManagement":0.005,"tests\\flow\\ProcessContextTest::testDefaultStepDuration":0.007,"tests\\flow\\ProcessContextTest::testGenerateBatchNo":0.006,"tests\\flow\\ProcessContextTest::testBatchNoUniqueness":0.006,"tests\\flow\\ProcessContextTest::testCanStartNewProcess":0.006,"tests\\flow\\ProcessContextTest::testIsWashProcessCompleted":0.006,"tests\\flow\\ProcessContextTest::testChaining":0.005,"tests\\flow\\ProcessEngineTest::testCreateStandardEngine":0.006,"tests\\flow\\ProcessEngineTest::testCreateNoMorningWashEngine":0.006,"tests\\flow\\ProcessEngineTest::testCreateSimpleEngine":0.006,"tests\\flow\\ProcessEngineTest::testCompleteWashProcess":0.045,"tests\\flow\\ProcessEngineTest::testTimeValidationFailure":0.005,"tests\\flow\\ProcessEngineTest::testWrongStep":0.01,"tests\\flow\\ProcessEngineTest::testDisableNode":0.005,"tests\\flow\\ProcessEngineTest::testGetNodes":0.006,"tests\\flow\\ProcessEngineTest::testGetEnabledNodes":0.005,"tests\\flow\\ProcessEngineTest::testUpdateConfig":0.006,"tests\\flow\\ProcessEngineTest::testMachineWashProcess":0.033,"tests\\flow\\nodes\\FinalRinseNodeTest::testCanHandleAfterDisinfect":0.007,"tests\\flow\\nodes\\FinalRinseNodeTest::testCanHandleAfterMachineWashByDefault":0.005,"tests\\flow\\nodes\\FinalRinseNodeTest::testCannotHandleAfterMachineWashWhenDisabled":0.008,"tests\\flow\\nodes\\FinalRinseNodeTest::testCannotHandleNonFinalRinseReader":0.008,"tests\\flow\\nodes\\FinalRinseNodeTest::testHandleProcess":0.01,"tests\\flow\\nodes\\WashNodeTest::testNodeIdentity":0.006,"tests\\flow\\nodes\\WashNodeTest::testCanHandleWashReader":0.006,"tests\\flow\\nodes\\WashNodeTest::testCannotHandleNonWashReader":0.005,"tests\\flow\\nodes\\WashNodeTest::testCanStartNewWashProcess":0.005,"tests\\flow\\nodes\\WashNodeTest::testCannotWashWithoutMorningWash":0.006,"tests\\flow\\nodes\\WashNodeTest::testHandleProcess":0.009,"tests\\flow\\nodes\\WashNodeTest::testGenerateBatchNo":0.008,"tests\\flow\\nodes\\WashNodeTest::testKeepExistingBatchNo":0.006,"tests\\flow\\strategies\\MorningWashStrategyTest::testNoneMode":0.006,"tests\\flow\\strategies\\MorningWashStrategyTest::testAllMode":0.005,"tests\\flow\\strategies\\MorningWashStrategyTest::testDailyFirstModeWithNoRecords":0.005,"tests\\flow\\strategies\\MorningWashStrategyTest::testDailyFirstModeWithRecords":0.006,"tests\\flow\\strategies\\MorningWashStrategyTest::testSpecificTypesMode":0.005,"tests\\flow\\strategies\\MorningWashStrategyTest::testStorageTimeMode":0.006,"tests\\flow\\strategies\\MorningWashStrategyTest::testStrategyName":0.005,"tests\\flow\\strategies\\TimeValidationStrategyTest::testNoTimeLimitForFirstTime":0.005,"tests\\flow\\strategies\\TimeValidationStrategyTest::testTimeRequirementMet":0.006,"tests\\flow\\strategies\\TimeValidationStrategyTest::testTimeRequirementNotMet":0.005,"tests\\flow\\strategies\\TimeValidationStrategyTest::testCustomDuration":0.006,"tests\\flow\\strategies\\TimeValidationStrategyTest::testIsApplicable":0.006,"tests\\flow\\strategies\\TimeValidationStrategyTest::testStrategyName":0.006,"tests\\flow\\strategies\\TimeValidationStrategyTest::testStrategyPhase":0.005,"tests\\flow\\ProcessEngineTest::testSkipStep":0.012,"tests\\flow\\ProcessEngineTest::testDisinfectAfterWash":0.005,"tests\\flow\\BatchConsistencyTest::testSingleMachineBatchConsistency":0.046,"tests\\flow\\BatchConsistencyTest::testMultiEndoscopeBatchUniqueness":0.036,"tests\\flow\\BatchConsistencyTest::testBatchNoFormat":0.008,"tests\\flow\\BatchConsistencyTest::testBatchNoStability":0.02,"tests\\flow\\BatchConsistencyTest::testNewProcessGeneratesNewBatchNo":0.024,"tests\\flow\\BatchConsistencyTest::testDistributedBatchConsistency":0.057,"tests\\flow\\BatchConsistencyTest::testBatchNoPreservedOnError":0.024,"tests\\flow\\BatchConsistencyTest::testBatchNoWithDifferentProcessTypes":0.022,"tests\\flow\\EdgeCaseTest::testEmptyContext":0.005,"tests\\flow\\EdgeCaseTest::testLongEndoscopeName":0.006,"tests\\flow\\EdgeCaseTest::testSpecialCharactersInName":0.006,"tests\\flow\\EdgeCaseTest::testBatchNoGenerationEdgeCases":0.006,"tests\\flow\\EdgeCaseTest::testTimeBoundaryValues":0.006,"tests\\flow\\EdgeCaseTest::testEmptyChain":0.005,"tests\\flow\\EdgeCaseTest::testAllNodesDisabled":0.021,"tests\\flow\\EdgeCaseTest::testRepeatedStepTimeSetting":0.006,"tests\\flow\\EdgeCaseTest::testChainingEdgeCases":0.006,"tests\\flow\\EdgeCaseTest::testErrorStateOverwrite":0.006,"tests\\flow\\EdgeCaseTest::testRecoveryFromError":0.005,"tests\\flow\\EdgeCaseTest::testInvalidConfigItems":0.007,"tests\\flow\\EdgeCaseTest::testConcurrentBatchNoGeneration":0.011,"tests\\flow\\EdgeCaseTest::testMorningWashBoundaryTime":0.006,"tests\\flow\\EdgeCaseTest::testStorageTimeBoundary":0.007,"tests\\flow\\EdgeCaseTest::testStorageTimeOverThreshold":0.005,"tests\\flow\\PerformanceTest::testSingleExecutionPerformance":0.011,"tests\\flow\\PerformanceTest::testCompleteProcessPerformance":0.039,"tests\\flow\\PerformanceTest::testBatchNoGenerationPerformance":0.023,"tests\\flow\\PerformanceTest::testEngineCreationPerformance":0.094,"tests\\flow\\PerformanceTest::testConfigLoadingPerformance":0.023,"tests\\flow\\PerformanceTest::testContextCreationPerformance":0.258,"tests\\flow\\PerformanceTest::testStrategyExecutionPerformance":0.156,"tests\\flow\\PerformanceTest::testMemoryUsage":0.226,"tests\\flow\\PerformanceTest::testConcurrentProcessingSimulation":0.058,"tests\\flow\\PerformanceTest::testChainTraversalPerformance":5.796,"tests\\flow\\config\\ProcessConfigTest::testCreateDefaultConfig":0.007,"tests\\flow\\config\\ProcessConfigTest::testFromArray":0.006,"tests\\flow\\config\\ProcessConfigTest::testGetEnabledSteps":0.007,"tests\\flow\\config\\ProcessConfigTest::testAddStep":0.006,"tests\\flow\\config\\ProcessConfigTest::testRemoveStep":0.005,"tests\\flow\\config\\ProcessConfigTest::testSetNodeEnabled":0.008,"tests\\flow\\config\\ProcessConfigTest::testMorningWashConfig":0.006,"tests\\flow\\config\\ProcessConfigTest::testTimeValidationConfig":0.007,"tests\\flow\\config\\ProcessConfigTest::testVoiceTemplateConfig":0.005,"tests\\flow\\config\\ProcessConfigTest::testSetStepVoice":0.006,"tests\\flow\\config\\ProcessConfigTest::testToArray":0.007,"tests\\flow\\config\\ProcessConfigTest::testCreateStandard":0.006,"tests\\flow\\config\\ProcessConfigTest::testCreateNoMorningWash":0.007,"tests\\flow\\config\\ProcessConfigTest::testCreateSimple":0.006,"tests\\flow\\config\\ProcessConfigTest::testCreateMachineWash":0.005,"tests\\flow\\config\\ProcessConfigTest::testCreateNoDry":0.006,"tests\\flow\\config\\ProcessConfigTest::testCreateDryOnly":0.005,"tests\\flow\\config\\ProcessConfigTest::testChaining":0.006,"tests\\flow\\nodes\\DisinfectNodeTest::testNodeIdentity":0.005,"tests\\flow\\nodes\\DisinfectNodeTest::testCanHandleAfterRinse":0.005,"tests\\flow\\nodes\\DisinfectNodeTest::testCanHandleAfterFinalRinse":0.005,"tests\\flow\\nodes\\DisinfectNodeTest::testCanHandleAfterWash":0.005,"tests\\flow\\nodes\\DisinfectNodeTest::testCannotHandleNonDisinfectReader":0.005,"tests\\flow\\nodes\\DisinfectNodeTest::testCannotHandleAfterDisinfect":0.005,"tests\\flow\\nodes\\DisinfectNodeTest::testHandleProcess":0.009,"tests\\flow\\nodes\\DisinfectNodeTest::testDatabaseOperationFlags":0.008,"tests\\flow\\nodes\\DisinfectNodeTest::testWebSocketNotifyFlag":0.008,"tests\\flow\\nodes\\MorningWashNodeTest::testNodeIdentity":0.005,"tests\\flow\\nodes\\MorningWashNodeTest::testCanHandleMorningWashReader":0.021,"tests\\flow\\nodes\\MorningWashNodeTest::testCannotHandleWhenNoNeed":0.006,"tests\\flow\\nodes\\MorningWashNodeTest::testCannotHandleNonMorningWashReader":0.005,"tests\\flow\\nodes\\MorningWashNodeTest::testCannotHandleWhenAlreadyWashed":0.005,"tests\\flow\\nodes\\MorningWashNodeTest::testHandleProcess":0.008,"tests\\flow\\nodes\\MorningWashNodeTest::testGenerateBatchNo":0.009,"tests\\flow\\nodes\\MorningWashNodeTest::testCanHandleDisinfectReaderForMorningWash":0.006,"tests\\flow\\nodes\\MorningWashNodeTest::testCanHandleMachineWashReaderForMorningWash":0.005,"tests\\flow\\nodes\\MorningWashNodeTest::testCannotHandleNonDisinfectMachineReader":0.006,"tests\\flow\\nodes\\MorningWashNodeTest::testHandleProcessWithDisinfect":0.009,"tests\\flow\\nodes\\MorningWashNodeTest::testHandleProcessWithMachineWash":0.009,"tests\\flow\\nodes\\DryNodeTest::testNodeIdentity":0.006,"tests\\flow\\nodes\\DryNodeTest::testCanHandleAfterFinalRinse":0.007,"tests\\flow\\nodes\\DryNodeTest::testCanHandleAfterDisinfect":0.006,"tests\\flow\\nodes\\DryNodeTest::testCannotHandleAfterRinse":0.005,"tests\\flow\\nodes\\DryNodeTest::testCannotHandleNonDryReader":0.007,"tests\\flow\\nodes\\DryNodeTest::testCannotHandleAfterDry":0.006,"tests\\flow\\nodes\\DryNodeTest::testHandleProcess":0.008,"tests\\flow\\nodes\\DryNodeTest::testDatabaseOperationFlags":0.009,"tests\\flow\\nodes\\DryNodeTest::testWebSocketNotifyFlag":0.008,"tests\\flow\\nodes\\DryNodeTest::testKeepExistingBatchNo":0.01,"tests\\flow\\ProcessEngineTest::testStandardWashRinseDisinfectFlow":0.023,"tests\\flow\\UsageExampleTest::testExample1StandardProcess":0.022,"tests\\flow\\UsageExampleTest::testExample2NoMorningWash":0.025,"tests\\flow\\UsageExampleTest::testExample3DynamicAdjust":0.048,"tests\\flow\\UsageExampleTest::testExample4CustomVoice":0.022,"tests\\flow\\UsageExampleTest::testExample5MorningWashModes":0.033,"tests\\flow\\UsageExampleTest::testExample6MachineWash":0.022,"tests\\flow\\UsageExampleTest::testExample7SimpleProcess":0.021,"tests\\flow\\UsageExampleTest::testExample8TimeValidation":0.021,"tests\\flow\\UsageExampleTest::testExample9FullProcess":0.021,"tests\\flow\\UsageExampleTest::testExample10MultiHospital":0.046,"tests\\flow\\UsageExampleTest::testLoadCustomProcessFromConfig":0.007,"tests\\flow\\UsageExampleTest::testCreateNoMorningWashFromConfig":0.042,"tests\\flow\\UsageExampleTest::testCreateMachineWashFromConfig":0.036,"tests\\flow\\UsageExampleTest::testCreateYiwuModeFromConfig":0.015,"tests\\flow\\UsageExampleTest::testFlowProcessorUsage":0.045,"tests\\flow\\UsageExampleTest::testFlowProcessorCompleteProcess":0.021,"tests\\flow\\UsageExampleTest::testFlowProcessorWithConfig":0.037,"tests\\db\\DBC::testDBConnect":0.113,"tests\\db\\DBC::testGenTables":0.416,"tests\\db\\DBC::testModel":0.171,"tests\\flow\\nodes\\EndNodeTest::testNodeIdentity":0.006,"tests\\flow\\nodes\\EndNodeTest::testCanHandleAfterDry":0.006,"tests\\flow\\nodes\\EndNodeTest::testCanHandleAfterDisinfect":0.005,"tests\\flow\\nodes\\EndNodeTest::testCanHandleAfterFinalRinse":0.005,"tests\\flow\\nodes\\EndNodeTest::testCanHandleAfterMachineWash":0.005,"tests\\flow\\nodes\\EndNodeTest::testCannotHandleNonEndReader":0.005,"tests\\flow\\nodes\\EndNodeTest::testCannotHandleAfterWash":0.007,"tests\\flow\\nodes\\EndNodeTest::testCannotHandleAfterRinse":0.006,"tests\\flow\\nodes\\EndNodeTest::testCannotHandleWithEmptyStep":0.005,"tests\\flow\\nodes\\EndNodeTest::testHandleProcess":0.009,"tests\\flow\\nodes\\EndNodeTest::testDatabaseOperationIsUpdate":0.011,"tests\\flow\\nodes\\EndNodeTest::testWebSocketNotifyFlag":0.009,"tests\\flow\\nodes\\EndNodeTest::testActionEndTimeIsSet":0.009,"tests\\flow\\nodes\\FinalRinseNodeTest::testCannotHandleAfterWash":0.006,"tests\\flow\\nodes\\FinalRinseNodeTest::testDatabaseOperationFlags":0.008,"tests\\flow\\nodes\\FinalRinseNodeTest::testWebSocketNotifyFlag":0.009,"tests\\flow\\nodes\\FinalRinseNodeTest::testNodeIdentity":0.005,"tests\\flow\\nodes\\MachineWashNodeTest::testNodeIdentity":0.005,"tests\\flow\\nodes\\MachineWashNodeTest::testCanHandleAfterWash":0.005,"tests\\flow\\nodes\\MachineWashNodeTest::testCanHandleAfterRinse":0.005,"tests\\flow\\nodes\\MachineWashNodeTest::testCanHandleAfterDisinfect":0.005,"tests\\flow\\nodes\\MachineWashNodeTest::testCanHandleWithEmptyStep":0.006,"tests\\flow\\nodes\\MachineWashNodeTest::testCanHandleAfterEnd":0.006,"tests\\flow\\nodes\\MachineWashNodeTest::testCanHandleAfterEndoscopeOut":0.005,"tests\\flow\\nodes\\MachineWashNodeTest::testCannotHandleNonMachineWashReader":0.005,"tests\\flow\\nodes\\MachineWashNodeTest::testCannotHandleAfterFinalRinse":0.005,"tests\\flow\\nodes\\MachineWashNodeTest::testCannotHandleAfterDry":0.006,"tests\\flow\\nodes\\MachineWashNodeTest::testHandleProcess":0.008,"tests\\flow\\nodes\\MachineWashNodeTest::testDatabaseOperationFlags":0.01,"tests\\flow\\nodes\\MachineWashNodeTest::testWebSocketNotifyFlag":0.008,"tests\\flow\\nodes\\RinseNodeTest::testNodeIdentity":0.005,"tests\\flow\\nodes\\RinseNodeTest::testCanHandleAfterWash":0.007,"tests\\flow\\nodes\\RinseNodeTest::testCannotHandleNonRinseReader":0.007,"tests\\flow\\nodes\\RinseNodeTest::testCannotHandleAfterDisinfect":0.006,"tests\\flow\\nodes\\RinseNodeTest::testCannotHandleWithEmptyStep":0.006,"tests\\flow\\nodes\\RinseNodeTest::testCannotHandleAfterRinse":0.005,"tests\\flow\\nodes\\RinseNodeTest::testHandleProcess":0.01,"tests\\flow\\nodes\\RinseNodeTest::testDatabaseOperationFlags":0.009,"tests\\flow\\nodes\\RinseNodeTest::testWebSocketNotifyFlag":0.009,"tests\\flow\\nodes\\RinseNodeTest::testDisabledNodeSkips":0.009,"tests\\flow\\strategies\\TimeValidationStrategyTest::testNonDurationStepIsSkipped":0.008,"tests\\flow\\strategies\\TimeValidationStrategyTest::testSetStepDuration":0.006,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testStrategyName":0.007,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testStrategyPhaseIsAfter":0.006,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testIsAlwaysApplicable":0.007,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testNormalWashVoice":0.005,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testNormalRinseVoice":0.005,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testNormalDisinfectVoice":0.005,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testFinalRinseVoice":0.006,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testDryVoice":0.006,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testEndVoice":0.005,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testMachineWashVoice":0.007,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testMorningWashVoice":0.005,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testMachineMorningWashVoice":0.006,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testErrorStateGeneratesErrorVoice":0.006,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testFullVoiceIncludesEndoscopeName":0.006,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testLeakTestRemindAppended":0.006,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testStorageRemindAppended":0.005,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testCustomVoiceTemplate":0.005,"tests\\flow\\strategies\\VoiceGenerationStrategyTest::testSetStepVoice":0.005,"tests\\flow\\FlowProcessorTest::testSuccessfulFlowSavesToDatabase":0.011,"tests\\flow\\FlowProcessorTest::testSuccessfulFlowSendsVoice":0.008,"tests\\flow\\FlowProcessorTest::testFailedFlowDoesNotSaveToDatabase":0.007,"tests\\flow\\FlowProcessorTest::testFailedFlowStillSendsVoice":0.008,"tests\\flow\\FlowProcessorTest::testWebSocketNotificationSentWhenNeeded":0.01,"tests\\flow\\FlowProcessorTest::testWebSocketNotificationNotSentWhenNotNeeded":0.008,"tests\\flow\\FlowProcessorTest::testEndOperationIsUpdate":0.01,"tests\\flow\\FlowProcessorTest::testGetActionTypeMapping":0.107,"tests\\flow\\FlowProcessorTest::testStaticFactoryCreate":0.007,"tests\\flow\\ProcessSimulationTest::testBasicManualWashWithoutDatabase":0.287,"tests\\flow\\ProcessSimulationTest::testNodeChainConstruction":0.264,"tests\\flow\\ProcessSimulationTest::testMorningWashNodeConfiguration":0.278,"tests\\flow\\ProcessSimulationTest::testMachineWashNodeConfiguration":0.271,"tests\\flow\\ProcessSimulationTest::testStorageNodeConfiguration":0.273,"tests\\flow\\ProcessSimulationTest::testDuplicateCheckNode":0.522,"tests\\flow\\ProcessSimulationTest::testCloseNode":0.268,"tests\\flow\\ProcessSimulationTest::testNodeEnableDisable":0.268,"tests\\flow\\ProcessSimulationTest::testConfigUpdate":0.522,"tests\\flow\\ProcessSimulationTest::testStrategyInitialization":0.291,"tests\\flow\\FullProcessTest::testCompleteManualWashProcess":0.09,"tests\\flow\\FullProcessTest::testCompleteManualWashProcessUsingHelper":0.285,"tests\\flow\\FullProcessTest::testMorningWashRequired":0.262,"tests\\flow\\FullProcessTest::testManualWashAfterMorningWash":0.269,"tests\\flow\\FullProcessTest::testMachineWashProcess":0.281,"tests\\flow\\FullProcessTest::testMachineWashProcessUsingHelper":0.286,"tests\\flow\\FullProcessTest::testMorningWashThenMachineWash":0.275,"tests\\flow\\FullProcessTest::testSwipeEndoscopeWithoutOperator":0.02,"tests\\flow\\FullProcessTest::testWrongStepOrder":0.078,"tests\\flow\\FullProcessTest::testDuplicateSwipe":0.142,"tests\\flow\\FullProcessTest::testUnboundReader":0.273,"tests\\flow\\FullProcessTest::testUnboundEndoscope":0.323,"tests\\flow\\FullProcessTest::testDifferentOperatorContinueProcess":0.124,"tests\\flow\\FullProcessTest::testWashStepVoice":0.074,"tests\\flow\\FullProcessTest::testDisinfectStepVoice":0.182,"tests\\flow\\FullProcessTest::testOperatorCardVoice":0.02,"tests\\flow\\FullProcessTest::testErrorVoice":0.021,"tests\\flow\\FullProcessTest::testVoiceTemplateParams":0.077,"tests\\flow\\FullProcessTest::testProcessChainExecution":0.236,"tests\\flow\\FullProcessTest::testDisabledNodeSkipped":0.277,"tests\\flow\\FullProcessTest::testTimeValidationBlock":0.265,"tests\\flow\\FullProcessTest::testDuplicateSwipeBlock":0.201,"tests\\flow\\FullProcessTest::testNewProcessAfterComplete":0.331,"tests\\flow\\FullProcessTest::testConcurrentProcessIsolation":0.174,"tests\\flow\\FullProcessTest::testProcessorReset":0.081,"tests\\flow\\FullProcessTest::testVirtualContextBuilder":0.017,"tests\\flow\\FullProcessTest::testEnvironmentConfig":0.007,"tests\\flow\\Test::testExample":0.005,"tests\\flow\\cases\\BlockTest::testProcessChainExecution":0.239,"tests\\flow\\cases\\BlockTest::testDisabledNodeSkipped":0.288,"tests\\flow\\cases\\BlockTest::testTimeValidationBlockWithBlockModeOn":0.263,"tests\\flow\\cases\\BlockTest::testTimeValidationWithBlockModeOff":0.282,"tests\\flow\\cases\\BlockTest::testDuplicateSwipeBlock":0.193,"tests\\flow\\cases\\BlockTest::testTimeValidationPass":0.281,"tests\\flow\\cases\\ErrorFlowTest::testSwipeEndoscopeWithoutOperator":0.008,"tests\\flow\\cases\\ErrorFlowTest::testWrongStepOrder":0.069,"tests\\flow\\cases\\ErrorFlowTest::testDuplicateSwipe":0.109,"tests\\flow\\cases\\ErrorFlowTest::testUnboundReader":0.276,"tests\\flow\\cases\\ErrorFlowTest::testUnboundEndoscope":0.27,"tests\\flow\\cases\\HelperTest::testProcessorReset":0.063,"tests\\flow\\cases\\HelperTest::testVirtualContextBuilder":0.007,"tests\\flow\\cases\\HelperTest::testEnvironmentConfig":0.006,"tests\\flow\\cases\\MachineWashTest::testMachineWashProcess":0.06,"tests\\flow\\cases\\MachineWashTest::testMachineWashProcessUsingHelper":0.06,"tests\\flow\\cases\\MachineWashTest::testMorningWashThenMachineWash":0.059,"tests\\flow\\cases\\MachineWashTest::testMultipleEndoscopeMachineWash":0.112,"tests\\flow\\cases\\ManualWashTest::testCompleteManualWashProcess":0.031,"tests\\flow\\cases\\ManualWashTest::testCompleteManualWashProcessUsingHelper":0.436,"tests\\flow\\cases\\ManualWashTest::testMorningWashRequired":0.316,"tests\\flow\\cases\\ManualWashTest::testManualWashAfterMorningWash":0.403,"tests\\flow\\cases\\ManualWashTest::testDifferentOperatorContinueProcess":0.138,"tests\\flow\\cases\\ManualWashTest::testNewProcessAfterComplete":0.443,"tests\\flow\\cases\\ManualWashTest::testConcurrentProcessIsolation":0.201,"tests\\flow\\cases\\VoiceTest::testWashStepVoice":0.064,"tests\\flow\\cases\\VoiceTest::testDisinfectStepVoice":0.2,"tests\\flow\\cases\\VoiceTest::testOperatorCardVoice":0.008,"tests\\flow\\cases\\VoiceTest::testErrorVoice":0.008,"tests\\flow\\cases\\VoiceTest::testWashDurationInsufficientVoice":0.276}} \ No newline at end of file diff --git a/app/config/TODO.md b/app/config/TODO.md index 193c76c..3e7d71a 100644 --- a/app/config/TODO.md +++ b/app/config/TODO.md @@ -2,4 +2,6 @@ 内镜未刷取出就操作 -刷两次代表加强洗 \ No newline at end of file +刷两次代表加强洗 + +网关阻断 \ No newline at end of file diff --git a/app/flow/FlowMain.php b/app/flow/FlowMain.php index 915fcea..af57654 100644 --- a/app/flow/FlowMain.php +++ b/app/flow/FlowMain.php @@ -4,6 +4,7 @@ namespace app\flow; use app\config\Config; use app\flow\config\ProcessConfig; +use app\flow\context\ProcessContext; use app\net\PacketContext; use app\utils\Logger; diff --git a/app/flow/FlowProcessor.php b/app/flow/FlowProcessor.php index 9824f64..d50b774 100644 --- a/app/flow/FlowProcessor.php +++ b/app/flow/FlowProcessor.php @@ -94,7 +94,7 @@ class FlowProcessor if ($mgr->hasOperator($context->getReader()->id) || $context->hasOperator()) { if ($mgr->hasOperator($context->getReader()->id)) { $op = $mgr->getOperator($context->getReader()->id, $context->getReader()->type); - $context = $context->builder()->withOperator(new \app\flow\vo\OperatorInfo( + $context = $context->builder()->withOperator(new \app\flow\context\bean\OperatorInfo( id: $op['id'], name: $op['name'], rfid: $op['rfid'] diff --git a/app/flow/OperatorSessionManager.php b/app/flow/OperatorSessionManager.php index 42f36b8..d08f14c 100644 --- a/app/flow/OperatorSessionManager.php +++ b/app/flow/OperatorSessionManager.php @@ -103,7 +103,13 @@ class OperatorSessionManager */ public function hasOperator(string $readerId): bool { - return isset($this->sessions[$readerId]); + $cache = $this->sessions[$readerId] ?? null; + if (empty($cache)) return false; + // 如果时间过去了,返回没有 + if ($this->expire > 0 && isset($cache['time']) && (time() - $cache['time']) > $this->expire) { + return false; + } + return true; } /** @@ -124,7 +130,7 @@ class OperatorSessionManager public function pop(string $readerId): ?array { - $op = $this->getOperator($readerId); + $op = $this->sessions[$readerId] ?? null; $this->clearOperator($readerId); return $op; } diff --git a/app/flow/context/ProcessContext.php b/app/flow/context/ProcessContext.php index 18eeb23..0936685 100644 --- a/app/flow/context/ProcessContext.php +++ b/app/flow/context/ProcessContext.php @@ -3,15 +3,16 @@ namespace app\flow\context; use app\flow\config\ProcessConfig; -use app\flow\vo\EndoscopeInfo; -use app\flow\vo\ExecutionResult; -use app\flow\vo\MorningWashStatus; -use app\flow\vo\OperatorInfo; -use app\flow\vo\ProcessStatus; -use app\flow\vo\ReaderInfo; -use app\flow\vo\ReminderStatus; -use app\flow\vo\StorageStatus; -use app\flow\vo\VoiceState; +use app\flow\context\bean\EndoscopeInfo; +use app\flow\context\bean\ExecutionResult; +use app\flow\context\bean\MorningWashStatus; +use app\flow\context\bean\OperatorInfo; +use app\flow\context\bean\ProcessStatus; +use app\flow\context\bean\ReaderInfo; +use app\flow\context\bean\ReminderStatus; +use app\flow\context\bean\StorageStatus; +use app\flow\context\bean\VoiceState; +use app\model\EctActions; use app\net\PacketContext; /** @@ -206,9 +207,9 @@ readonly class ProcessContext /** * 获取上一个操作记录 - * @return \app\model\EctActions|null 上一个操作记录 (来源: ProcessStatus) + * @return EctActions|null 上一个操作记录 (来源: ProcessStatus) */ - public function getPreviousAction(): ?\app\model\EctActions + public function getPreviousAction(): ?EctActions { return $this->processStatus->previousAction; } diff --git a/app/flow/context/ProcessContextBuilder.php b/app/flow/context/ProcessContextBuilder.php index 6795565..4d66ca2 100644 --- a/app/flow/context/ProcessContextBuilder.php +++ b/app/flow/context/ProcessContextBuilder.php @@ -4,18 +4,18 @@ namespace app\flow\context; use app\config\Config; use app\flow\config\ProcessConfig; -use app\flow\vo\EndoscopeInfo; -use app\flow\vo\ExecutionResult; -use app\flow\vo\MorningWashStatus; -use app\flow\vo\OperatorInfo; -use app\flow\vo\ProcessStatus; -use app\flow\vo\ReaderInfo; -use app\flow\vo\ReminderStatus; -use app\flow\vo\StorageStatus; -use app\flow\vo\VoiceState; +use app\flow\context\bean\EndoscopeInfo; +use app\flow\context\bean\ExecutionResult; +use app\flow\context\bean\MorningWashStatus; +use app\flow\context\bean\OperatorInfo; +use app\flow\context\bean\ProcessStatus; +use app\flow\context\bean\ReaderInfo; +use app\flow\context\bean\ReminderStatus; +use app\flow\context\bean\StorageStatus; +use app\flow\context\bean\VoiceState; use app\flow\enum\DbOperationType; use app\flow\enum\VoiceMessage; -use app\flow\vo\BatchNo; +use app\flow\context\bean\BatchNo; use app\model\EctActions; use app\net\PacketContext; use app\repository\EctActionsRepository; @@ -79,6 +79,7 @@ class ProcessContextBuilder $builder = new self(); $builder->packetContext = $packetContext; $builder->engineConfig = $additionalData['engineConfig'] ?? null; + if (empty($builder->engineConfig)) Logger::warn("fromPacketContext 需要通过 additionalData 传递 engineConfig"); // 获取原始卡号和读卡器编号 $cardNo = $packetContext->packet->card ?? ''; @@ -228,6 +229,7 @@ class ProcessContextBuilder // 查询今日洗消记录数(晨洗判断) $todayWashRecords = $actionsRepo->countTodayActions($this->endoscope->id, $this->morningStartTime, [0, 7, 8]); + Logger::debug("{} 内镜今日洗消记录数: {}", [$this->endoscope->name,$todayWashRecords]); $this->morningWash = new MorningWashStatus( needMorningWash: $this->morningWash->needMorningWash, morningWashed: $this->morningWash->morningWashed, diff --git a/app/flow/vo/BatchNo.php b/app/flow/context/bean/BatchNo.php similarity index 83% rename from app/flow/vo/BatchNo.php rename to app/flow/context/bean/BatchNo.php index b4161b6..9ba2e21 100644 --- a/app/flow/vo/BatchNo.php +++ b/app/flow/context/bean/BatchNo.php @@ -1,6 +1,6 @@ isValid()) { + throw new \InvalidArgumentException('Invalid batch string: ' . $batchNo); + } + return $batch->parse(); + } + /** * 验证批次号格式是否有效 */ @@ -123,12 +139,23 @@ readonly class BatchNo /** * 获取日期部分 */ - public function getDate(): string + public function getDateStr(): string { $parsed = $this->parse(); return $parsed['dateFormatted']; } + + /** + * 获取时间戳 + * @return int|false + */ + public function getTimestamp(): int|false + { + $parsed = $this->parse(); + return strtotime($parsed['dateFormatted']); + } + /** * 获取机器ID */ diff --git a/app/flow/vo/CanHandleResult.php b/app/flow/context/bean/CanHandleResult.php similarity index 86% rename from app/flow/vo/CanHandleResult.php rename to app/flow/context/bean/CanHandleResult.php index 521af31..2d0db8e 100644 --- a/app/flow/vo/CanHandleResult.php +++ b/app/flow/context/bean/CanHandleResult.php @@ -1,6 +1,6 @@ getCurrentStep() === $this->getCode()) { - return CanHandleResult::yes(); + return CanHandleResult::canHandle(); } - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } /** diff --git a/app/flow/nodes/CloseNode.php b/app/flow/nodes/CloseNode.php index 8b8f2cd..0f57aa1 100644 --- a/app/flow/nodes/CloseNode.php +++ b/app/flow/nodes/CloseNode.php @@ -5,7 +5,7 @@ namespace app\flow\nodes; use app\flow\enum\DbOperationType; use app\flow\context\ProcessContext; use app\flow\enum\VoiceMessage; -use app\flow\vo\CanHandleResult; +use app\flow\context\bean\CanHandleResult; use app\repository\EctActionsRepository; use app\utils\Logger; @@ -39,9 +39,9 @@ class CloseNode extends AbstractProcessNode public function canHandle(ProcessContext $context): CanHandleResult { if (!$context->isSuccess() || $context->isDatabaseOperationNeeded() || !empty($context->getVoice()->message)) { - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } - return CanHandleResult::yes(); + return CanHandleResult::canHandle(); } /** diff --git a/app/flow/nodes/DisinfectNode.php b/app/flow/nodes/DisinfectNode.php index 095546a..e0c5791 100644 --- a/app/flow/nodes/DisinfectNode.php +++ b/app/flow/nodes/DisinfectNode.php @@ -5,7 +5,7 @@ namespace app\flow\nodes; use app\flow\enum\DbOperationType; use app\flow\context\ProcessContext; use app\flow\enum\VoiceMessage; -use app\flow\vo\CanHandleResult; +use app\flow\context\bean\CanHandleResult; /** * 消毒节点 @@ -36,22 +36,22 @@ class DisinfectNode extends AbstractProcessNode { // 如果内镜未取出 if ($context->getStorage()->isInStorage) { - return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT); + return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT); } if (!$this->isMatchReaderType($context)) { if ($context->getCurrentStep() === RinseNode::getName()) { - return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_DISINFECT); + return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_DISINFECT); } - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } // 上一个步骤必须是漂洗 或者 晨洗 if (!$this->isRequiredNode($context->getCurrentStep(), [RinseNode::getName(), MorningWashNode::getName()])) { - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } - return CanHandleResult::yes(); + return CanHandleResult::canHandle(); } /** diff --git a/app/flow/nodes/DryNode.php b/app/flow/nodes/DryNode.php index 87044c0..988eb0a 100644 --- a/app/flow/nodes/DryNode.php +++ b/app/flow/nodes/DryNode.php @@ -5,7 +5,7 @@ namespace app\flow\nodes; use app\flow\enum\DbOperationType; use app\flow\context\ProcessContext; use app\flow\enum\VoiceMessage; -use app\flow\vo\CanHandleResult; +use app\flow\context\bean\CanHandleResult; use app\utils\Logger; /** @@ -40,23 +40,23 @@ class DryNode extends AbstractProcessNode { // 如果内镜未取出 if ($context->getStorage()->isInStorage) { - return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT); + return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT); } if (!$this->isMatchReaderType($context)) { if ($context->getCurrentStep() === FinalRinseNode::getName()) { if (!$context->isSuccess()) Logger::debug("[DryNode] 刷卡错误,当前步骤是终末漂洗,但是刷的读卡器类型不是终末漂洗,对用户进行语音提示刷终末漂洗读卡器"); - return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_DRY); + return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_DRY); } - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } // 上一个步骤必须是终末漂洗 if (!$this->isRequiredNode($context->getCurrentStep(), [FinalRinseNode::getName()])) { - return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_DISINFECT); + return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_DISINFECT); } - return CanHandleResult::yes(); + return CanHandleResult::canHandle(); } /** diff --git a/app/flow/nodes/DuplicateCheckNode.php b/app/flow/nodes/DuplicateCheckNode.php index ad4c23a..4db2ae1 100644 --- a/app/flow/nodes/DuplicateCheckNode.php +++ b/app/flow/nodes/DuplicateCheckNode.php @@ -5,7 +5,7 @@ namespace app\flow\nodes; use app\flow\enum\DbOperationType; use app\flow\context\ProcessContext; use app\flow\enum\VoiceMessage; -use app\flow\vo\CanHandleResult; +use app\flow\context\bean\CanHandleResult; use app\repository\EctActionsRepository; use app\utils\Logger; @@ -40,9 +40,9 @@ class DuplicateCheckNode extends AbstractProcessNode public function canHandle(ProcessContext $context): CanHandleResult { if ($context->getPreviousAction()?->process_name === $context->getReader()->type) { - return CanHandleResult::yes(); + return CanHandleResult::canHandle(); } - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } /** diff --git a/app/flow/nodes/EndNode.php b/app/flow/nodes/EndNode.php index c0ef3ed..150a97c 100644 --- a/app/flow/nodes/EndNode.php +++ b/app/flow/nodes/EndNode.php @@ -5,7 +5,7 @@ namespace app\flow\nodes; use app\flow\enum\DbOperationType; use app\flow\context\ProcessContext; use app\flow\enum\VoiceMessage; -use app\flow\vo\CanHandleResult; +use app\flow\context\bean\CanHandleResult; /** * 结束节点 @@ -36,26 +36,25 @@ class EndNode extends AbstractProcessNode { // 如果内镜未取出 if ($context->getStorage()->isInStorage) { - return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT); + return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT); } if (!$this->isMatchReaderType($context)) { - if ($context->getCurrentStep() === DryNode::getName() && $context->getCurrentStep() === FinalRinseNode::getName()) { - return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_END); + if ($context->getCurrentStep() === DryNode::getName() || $context->getCurrentStep() === FinalRinseNode::getName()) { + return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_END); } - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } // 上一个步骤必须是干燥、终末漂洗或机洗 - $validSteps = ['干燥', '终末漂洗', '机洗']; - if ($this->isRequiredNode($context->getCurrentStep(), ['干燥', '终末漂洗', '机洗'])) { + if (!$this->isRequiredNode($context->getCurrentStep(), ['干燥', '终末漂洗', '机洗'])) { if ($context->getCurrentStep() === FinalRinseNode::getName()) { - return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_WASH); + return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_WASH); } - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } - return CanHandleResult::yes(); + return CanHandleResult::canHandle(); } /** diff --git a/app/flow/nodes/FinalRinseNode.php b/app/flow/nodes/FinalRinseNode.php index d250e00..281dff7 100644 --- a/app/flow/nodes/FinalRinseNode.php +++ b/app/flow/nodes/FinalRinseNode.php @@ -5,7 +5,7 @@ namespace app\flow\nodes; use app\flow\enum\DbOperationType; use app\flow\context\ProcessContext; use app\flow\enum\VoiceMessage; -use app\flow\vo\CanHandleResult; +use app\flow\context\bean\CanHandleResult; use app\utils\Logger; /** @@ -39,22 +39,22 @@ class FinalRinseNode extends AbstractProcessNode { // 如果内镜未取出 if ($context->getStorage()->isInStorage) { - return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT); + return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT); } if (!$this->isMatchReaderType($context)) { if ($context->getCurrentStep() === DisinfectNode::getName()) { if (!$context->isSuccess()) Logger::debug("[FinalRinseNode] 刷卡错误,当前步骤是消毒,但是刷的读卡器类型不是消毒,对用户进行语音提示刷消毒读卡器"); - return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_FINAL_RINSE); + return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_FINAL_RINSE); } - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } // 上一个步骤必须是消毒或机洗 if ($this->isRequiredNode($context->getCurrentStep(), ['消毒', '机洗'])) { - return CanHandleResult::yes(); + return CanHandleResult::canHandle(); } - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } /** diff --git a/app/flow/nodes/MachineWashNode.php b/app/flow/nodes/MachineWashNode.php index c0bdf0a..bc48526 100644 --- a/app/flow/nodes/MachineWashNode.php +++ b/app/flow/nodes/MachineWashNode.php @@ -5,7 +5,7 @@ namespace app\flow\nodes; use app\flow\enum\DbOperationType; use app\flow\context\ProcessContext; use app\flow\enum\VoiceMessage; -use app\flow\vo\CanHandleResult; +use app\flow\context\bean\CanHandleResult; /** * 机洗节点 @@ -36,30 +36,30 @@ class MachineWashNode extends AbstractProcessNode { // 如果内镜未取出 if ($context->getStorage()->isInStorage) { - return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT); + return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT); } if (!$this->isMatchReaderType($context)) { if ($context->getCurrentStep() === WashNode::getName()) { - return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_MACHINE_WASH); + return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_MACHINE_WASH); } - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } // 需要晨洗但未完成:提示先进行晨洗 if ($context->getMorningWash()->needMorningWash && !$context->getMorningWash()->morningWashed) { - return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_MORNING_WASH); + return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_MORNING_WASH); } // 机洗可以在多个步骤后执行:空步骤(新流程)、结束、内镜取出、清洗,晨洗 if (!$this->isRequiredNode($context->getCurrentStep(), ['', '结束', '内镜取出', '清洗', MachineWashNode::getName()])) { if ($context->getCurrentStep() === EndNode::getName()) { - return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_MACHINE_WASH); + return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_MACHINE_WASH); } - return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_END); + return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_END); } - return CanHandleResult::yes(); + return CanHandleResult::canHandle(); } /** diff --git a/app/flow/nodes/MorningWashNode.php b/app/flow/nodes/MorningWashNode.php index 95efc2d..6076257 100644 --- a/app/flow/nodes/MorningWashNode.php +++ b/app/flow/nodes/MorningWashNode.php @@ -5,8 +5,8 @@ namespace app\flow\nodes; use app\flow\enum\DbOperationType; use app\flow\context\ProcessContext; use app\flow\enum\VoiceMessage; -use app\flow\vo\CanHandleResult; -use app\flow\vo\MorningWashStatus; +use app\flow\context\bean\CanHandleResult; +use app\flow\context\bean\MorningWashStatus; use app\utils\Logger; /** @@ -38,19 +38,19 @@ class MorningWashNode extends AbstractProcessNode { // 如果内镜未取出 if ($context->getStorage()->isInStorage) { - return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT); + return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT); } // 只有需要晨洗且未完成晨洗时才处理 if (!$context->getMorningWash()->needMorningWash || $context->getMorningWash()->morningWashed) { - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } // 检查当前读卡器类型是否匹配 if (!$this->isRequiredNode($context->getReader()->type, ['漂洗', '机洗'])){ - return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_MORNING_WASH); + return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_MORNING_WASH); } - return CanHandleResult::yes(); + return CanHandleResult::canHandle(); } /** diff --git a/app/flow/nodes/ProcessNodeInterface.php b/app/flow/nodes/ProcessNodeInterface.php index 4ee1ecf..39c394c 100644 --- a/app/flow/nodes/ProcessNodeInterface.php +++ b/app/flow/nodes/ProcessNodeInterface.php @@ -3,7 +3,7 @@ namespace app\flow\nodes; use app\flow\context\ProcessContext; -use app\flow\vo\CanHandleResult; +use app\flow\context\bean\CanHandleResult; /** * 流程节点接口 diff --git a/app/flow/nodes/RinseNode.php b/app/flow/nodes/RinseNode.php index 413c6d1..3955c81 100644 --- a/app/flow/nodes/RinseNode.php +++ b/app/flow/nodes/RinseNode.php @@ -5,7 +5,7 @@ namespace app\flow\nodes; use app\flow\enum\DbOperationType; use app\flow\context\ProcessContext; use app\flow\enum\VoiceMessage; -use app\flow\vo\CanHandleResult; +use app\flow\context\bean\CanHandleResult; /** * 漂洗节点 @@ -38,24 +38,24 @@ class RinseNode extends AbstractProcessNode { // 如果内镜未取出 if ($context->getStorage()->isInStorage) { - return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT); + return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT); } // 期望当前读卡器为漂洗 if (!$this->isMatchReaderType($context)) { // 当前步骤是清洗且读卡器不符:说明清洗完了应该刷漂洗 if ($context->getCurrentStep() === WashNode::getName()) { - return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_RINSE); + return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_RINSE); } - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } // 上一个步骤必须是清洗 if (!$this->isRequiredNode($context->getCurrentStep(), [WashNode::getName()])) { - return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_WASH); + return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_WASH); } - return CanHandleResult::yes(); + return CanHandleResult::canHandle(); } /** diff --git a/app/flow/nodes/StorageInNode.php b/app/flow/nodes/StorageInNode.php index 94f2801..e217409 100644 --- a/app/flow/nodes/StorageInNode.php +++ b/app/flow/nodes/StorageInNode.php @@ -6,8 +6,8 @@ use app\config\Config; use app\flow\enum\DbOperationType; use app\flow\context\ProcessContext; use app\flow\enum\VoiceMessage; -use app\flow\vo\CanHandleResult; -use app\flow\vo\StorageStatus; +use app\flow\context\bean\CanHandleResult; +use app\flow\context\bean\StorageStatus; use app\utils\Logger; /** @@ -44,12 +44,12 @@ class StorageInNode extends AbstractProcessNode // 单读卡器模式不处理,由 StorageNode 统一处理 if ($singleReaderMode) { - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } // 读卡器不是内镜放入类型,不处理 if (!$this->isMatchReaderType($context)) { - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } // 获取内镜当前存储状态 @@ -58,17 +58,17 @@ class StorageInNode extends AbstractProcessNode // 如果内镜已在库中,则当前应该是出库操作,不处理 if ($isInStorage) { Logger::debug('[StorageInNode] 内镜已在库中,转由出库节点处理'); - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } // 检查前置步骤要求 $validSteps = ['', '结束', '内镜取出', '测漏正常', '测漏异常']; if (!in_array($context->getCurrentStep(), $validSteps)) { Logger::debug('[StorageInNode] 当前步骤 {} 不符合入库条件', [$context->getCurrentStep()]); - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } - return CanHandleResult::yes(); + return CanHandleResult::canHandle(); } /** diff --git a/app/flow/nodes/StorageNode.php b/app/flow/nodes/StorageNode.php index 386877e..1a8a1a7 100644 --- a/app/flow/nodes/StorageNode.php +++ b/app/flow/nodes/StorageNode.php @@ -6,8 +6,8 @@ use app\config\Config; use app\flow\enum\DbOperationType; use app\flow\context\ProcessContext; use app\flow\enum\VoiceMessage; -use app\flow\vo\CanHandleResult; -use app\flow\vo\StorageStatus; +use app\flow\context\bean\CanHandleResult; +use app\flow\context\bean\StorageStatus; use app\utils\Logger; /** @@ -47,12 +47,12 @@ class StorageNode extends AbstractProcessNode // 非单读卡器模式不处理 if (!$singleReaderMode) { - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } // 读卡器类型必须是'内镜放入'或'内镜取出' if (!in_array($context->getReader()->type, ['内镜放入', '内镜取出'])) { - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } $isInStorage = $context->getStorage()->isInStorage; @@ -62,18 +62,18 @@ class StorageNode extends AbstractProcessNode $validSteps = ['内镜放入', '结束']; if (!in_array($context->getCurrentStep(), $validSteps)) { Logger::debug('[StorageNode] 当前步骤 {} 不符合出库条件', [$context->getCurrentStep()]); - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } } else { // 内镜不在库中,执行入库 $validSteps = ['', '结束', '内镜取出', '测漏正常', '测漏异常']; if (!in_array($context->getCurrentStep(), $validSteps)) { Logger::debug('[StorageNode] 当前步骤 {} 不符合入库条件', [$context->getCurrentStep()]); - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } } - return CanHandleResult::yes(); + return CanHandleResult::canHandle(); } /** diff --git a/app/flow/nodes/StorageOutNode.php b/app/flow/nodes/StorageOutNode.php index 203bd82..68183f0 100644 --- a/app/flow/nodes/StorageOutNode.php +++ b/app/flow/nodes/StorageOutNode.php @@ -6,8 +6,8 @@ use app\config\Config; use app\flow\enum\DbOperationType; use app\flow\context\ProcessContext; use app\flow\enum\VoiceMessage; -use app\flow\vo\CanHandleResult; -use app\flow\vo\StorageStatus; +use app\flow\context\bean\CanHandleResult; +use app\flow\context\bean\StorageStatus; use app\utils\Logger; /** @@ -44,12 +44,12 @@ class StorageOutNode extends AbstractProcessNode // 单读卡器模式不处理,由 StorageNode 统一处理 if ($singleReaderMode) { - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } // 读卡器不是内镜取出类型,不处理 if (!$this->isMatchReaderType($context)) { - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } // 获取内镜当前存储状态 @@ -58,17 +58,17 @@ class StorageOutNode extends AbstractProcessNode // 如果内镜不在库中,则当前应该是入库操作,不处理 if (!$isInStorage) { Logger::debug('[StorageOutNode] 内镜不在库中,转由入库节点处理'); - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } // 检查前置步骤要求:必须在库中才能出库 $validSteps = ['内镜放入', '结束']; if (!in_array($context->getCurrentStep(), $validSteps)) { Logger::debug('[StorageOutNode] 当前步骤 {} 不符合出库条件', [$context->getCurrentStep()]); - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } - return CanHandleResult::yes(); + return CanHandleResult::canHandle(); } /** diff --git a/app/flow/nodes/VirtualWashMachineNode.php b/app/flow/nodes/VirtualWashMachineNode.php index 95e1614..e87ce1b 100644 --- a/app/flow/nodes/VirtualWashMachineNode.php +++ b/app/flow/nodes/VirtualWashMachineNode.php @@ -6,7 +6,7 @@ use app\config\Config; use app\flow\enum\DbOperationType; use app\flow\context\ProcessContext; use app\flow\enum\VoiceMessage; -use app\flow\vo\CanHandleResult; +use app\flow\context\bean\CanHandleResult; /** * 虚拟清洗机节点 @@ -37,18 +37,18 @@ class VirtualWashMachineNode extends AbstractProcessNode { // 如果内镜未取出 if ($context->getStorage()->isInStorage) { - return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT); + return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT); } // 如果不是机洗 if ($context->getReader()->type !== MachineWashNode::getName()) { - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } if (Config::getInstance()->enableVirtualCleanerParser) { - return CanHandleResult::yes(); + return CanHandleResult::canHandle(); } - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } /** diff --git a/app/flow/nodes/WashNode.php b/app/flow/nodes/WashNode.php index d30fa5a..2c7e1b0 100644 --- a/app/flow/nodes/WashNode.php +++ b/app/flow/nodes/WashNode.php @@ -5,7 +5,7 @@ namespace app\flow\nodes; use app\flow\enum\DbOperationType; use app\flow\context\ProcessContext; use app\flow\enum\VoiceMessage; -use app\flow\vo\CanHandleResult; +use app\flow\context\bean\CanHandleResult; use app\utils\Logger; /** @@ -39,26 +39,28 @@ class WashNode extends AbstractProcessNode // 如果内镜未取出 if ($context->getStorage()->isInStorage) { - return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT); + return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT); } - // 读卡器不是本节点,不处理 - if (!$this->isMatchReaderType($context)) { - return CanHandleResult::no(); - } + // 需要晨洗但未完成:提示先进行晨洗 if ($context->getMorningWash()->needMorningWash && !$context->getMorningWash()->morningWashed) { - return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_MORNING_WASH); + return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_MORNING_WASH); } $validCurrentSteps = ['', '结束', '内镜取出', '内镜放入', '测漏正常', '晨洗']; if (!in_array($context->getCurrentStep(), $validCurrentSteps)) { // 读卡器是清洗但步骤不对(如终末漂洗时刷清洗),提示应该先刷结束 - return CanHandleResult::no(); + return CanHandleResult::cannotHandle(); } - return CanHandleResult::yes(); + // 读卡器不是本节点,不处理 + if (!$this->isMatchReaderType($context)) { + return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_WASH); + } + + return CanHandleResult::canHandle(); } /** diff --git a/app/flow/strategies/MorningWashStrategy.php b/app/flow/strategies/MorningWashStrategy.php index 3c5d2f6..2819875 100644 --- a/app/flow/strategies/MorningWashStrategy.php +++ b/app/flow/strategies/MorningWashStrategy.php @@ -6,7 +6,7 @@ use app\flow\config\MorningMode; use app\flow\config\MorningWashConfig; use app\flow\context\ProcessContext; use app\flow\nodes\ProcessNodeInterface; -use app\flow\vo\MorningWashStatus; +use app\flow\context\bean\MorningWashStatus; use app\utils\Logger; /** diff --git a/app/flow/strategies/TimeValidationStrategy.php b/app/flow/strategies/TimeValidationStrategy.php index faa9bf9..1bc2863 100644 --- a/app/flow/strategies/TimeValidationStrategy.php +++ b/app/flow/strategies/TimeValidationStrategy.php @@ -59,15 +59,16 @@ class TimeValidationStrategy extends AbstractStrategy /** * 执行时间验证 + * 验证上一步骤(currentStep)的时长是否达标 */ protected function doExecute(ProcessContext $context, ProcessNodeInterface $node): ProcessContext { - $stepCode = $node->getCode(); - $currentStep = $context->getCurrentStep(); + // 验证的是上一步骤(currentStep)的时长,而不是当前节点 + $stepCode = $context->getCurrentStep(); $processType = $context->getProcessType(); Logger::debug("开始执行时间验证策略,步骤:{$stepCode},流程类型:{$processType}"); - $configDuration = $this->timeValidationConfig->getDuration($stepCode,$processType); + $configDuration = $this->timeValidationConfig->getDuration($stepCode, $processType); Logger::debug("步骤:{$stepCode},流程类型:{$processType},配置时长:{$configDuration}s"); if ($configDuration > 0) { @@ -76,7 +77,7 @@ class TimeValidationStrategy extends AbstractStrategy } else { Logger::debug("步骤:{$stepCode},流程类型:{$processType},无配置时长,从数据库查询"); // 从数据库按流程类型精确查询 - $requiredDuration = $this->getDurationFromDb($stepCode, $context->getProcessType()); + $requiredDuration = $this->getDurationFromDb($stepCode, $processType); if ($requiredDuration > 0) { $context = $context->builder()->withStepDuration($stepCode, $requiredDuration)->build(); } else { @@ -116,11 +117,13 @@ class TimeValidationStrategy extends AbstractStrategy /** * 判断策略是否适用 * 只有在 timeValidationConfig 中登记的步骤才参与时间验证 + * 验证的是上一步骤(currentStep)的时长 */ public function isApplicable(ProcessContext $context, ProcessNodeInterface $node): bool { if ($context->getCurrentStep() != $context->getPreviousAction()?->process_name) return false; - if (!$this->timeValidationConfig->hasStep($node->getCode(), $context->getProcessType())) return false; + // 检查的是 currentStep(上一步骤)是否有时间配置 + if (!$this->timeValidationConfig->hasStep($context->getCurrentStep(), $context->getProcessType())) return false; return true; } diff --git a/app/repository/EctActionsRepository.php b/app/repository/EctActionsRepository.php index b11d6ae..c97efdc 100644 --- a/app/repository/EctActionsRepository.php +++ b/app/repository/EctActionsRepository.php @@ -2,6 +2,7 @@ namespace app\repository; +use app\flow\context\bean\BatchNo; use app\flow\context\ProcessContext; use app\flow\enum\DbOperationType; use app\model\EctActions; @@ -99,9 +100,9 @@ class EctActionsRepository extends BaseRepository $count = 0; $today = date('Ymd'); $query->lazy()->each(function (EctActions $record) use (&$count, $today) { - $batchInfo = ProcessContext::parseBatchNo($record->op_batchno); - $dateTime = strtotime($batchInfo['date']); - if (empty($batchInfo['date']) || $dateTime === false) return; + $batchInfo = BatchNo::fromString($record->op_batchno); + $dateTime = $batchInfo->getTimestamp(); + if (empty($batchInfo->getDateStr()) || $dateTime === false) return; $recordDate = date('Ymd', $dateTime); if ($recordDate >= $today) { $count += 1; diff --git a/tests/flow/VirtualContextBuilder.php b/tests/flow/VirtualContextBuilder.php index b66253a..af37f75 100644 --- a/tests/flow/VirtualContextBuilder.php +++ b/tests/flow/VirtualContextBuilder.php @@ -3,16 +3,16 @@ namespace tests\flow; use app\flow\config\ProcessConfig; +use app\flow\context\bean\EndoscopeInfo; +use app\flow\context\bean\ExecutionResult; +use app\flow\context\bean\MorningWashStatus; +use app\flow\context\bean\OperatorInfo; +use app\flow\context\bean\ProcessStatus; +use app\flow\context\bean\ReaderInfo; +use app\flow\context\bean\ReminderStatus; +use app\flow\context\bean\StorageStatus; +use app\flow\context\bean\VoiceState; use app\flow\context\ProcessContext; -use app\flow\vo\EndoscopeInfo; -use app\flow\vo\ExecutionResult; -use app\flow\vo\MorningWashStatus; -use app\flow\vo\OperatorInfo; -use app\flow\vo\ProcessStatus; -use app\flow\vo\ReaderInfo; -use app\flow\vo\ReminderStatus; -use app\flow\vo\StorageStatus; -use app\flow\vo\VoiceState; use app\model\EctActions; /** @@ -284,6 +284,7 @@ class VirtualContextBuilder $action->op_batchno = $batchNo ?: $this->processStatus->batchNo; $action->op_starttime = date('Y-m-d H:i:s', time() - 60); $action->op_endtime = $opEndtime; + $action->action_type = $this->mapActionType($this->processStatus->processType); $action->action_type_name = $this->processStatus->processType; $this->processStatus = new ProcessStatus( @@ -297,6 +298,23 @@ class VirtualContextBuilder return $this; } + /** + * 映射流程类型到 action_type 数字 + */ + private function mapActionType(string $processType): int + { + return match ($processType) { + '手工洗' => 1, + '机洗' => 2, + '手工洗(加强)' => 3, + '机洗(加强)' => 4, + '手工洗(晨洗)' => 5, + '机洗(晨洗)' => 6, + '晨洗' => 7, + default => 0, + }; + } + /** * 设置晨洗状态 - 需要晨洗 */ diff --git a/tests/flow/VirtualityFlowProcessor.php b/tests/flow/VirtualityFlowProcessor.php index 0352953..5327421 100644 --- a/tests/flow/VirtualityFlowProcessor.php +++ b/tests/flow/VirtualityFlowProcessor.php @@ -5,9 +5,9 @@ namespace tests\flow; use app\flow\config\ProcessConfig; use app\flow\context\ProcessContext; use app\flow\ProcessEngine; -use app\flow\vo\EndoscopeInfo; -use app\flow\vo\OperatorInfo; -use app\flow\vo\ReaderInfo; +use app\flow\context\bean\EndoscopeInfo; +use app\flow\context\bean\OperatorInfo; +use app\flow\context\bean\ReaderInfo; use app\utils\Logger; /** @@ -166,6 +166,11 @@ class VirtualityFlowProcessor $builder->currentStep($currentState->getCurrentStep()) ->batchNo($currentState->getBatchNo()) ->processType($currentState->getProcessType()); + + // 设置 previousAction:上一步骤名称就是当前状态的 currentStep + if (!empty($currentState->getCurrentStep())) { + $builder->previousAction($currentState->getCurrentStep(), $currentState->getBatchNo()); + } } else { // 新流程 $builder->newProcess(); @@ -185,6 +190,14 @@ class VirtualityFlowProcessor // 执行流程 $result = $this->engine->execute($context); + // 确保 previousAction 在结果中正确设置 + // 如果执行成功且有上一步骤信息,确保 previousAction 被保留 + if ($result->isSuccess() && $context->getPreviousAction() !== null && $result->getPreviousAction() === null) { + $result = $result->builder() + ->withPreviousAction($context->getPreviousAction()) + ->build(); + } + // 保存状态 $this->endoscopeStates[$endoscopeData['id']] = $result; $this->history[] = $result; @@ -214,8 +227,9 @@ class VirtualityFlowProcessor Logger::info("当前流程:{}", [$result->getProcessType()]); Logger::info("当前批次号:{}", [$result->getBatchNo()]); Logger::info("当前步骤:{}", [$result->getCurrentStep()]); - Logger::info("上一个步骤类型:{}", [$result->getPreviousAction()->action_type??"null"]); + Logger::info("上一个步骤类型:{}", [$result->getPreviousAction()->action_type_name?? "null"]); Logger::info("上一个步骤:{}", [$result->getPreviousAction()->process_name??"null"]); + Logger::info("时长:{}", [$result->getDuration()?? "null"]); Logger::info("当前语音:{$result->getFullVoice()}\n"); return $result; } diff --git a/tests/flow/node_flow/BlockTest.php b/tests/flow/node_flow/BlockTest.php index 10982d9..62473c9 100644 --- a/tests/flow/node_flow/BlockTest.php +++ b/tests/flow/node_flow/BlockTest.php @@ -80,11 +80,14 @@ class BlockTest extends TestCase Config::getInstance()->setBlockMode(true); // 创建一个时间不足的场景(只有5秒) + // 关键:设置 previousAction 和 processType 使得时间验证策略生效 $context = $this->processor->createContextBuilder() ->endoscope('胃镜1') ->reader('漂洗') ->operator('操作员1') ->currentStep('清洗') + ->previousAction('清洗') // 上一步也是清洗,表示重复刷同一步骤 + ->processType('手工洗') // 必须设置流程类型,否则 hasStep 返回 false ->duration(5) // 只有5秒,时间不足 ->batchNo(date('Ymd') . '010001') ->build(); @@ -112,6 +115,8 @@ class BlockTest extends TestCase ->reader('漂洗') ->operator('操作员1') ->currentStep('清洗') + ->previousAction('清洗') // 设置 previousAction 使时间验证生效 + ->processType('手工洗') // 必须设置流程类型 ->duration(5) // 只有5秒,时间不足 ->batchNo(date('Ymd') . '010001') ->build(); @@ -161,6 +166,8 @@ class BlockTest extends TestCase ->reader('漂洗') ->operator('操作员1') ->currentStep('清洗') + ->previousAction('清洗') // 设置 previousAction 使时间验证生效 + ->processType('手工洗') // 必须设置流程类型 ->duration(120) // 120秒,时间充足 ->batchNo(date('Ymd') . '010001') ->build();