diff --git a/tests/Feature/Upgrade/PopulateCaseStartedTest.php b/tests/Feature/Upgrade/PopulateCaseStartedTest.php new file mode 100644 index 0000000000..8160d0cbc5 --- /dev/null +++ b/tests/Feature/Upgrade/PopulateCaseStartedTest.php @@ -0,0 +1,396 @@ +delete(); + parent::tearDown(); + } + + public function testUp() + { + // Instantiate PopulateCaseStarted + $populateCaseStarted = new PopulateCaseStarted(); + + // Confirm initial empty state of cases_started table + $initialCount = DB::table('cases_started')->count(); + $this->assertEquals(0, $initialCount, 'cases_started should be empty before migration'); + + // Create sample ProcessRequests with related data + $processRequests = ProcessRequest::factory()->count(5)->create(); + + // Run the migration + $populateCaseStarted->up(); + + // Confirm record insertion into cases_started + $finalCount = DB::table('cases_started')->count(); + $this->assertEquals($processRequests->count(), $finalCount, 'cases_started count should match the number of ProcessRequests created'); + + foreach ($processRequests as $processRequest) { + $casesStartedRecord = DB::table('cases_started')->where('case_number', $processRequest->case_number)->first(); + $this->assertNotNull($casesStartedRecord, 'Each ProcessRequest should have a corresponding record in cases_started'); + + // Validate field mapping and transformations + $this->assertSame($processRequest->user_id, $casesStartedRecord->user_id); + $this->assertSame($processRequest->case_number, $casesStartedRecord->case_number); + $this->assertSame($processRequest->case_title, $casesStartedRecord->case_title); + $this->assertSame($processRequest->case_title_formatted, $casesStartedRecord->case_title_formatted); + $this->assertSame($this->mapStatus($processRequest->status), $casesStartedRecord->case_status); + $this->assertEquals($processRequest->initiated_at, $casesStartedRecord->initiated_at); + $this->assertEquals($processRequest->completed_at, $casesStartedRecord->completed_at); + $this->assertEquals($processRequest->created_at, $casesStartedRecord->created_at); + $this->assertEquals($processRequest->updated_at, $casesStartedRecord->updated_at); + } + } + + public function testTokensColumn() + { + // Instantiate PopulateCaseStarted + $populateCaseStarted = new PopulateCaseStarted(); + + // Confirm initial empty state of cases_started table + $initialCount = DB::table('cases_started')->count(); + $this->assertEquals(0, $initialCount, 'cases_started should be empty before migration'); + + // Create user + $user = User::factory()->create(); + $this->actingAs($user); + // Create sample ProcessRequests with related data + $processRequests = ProcessRequest::factory()->count(5)->create([ + 'user_id' => $user->id, + ]); + // Get the ID of the first process request to use as the shared process_request_id + $processRequest = $processRequests->first(); + ProcessRequestToken::factory()->create([ + 'process_request_id' => $processRequest->id, + 'element_type' => 'startEvent', + ]); + $processRequestTokens = ProcessRequestToken::factory()->count(3)->create([ + 'process_request_id' => $processRequest->id, + 'element_type' => 'task', + ]); + $processRequestTokenIds = $processRequestTokens->pluck('id')->toArray(); + // Run the migration + $populateCaseStarted->up(); + + // Confirm record insertion into cases_started + $finalCount = DB::table('cases_started')->count(); + $this->assertEquals($processRequests->count(), $finalCount, 'cases_started count should match the number of ProcessRequests created'); + $casesStartedRecord = DB::table('cases_started')->where('case_number', $processRequest->case_number)->first(); + $this->assertNotNull($casesStartedRecord, 'Each ProcessRequest should have a corresponding record in cases_started'); + + $tokensArray = json_decode($casesStartedRecord->request_tokens, true); + $this->assertEqualsCanonicalizing($tokensArray, $processRequestTokenIds); + } + + public function testParticipatedColumn() + { + // Instantiate PopulateCaseStarted + $populateCaseStarted = new PopulateCaseStarted(); + + // Confirm initial empty state of cases_started table + $initialCount = DB::table('cases_started')->count(); + $this->assertEquals(0, $initialCount, 'cases_started should be empty before migration'); + + // Create first user + $user1 = User::factory()->create(); + $this->actingAs($user1); + // Create second user + $user2 = User::factory()->create(); + $this->actingAs($user2); + + // Create sample ProcessRequests with related data + $processRequests = ProcessRequest::factory()->create([ + 'user_id' => $user1->id, + ]); + $processRequests = ProcessRequest::factory()->create([ + 'user_id' => $user2->id, + ]); + // Get the ID of the first process request to use as the shared process_request_id + $processRequest = $processRequests->first(); + + // Create ProcessRequestTokens for processRequest + ProcessRequestToken::factory()->create([ + 'process_request_id' => $processRequest->id, + 'element_type' => 'startEvent', + 'user_id' => $user1->id, + ]); + ProcessRequestToken::factory()->count(2)->create([ + 'process_request_id' => $processRequest->id, + 'element_type' => 'task', + 'user_id' => $user1->id, + ]); + ProcessRequestToken::factory()->count(2)->create([ + 'process_request_id' => $processRequest->id, + 'element_type' => 'task', + 'user_id' => $user2->id, + ]); + $processRequestTokens = DB::table('process_request_tokens')->where('process_request_id', $processRequest->id); + $participantIds = $processRequestTokens->pluck('user_id')->toArray(); + $uniqueParticipantIds = array_unique($participantIds); + // Run the migration + $populateCaseStarted->up(); + + // Confirm record insertion into cases_started + $finalCount = DB::table('cases_started')->count(); + $this->assertEquals($processRequests->count(), $finalCount, 'cases_started count should match the number of ProcessRequests created'); + $casesStartedRecord = DB::table('cases_started')->where('case_number', $processRequest->case_number)->first(); + $this->assertNotNull($casesStartedRecord, 'Each ProcessRequest should have a corresponding record in cases_started'); + // Prepare the participants record + $tokensArray = json_decode($casesStartedRecord->participants, true); + // Assert both arrays contain the same items in any order + $this->assertEqualsCanonicalizing($tokensArray, $uniqueParticipantIds); + } + + public function testCasesStartedProcessColumn() + { + // Instantiate the migration class + $populateCaseStarted = new PopulateCaseStarted(); + + // Confirm the initial state of the `cases_started` table + $initialCount = DB::table('cases_started')->count(); + $this->assertEquals(0, $initialCount, 'cases_started table should be empty before migration'); + + // Create test users + $user1 = User::factory()->create(); + $user2 = User::factory()->create(); + // Create test processes + $process1 = Process::factory()->create(); + $process2 = Process::factory()->create(); + // Create sample ProcessRequests for both users + $processRequest1 = ProcessRequest::factory()->create([ + 'user_id' => $user1->id, + 'name' => $process1->name, + 'process_id' => $process1->id, + ]); + $processRequest2 = ProcessRequest::factory()->create([ + 'user_id' => $user2->id, + 'parent_request_id' => $processRequest1->id, + 'name' => $process2->name, + 'process_id' => $process2->id, + ]); + + // Create ProcessRequestTokens for processRequest1 + ProcessRequestToken::factory()->create([ + 'process_request_id' => $processRequest1->id, + 'process_id' => $processRequest1->process_id, + 'element_type' => 'startEvent', + 'status' => 'TRIGGERED', + 'element_id' => 'node_1', + 'user_id' => $user1->id, + ]); + ProcessRequestToken::factory()->create([ + 'process_request_id' => $processRequest1->id, + 'process_id' => $processRequest1->process_id, + 'element_type' => 'callActivity', + 'status' => 'CLOSED', + 'element_id' => 'node_51', + 'user_id' => $user1->id, + 'subprocess_request_id' => $processRequest2->id, + ]); + ProcessRequestToken::factory()->create([ + 'process_request_id' => $processRequest1->id, + 'process_id' => $processRequest1->process_id, + 'element_type' => 'task', + 'status' => 'ACTIVE', + 'element_id' => 'node_12', + 'user_id' => $user1->id, + ]); + + // Create ProcessRequestTokens for processRequest2 + ProcessRequestToken::factory()->create([ + 'process_request_id' => $processRequest2->id, + 'process_id' => $processRequest2->process_id, + 'element_type' => 'startEvent', + 'status' => 'TRIGGERED', + 'element_id' => 'node_1', + 'user_id' => $user1->id, + ]); + ProcessRequestToken::factory()->create([ + 'process_request_id' => $processRequest2->id, + 'process_id' => $processRequest2->process_id, + 'element_type' => 'task', + 'status' => 'CLOSED', + 'element_id' => 'node_2', + 'user_id' => $user1->id, + ]); + ProcessRequestToken::factory()->create([ + 'process_request_id' => $processRequest2->id, + 'process_id' => $processRequest2->process_id, + 'element_type' => 'task', + 'status' => 'CLOSED', + 'element_id' => 'node_12', + 'user_id' => $user1->id, + ]); + ProcessRequestToken::factory()->create([ + 'process_request_id' => $processRequest2->id, + 'process_id' => $processRequest2->process_id, + 'element_type' => 'end_event', + 'status' => 'CLOSED', + 'element_id' => 'node_25', + 'user_id' => null, + ]); + + // Run the migration + $populateCaseStarted->up(); + + // Validate that the ProcessRequest1 has a corresponding entry in `cases_started` + $casesStartedRecord = DB::table('cases_started')->where('case_number', $processRequest1->case_number)->first(); + $this->assertNotNull($casesStartedRecord, 'ProcessRequest should have a corresponding record in cases_started'); + + // Expected data structure for `cases_started.processes` column + $expectedData = [ + (object) ['id' => $processRequest1->process_id, 'name' => $processRequest1->name], + (object) ['id' => $processRequest2->process_id, 'name' => $processRequest2->name], + ]; + + // Decode the JSON data from `cases_started.processes` + $processesArray = json_decode($casesStartedRecord->processes); + + // Assert both arrays contain the same items in any order + $this->assertEqualsCanonicalizing($expectedData, $processesArray, 'The processes data in cases_started should match the expected data'); + } + + public function testCasesStartedRequestsColumn() + { + // Instantiate the migration class + $populateCaseStarted = new PopulateCaseStarted(); + + // Confirm the initial state of the `cases_started` table + $initialCount = DB::table('cases_started')->count(); + $this->assertEquals(0, $initialCount, 'cases_started table should be empty before migration'); + + // Create test users + $user1 = User::factory()->create(); + $user2 = User::factory()->create(); + // Create test processes + $process1 = Process::factory()->create(); + $process2 = Process::factory()->create(); + // Create sample ProcessRequests for both users + $processRequest1 = ProcessRequest::factory()->create([ + 'user_id' => $user1->id, + 'name' => $process1->name, + 'process_id' => $process1->id, + ]); + $processRequest2 = ProcessRequest::factory()->create([ + 'user_id' => $user2->id, + 'parent_request_id' => $processRequest1->id, + 'name' => $process2->name, + 'process_id' => $process2->id, + ]); + + // Create ProcessRequestTokens for processRequest1 + ProcessRequestToken::factory()->create([ + 'process_request_id' => $processRequest1->id, + 'process_id' => $processRequest1->process_id, + 'element_type' => 'startEvent', + 'status' => 'TRIGGERED', + 'element_id' => 'node_1', + 'user_id' => $user1->id, + ]); + ProcessRequestToken::factory()->create([ + 'process_request_id' => $processRequest1->id, + 'process_id' => $processRequest1->process_id, + 'element_type' => 'callActivity', + 'status' => 'CLOSED', + 'element_id' => 'node_51', + 'user_id' => $user1->id, + 'subprocess_request_id' => $processRequest2->id, + ]); + ProcessRequestToken::factory()->create([ + 'process_request_id' => $processRequest1->id, + 'process_id' => $processRequest1->process_id, + 'element_type' => 'task', + 'status' => 'ACTIVE', + 'element_id' => 'node_12', + 'user_id' => $user1->id, + ]); + + // Create ProcessRequestTokens for processRequest2 + ProcessRequestToken::factory()->create([ + 'process_request_id' => $processRequest2->id, + 'process_id' => $processRequest2->process_id, + 'element_type' => 'startEvent', + 'status' => 'TRIGGERED', + 'element_id' => 'node_1', + 'user_id' => $user1->id, + ]); + ProcessRequestToken::factory()->create([ + 'process_request_id' => $processRequest2->id, + 'process_id' => $processRequest2->process_id, + 'element_type' => 'task', + 'status' => 'CLOSED', + 'element_id' => 'node_2', + 'user_id' => $user1->id, + ]); + ProcessRequestToken::factory()->create([ + 'process_request_id' => $processRequest2->id, + 'process_id' => $processRequest2->process_id, + 'element_type' => 'task', + 'status' => 'CLOSED', + 'element_id' => 'node_12', + 'user_id' => $user1->id, + ]); + ProcessRequestToken::factory()->create([ + 'process_request_id' => $processRequest2->id, + 'process_id' => $processRequest2->process_id, + 'element_type' => 'end_event', + 'status' => 'CLOSED', + 'element_id' => 'node_25', + 'user_id' => null, + ]); + + // Run the migration + $populateCaseStarted->up(); + + // Validate that the ProcessRequest1 has a corresponding entry in `cases_started` + $casesStartedRecord = DB::table('cases_started')->where('case_number', $processRequest1->case_number)->first(); + $this->assertNotNull($casesStartedRecord, 'ProcessRequest should have a corresponding record in cases_started'); + + // Expected data structure for `cases_started.processes` column + $expectedData = [ + (object) ['id' => $processRequest1->id, 'name' => $processRequest1->name, 'parent_request_id' => $processRequest1->parent_request_id], + (object) ['id' => $processRequest2->id, 'name' => $processRequest2->name, 'parent_request_id' => $processRequest2->parent_request_id], + ]; + + // Decode the JSON data from `cases_started.requests` + $requestsArray = json_decode($casesStartedRecord->requests); + + // Assert both arrays contain the same items in any order + $this->assertEqualsCanonicalizing($expectedData, $requestsArray, 'The requests data in cases_started should match the expected data'); + } + + /** + * Helper function to map ProcessRequest status to cases_started status + * + * @param string $status ProcessRequest status + * @return string cases_started status + */ + private function mapStatus($status) + { + return $status === 'ACTIVE' ? 'IN_PROGRESS' : $status; + } +} diff --git a/tests/Feature/Upgrade/PopulateCasesParticipatedTest.php b/tests/Feature/Upgrade/PopulateCasesParticipatedTest.php new file mode 100644 index 0000000000..c4315a11f9 --- /dev/null +++ b/tests/Feature/Upgrade/PopulateCasesParticipatedTest.php @@ -0,0 +1,652 @@ +user = User::factory()->create(); + $this->user2 = User::factory()->create(); + $this->user3 = User::factory()->create(); + + $this->process = Process::factory()->create(); + $this->subProcess1 = Process::factory()->create(); + $this->subProcess2 = Process::factory()->create(); + + $this->request = ProcessRequest::factory()->create([ + 'user_id' => $this->user->id, + 'status' => 'ACTIVE', + 'process_id' => $this->process->id, + ]); + $this->childRequest1 = ProcessRequest::factory()->create([ + 'user_id' => $this->user->id, + 'status' => 'ACTIVE', + 'parent_request_id' => $this->request->id, + 'process_id' => $this->subProcess1->id, + ]); + $this->childRequest2 = ProcessRequest::factory()->create([ + 'user_id' => $this->user->id, + 'status' => 'ACTIVE', + 'parent_request_id' => $this->request->id, + 'process_id' => $this->subProcess2->id, + ]); + } + + private function upgrade() + { + $this->artisan('migrate', [ + '--path' => 'upgrades/2024_10_09_152947_populate_cases_participated.php', + ])->run(); + } + + private function getCaseStartedData($tokens) + { + $processes = collect([ + [ + 'id' => $this->process->id, + 'name' => $this->process->name, + ], + ]); + + $requests = collect([ + [ + 'id' => $this->request->id, + 'name' => $this->request->name, + 'parent_request_id' => $this->request->parent_request_id, + ], + ]); + + $tasks = $tokens->map(function ($item) { + return [ + 'id' => $item->id, + 'element_id' => $item->element_id, + 'name' => $item->element_name, + 'process_id' => $item->process_id, + 'status' => $item->status, + ]; + }); + + $requestTokens = $tokens->pluck('id'); + + return [ + 'processes' => $processes->toArray(), + 'requests' => $requests->toArray(), + 'tasks' => $tasks->toArray(), + 'request_tokens' => $requestTokens->toArray(), + 'participants' => $tokens->pluck('user_id')->unique()->values()->toArray(), + ]; + } + + public function test_one_participant() + { + $tokens = ProcessRequestToken::factory()->count(5)->create([ + 'user_id' => $this->user->id, + 'process_request_id' => $this->request->id, + 'element_type' => 'task', + ]); + + $case = CaseStarted::factory()->create(array_merge([ + 'user_id' => $this->user->id + ], $this->getCaseStartedData($tokens))); + + $this->upgrade(); + + $this->assertDatabaseCount('cases_participated', 1); + $this->assertDatabaseHas('cases_participated', [ + 'user_id' => $this->user->id, + 'case_number' => $case->case_number, + 'case_title' => $case->case_title, + 'case_title_formatted' => $case->case_title_formatted, + 'case_status' => $case->case_status, + 'processes->[0]->id' => $this->process->id, + 'processes->[0]->name' => $this->process->name, + 'requests->[0]->id' => $this->request->id, + 'requests->[0]->name' => $this->request->name, + 'requests->[0]->parent_request_id' => $this->request->parent_request_id, + 'request_tokens->[0]' => $tokens[0]->id, + 'request_tokens->[4]' => $tokens[4]->id, + 'tasks->[0]->id' => $tokens[0]->id, + 'tasks->[0]->element_id' => $tokens[0]->element_id, + 'tasks->[0]->name' => $tokens[0]->element_name, + 'tasks->[0]->process_id' => $tokens[0]->process_id, + 'tasks->[0]->status' => $tokens[0]->status, + 'tasks->[4]->id' => $tokens[4]->id, + 'tasks->[4]->element_id' => $tokens[4]->element_id, + 'tasks->[4]->name' => $tokens[4]->element_name, + 'tasks->[4]->process_id' => $tokens[4]->process_id, + 'tasks->[4]->status' => $tokens[4]->status, + ]); + } + + public function test_multiple_participants() + { + $tokens1 = ProcessRequestToken::factory()->count(5)->create([ + 'user_id' => $this->user->id, + 'process_request_id' => $this->request->id, + 'element_type' => 'task', + ]); + + $tokens2 = ProcessRequestToken::factory()->count(5)->create([ + 'user_id' => $this->user2->id, + 'process_request_id' => $this->request->id, + 'element_type' => 'task', + ]); + + $tokens3 = ProcessRequestToken::factory()->count(5)->create([ + 'user_id' => $this->user3->id, + 'process_request_id' => $this->request->id, + 'element_type' => 'task', + ]); + + $tokens = $tokens1->merge($tokens2)->merge($tokens3); + + $data = $this->getCaseStartedData($tokens); + + $case = CaseStarted::factory()->create(array_merge([ + 'user_id' => $this->user->id + ], $data)); + + $this->upgrade(); + + $this->assertDatabaseCount('cases_participated', 3); + $this->assertDatabaseHas('cases_participated', [ + 'user_id' => $this->user->id, + 'case_number' => $case->case_number, + 'case_title' => $case->case_title, + 'case_title_formatted' => $case->case_title_formatted, + 'case_status' => $case->case_status, + 'processes->[0]->id' => $this->process->id, + 'processes->[0]->name' => $this->process->name, + 'requests->[0]->id' => $this->request->id, + 'requests->[0]->name' => $this->request->name, + 'requests->[0]->parent_request_id' => $this->request->parent_request_id, + 'request_tokens->[0]' => $tokens1[0]->id, + 'request_tokens->[9]' => $tokens2[4]->id, + 'request_tokens->[14]' => $tokens3[4]->id, + 'tasks->[0]->id' => $tokens1[0]->id, + 'tasks->[0]->element_id' => $tokens1[0]->element_id, + 'tasks->[0]->name' => $tokens1[0]->element_name, + 'tasks->[0]->process_id' => $tokens1[0]->process_id, + 'tasks->[0]->status' => $tokens1[0]->status, + 'tasks->[9]->id' => $tokens2[4]->id, + 'tasks->[9]->element_id' => $tokens2[4]->element_id, + 'tasks->[9]->name' => $tokens2[4]->element_name, + 'tasks->[9]->process_id' => $tokens2[4]->process_id, + 'tasks->[9]->status' => $tokens2[4]->status, + 'tasks->[14]->id' => $tokens3[4]->id, + 'tasks->[14]->element_id' => $tokens3[4]->element_id, + 'tasks->[14]->name' => $tokens3[4]->element_name, + 'tasks->[14]->process_id' => $tokens3[4]->process_id, + 'tasks->[14]->status' => $tokens3[4]->status, + ]); + + $this->assertDatabaseHas('cases_participated', [ + 'user_id' => $this->user2->id, + 'case_number' => $case->case_number, + 'case_title' => $case->case_title, + 'case_title_formatted' => $case->case_title_formatted, + 'case_status' => $case->case_status, + 'processes->[0]->id' => $this->process->id, + 'processes->[0]->name' => $this->process->name, + 'requests->[0]->id' => $this->request->id, + 'requests->[0]->name' => $this->request->name, + 'requests->[0]->parent_request_id' => $this->request->parent_request_id, + 'request_tokens->[0]' => $tokens1[0]->id, + 'request_tokens->[9]' => $tokens2[4]->id, + 'request_tokens->[14]' => $tokens3[4]->id, + 'tasks->[0]->id' => $tokens1[0]->id, + 'tasks->[0]->element_id' => $tokens1[0]->element_id, + 'tasks->[0]->name' => $tokens1[0]->element_name, + 'tasks->[0]->process_id' => $tokens1[0]->process_id, + 'tasks->[0]->status' => $tokens1[0]->status, + 'tasks->[9]->id' => $tokens2[4]->id, + 'tasks->[9]->element_id' => $tokens2[4]->element_id, + 'tasks->[9]->name' => $tokens2[4]->element_name, + 'tasks->[9]->process_id' => $tokens2[4]->process_id, + 'tasks->[9]->status' => $tokens2[4]->status, + 'tasks->[14]->id' => $tokens3[4]->id, + 'tasks->[14]->element_id' => $tokens3[4]->element_id, + 'tasks->[14]->name' => $tokens3[4]->element_name, + 'tasks->[14]->process_id' => $tokens3[4]->process_id, + 'tasks->[14]->status' => $tokens3[4]->status, + ]); + } + + public function test_participants() + { + $tokens1 = ProcessRequestToken::factory()->count(5)->create([ + 'user_id' => $this->user->id, + 'process_request_id' => $this->request->id, + 'element_type' => 'task', + ]); + + $tokens2 = ProcessRequestToken::factory()->count(5)->create([ + 'user_id' => $this->user2->id, + 'process_request_id' => $this->request->id, + 'element_type' => 'task', + ]); + + $tokens3 = ProcessRequestToken::factory()->count(5)->create([ + 'user_id' => $this->user3->id, + 'process_request_id' => $this->request->id, + 'element_type' => 'task', + ]); + + $tokens = $tokens1->merge($tokens2)->merge($tokens3); + $data = $this->getCaseStartedData($tokens); + + $case = CaseStarted::factory()->create(array_merge([ + 'user_id' => $this->user->id + ], $data)); + + $this->upgrade(); + + $this->assertDatabaseCount('cases_participated', 3); + $this->assertDatabaseHas('cases_participated', [ + 'user_id' => $this->user->id, + 'case_number' => $case->case_number, + 'participants->[0]' => $this->user->id, + 'participants->[1]' => $this->user2->id, + 'participants->[2]' => $this->user3->id, + ]); + $this->assertDatabaseHas('cases_participated', [ + 'user_id' => $this->user2->id, + 'case_number' => $case->case_number, + 'participants->[0]' => $this->user->id, + 'participants->[1]' => $this->user2->id, + 'participants->[2]' => $this->user3->id, + ]); + $this->assertDatabaseHas('cases_participated', [ + 'user_id' => $this->user3->id, + 'case_number' => $case->case_number, + 'participants->[0]' => $this->user->id, + 'participants->[1]' => $this->user2->id, + 'participants->[2]' => $this->user3->id, + ]); + } + + public function test_request_tokens() + { + $tokens1 = ProcessRequestToken::factory()->count(2)->create([ + 'user_id' => $this->user->id, + 'process_request_id' => $this->request->id, + 'element_type' => 'task', + ]); + + $tokens2 = ProcessRequestToken::factory()->count(3)->create([ + 'user_id' => $this->user2->id, + 'process_request_id' => $this->request->id, + 'element_type' => 'task', + ]); + + $tokens3 = ProcessRequestToken::factory()->count(2)->create([ + 'user_id' => $this->user3->id, + 'process_request_id' => $this->request->id, + 'element_type' => 'task', + ]); + + $tokens = $tokens1->merge($tokens2)->merge($tokens3); + $data = $this->getCaseStartedData($tokens); + + $case = CaseStarted::factory()->create(array_merge([ + 'user_id' => $this->user->id + ], $data)); + + $this->upgrade(); + + $this->assertDatabaseCount('cases_participated', 3); + $this->assertDatabaseHas('cases_participated', [ + 'user_id' => $this->user->id, + 'case_number' => $case->case_number, + 'request_tokens->[0]' => $tokens1[0]->id, + 'request_tokens->[1]' => $tokens1[1]->id, + 'request_tokens->[2]' => $tokens2[0]->id, + 'request_tokens->[3]' => $tokens2[1]->id, + 'request_tokens->[4]' => $tokens2[2]->id, + 'request_tokens->[5]' => $tokens3[0]->id, + 'request_tokens->[6]' => $tokens3[1]->id, + ]); + $this->assertDatabaseHas('cases_participated', [ + 'user_id' => $this->user2->id, + 'case_number' => $case->case_number, + 'request_tokens->[0]' => $tokens1[0]->id, + 'request_tokens->[1]' => $tokens1[1]->id, + 'request_tokens->[2]' => $tokens2[0]->id, + 'request_tokens->[3]' => $tokens2[1]->id, + 'request_tokens->[4]' => $tokens2[2]->id, + 'request_tokens->[5]' => $tokens3[0]->id, + 'request_tokens->[6]' => $tokens3[1]->id, + ]); + $this->assertDatabaseHas('cases_participated', [ + 'user_id' => $this->user3->id, + 'case_number' => $case->case_number, + 'request_tokens->[0]' => $tokens1[0]->id, + 'request_tokens->[1]' => $tokens1[1]->id, + 'request_tokens->[2]' => $tokens2[0]->id, + 'request_tokens->[3]' => $tokens2[1]->id, + 'request_tokens->[4]' => $tokens2[2]->id, + 'request_tokens->[5]' => $tokens3[0]->id, + 'request_tokens->[6]' => $tokens3[1]->id, + ]); + } + + public function test_tasks() + { + $tokens1 = ProcessRequestToken::factory()->count(2)->create([ + 'user_id' => $this->user->id, + 'process_request_id' => $this->request->id, + 'element_type' => 'task', + 'status' => 'ACTIVE', + ]); + + $tokens2 = ProcessRequestToken::factory()->count(3)->create([ + 'user_id' => $this->user2->id, + 'process_request_id' => $this->request->id, + 'element_type' => 'task', + 'status' => 'COMPLETED', + ]); + + $tokens3 = ProcessRequestToken::factory()->count(2)->create([ + 'user_id' => $this->user3->id, + 'process_request_id' => $this->request->id, + 'element_type' => 'task', + 'status' => 'ACTIVE', + ]); + + $tokens = $tokens1->merge($tokens2)->merge($tokens3); + $data = $this->getCaseStartedData($tokens); + + $case = CaseStarted::factory()->create(array_merge([ + 'user_id' => $this->user->id + ], $data)); + + $this->upgrade(); + + $this->assertDatabaseCount('cases_participated', 3); + $this->assertDatabaseHas('cases_participated', [ + 'user_id' => $this->user->id, + 'case_number' => $case->case_number, + 'tasks->[0]->id' => $tokens1[0]->id, + 'tasks->[0]->status' => $tokens1[0]->status, + 'tasks->[1]->id' => $tokens1[1]->id, + 'tasks->[1]->status' => $tokens1[1]->status, + 'tasks->[2]->id' => $tokens2[0]->id, + 'tasks->[2]->status' => $tokens2[0]->status, + 'tasks->[3]->id' => $tokens2[1]->id, + 'tasks->[3]->status' => $tokens2[1]->status, + 'tasks->[4]->id' => $tokens2[2]->id, + 'tasks->[4]->status' => $tokens2[2]->status, + 'tasks->[5]->id' => $tokens3[0]->id, + 'tasks->[5]->status' => $tokens3[0]->status, + 'tasks->[6]->id' => $tokens3[1]->id, + 'tasks->[6]->status' => $tokens3[1]->status, + ]); + } + + public function test_sub_processes() + { + $tokens1 = ProcessRequestToken::factory()->count(2)->create([ + 'user_id' => $this->user->id, + 'process_request_id' => $this->request->id, + 'element_type' => 'task', + 'status' => 'ACTIVE', + ]); + + $tokens2 = ProcessRequestToken::factory()->count(3)->create([ + 'user_id' => $this->user2->id, + 'process_request_id' => $this->request->id, + 'element_type' => 'task', + 'status' => 'COMPLETED', + ]); + + $tokens3 = ProcessRequestToken::factory()->count(2)->create([ + 'user_id' => $this->user3->id, + 'process_request_id' => $this->childRequest1->id, + 'element_type' => 'task', + 'status' => 'ACTIVE', + ]); + + $tokens = $tokens1->merge($tokens2)->merge($tokens3); + $data = $this->getCaseStartedData($tokens); + + $data['processes'] = collect($data['processes'])->push([ + 'id' => $this->subProcess1->id, + 'name' => $this->subProcess1->name, + ])->toArray(); + + $case = CaseStarted::factory()->create(array_merge([ + 'user_id' => $this->user->id + ], $data)); + + $this->upgrade(); + + $this->assertDatabaseCount('cases_participated', 3); + $this->assertDatabaseHas('cases_participated', [ + 'user_id' => $this->user->id, + 'case_number' => $case->case_number, + 'processes->[0]->id' => $this->process->id, + 'processes->[0]->name' => $this->process->name, + 'processes->[1]->id' => $this->subProcess1->id, + 'processes->[1]->name' => $this->subProcess1->name, + ]); + } + + public function test_child_requests() + { + $tokens1 = ProcessRequestToken::factory()->count(2)->create([ + 'user_id' => $this->user->id, + 'process_request_id' => $this->request->id, + 'element_type' => 'task', + 'status' => 'ACTIVE', + ]); + + $tokens2 = ProcessRequestToken::factory()->count(3)->create([ + 'user_id' => $this->user2->id, + 'process_request_id' => $this->childRequest1->id, + 'element_type' => 'task', + 'status' => 'COMPLETED', + ]); + + $tokens3 = ProcessRequestToken::factory()->count(2)->create([ + 'user_id' => $this->user3->id, + 'process_request_id' => $this->childRequest2->id, + 'element_type' => 'task', + 'status' => 'ACTIVE', + ]); + + $tokens = $tokens1->merge($tokens2)->merge($tokens3); + $data = $this->getCaseStartedData($tokens); + + $data['processes'] = collect($data['processes'])->push([ + 'id' => $this->subProcess1->id, + 'name' => $this->subProcess1->name, + ])->push([ + 'id' => $this->subProcess2->id, + 'name' => $this->subProcess2->name, + ])->toArray(); + + $data['requests'] = collect($data['requests'])->push([ + 'id' => $this->childRequest1->id, + 'name' => $this->childRequest1->name, + 'parent_request_id' => $this->childRequest1->parent_request_id, + ])->push([ + 'id' => $this->childRequest2->id, + 'name' => $this->childRequest2->name, + 'parent_request_id' => $this->childRequest2->parent_request_id, + ])->toArray(); + + $case = CaseStarted::factory()->create(array_merge([ + 'user_id' => $this->user->id + ], $data)); + + $this->upgrade(); + + $this->assertDatabaseCount('cases_participated', 3); + $this->assertDatabaseHas('cases_participated', [ + 'user_id' => $this->user->id, + 'case_number' => $case->case_number, + 'processes->[0]->id' => $this->process->id, + 'processes->[0]->name' => $this->process->name, + 'processes->[1]->id' => $this->subProcess1->id, + 'processes->[1]->name' => $this->subProcess1->name, + 'processes->[2]->id' => $this->subProcess2->id, + 'processes->[2]->name' => $this->subProcess2->name, + 'requests->[0]->id' => $this->request->id, + 'requests->[0]->name' => $this->request->name, + 'requests->[0]->parent_request_id' => $this->request->parent_request_id, + 'requests->[1]->id' => $this->childRequest1->id, + 'requests->[1]->name' => $this->childRequest1->name, + 'requests->[1]->parent_request_id' => $this->childRequest1->parent_request_id, + 'requests->[2]->id' => $this->childRequest2->id, + 'requests->[2]->name' => $this->childRequest2->name, + 'requests->[2]->parent_request_id' => $this->childRequest2->parent_request_id, + ]); + } + + public function test_sub_process_tasks() + { + $tokens1 = ProcessRequestToken::factory()->count(2)->create([ + 'user_id' => $this->user->id, + 'process_request_id' => $this->request->id, + 'element_type' => 'task', + 'status' => 'ACTIVE', + ]); + + $tokens2 = ProcessRequestToken::factory()->count(3)->create([ + 'user_id' => $this->user2->id, + 'process_request_id' => $this->childRequest1->id, + 'element_type' => 'task', + 'status' => 'COMPLETED', + ]); + + $tokens3 = ProcessRequestToken::factory()->count(2)->create([ + 'user_id' => $this->user3->id, + 'process_request_id' => $this->childRequest2->id, + 'element_type' => 'task', + 'status' => 'ACTIVE', + ]); + + $tokens = $tokens1->merge($tokens2)->merge($tokens3); + $data = $this->getCaseStartedData($tokens); + + $data['processes'] = collect($data['processes'])->push([ + 'id' => $this->subProcess1->id, + 'name' => $this->subProcess1->name, + ])->push([ + 'id' => $this->subProcess2->id, + 'name' => $this->subProcess2->name, + ])->toArray(); + + $data['requests'] = collect($data['requests'])->push([ + 'id' => $this->childRequest1->id, + 'name' => $this->childRequest1->name, + 'parent_request_id' => $this->childRequest1->parent_request_id, + ])->push([ + 'id' => $this->childRequest2->id, + 'name' => $this->childRequest2->name, + 'parent_request_id' => $this->childRequest2->parent_request_id, + ])->toArray(); + + $case = CaseStarted::factory()->create(array_merge([ + 'user_id' => $this->user->id + ], $data)); + + $this->upgrade(); + + $this->assertDatabaseCount('cases_participated', 3); + $this->assertDatabaseHas('cases_participated', [ + 'user_id' => $this->user->id, + 'case_number' => $case->case_number, + 'processes->[0]->id' => $this->process->id, + 'processes->[0]->name' => $this->process->name, + 'processes->[1]->id' => $this->subProcess1->id, + 'processes->[1]->name' => $this->subProcess1->name, + 'processes->[2]->id' => $this->subProcess2->id, + 'processes->[2]->name' => $this->subProcess2->name, + 'requests->[0]->id' => $this->request->id, + 'requests->[0]->name' => $this->request->name, + 'requests->[0]->parent_request_id' => $this->request->parent_request_id, + 'requests->[1]->id' => $this->childRequest1->id, + 'requests->[1]->name' => $this->childRequest1->name, + 'requests->[1]->parent_request_id' => $this->childRequest1->parent_request_id, + 'requests->[2]->id' => $this->childRequest2->id, + 'requests->[2]->name' => $this->childRequest2->name, + 'requests->[2]->parent_request_id' => $this->childRequest2->parent_request_id, + ]); + + $this->assertDatabaseHas('cases_participated', [ + 'user_id' => $this->user->id, + 'case_number' => $case->case_number, + 'tasks->[0]->id' => $tokens[0]->id, + 'tasks->[1]->id' => $tokens[1]->id, + 'tasks->[2]->id' => $tokens2[0]->id, + 'tasks->[3]->id' => $tokens2[1]->id, + 'tasks->[4]->id' => $tokens2[2]->id, + 'tasks->[5]->id' => $tokens3[0]->id, + 'tasks->[6]->id' => $tokens3[1]->id, + ]); + + $this->assertDatabaseHas('cases_participated', [ + 'user_id' => $this->user2->id, + 'case_number' => $case->case_number, + 'tasks->[0]->id' => $tokens[0]->id, + 'tasks->[1]->id' => $tokens[1]->id, + 'tasks->[2]->id' => $tokens2[0]->id, + 'tasks->[3]->id' => $tokens2[1]->id, + 'tasks->[4]->id' => $tokens2[2]->id, + 'tasks->[5]->id' => $tokens3[0]->id, + 'tasks->[6]->id' => $tokens3[1]->id, + ]); + + $this->assertDatabaseHas('cases_participated', [ + 'user_id' => $this->user3->id, + 'case_number' => $case->case_number, + 'tasks->[0]->id' => $tokens[0]->id, + 'tasks->[1]->id' => $tokens[1]->id, + 'tasks->[2]->id' => $tokens2[0]->id, + 'tasks->[3]->id' => $tokens2[1]->id, + 'tasks->[4]->id' => $tokens2[2]->id, + 'tasks->[5]->id' => $tokens3[0]->id, + 'tasks->[6]->id' => $tokens3[1]->id, + ]); + } +} diff --git a/upgrades/2024_10_09_032151_populate_case_started.php b/upgrades/2024_10_09_032151_populate_case_started.php index c6d29706e0..3c73dd6b79 100644 --- a/upgrades/2024_10_09_032151_populate_case_started.php +++ b/upgrades/2024_10_09_032151_populate_case_started.php @@ -30,7 +30,7 @@ public function up() // @todo add a validation to check the data consistency $this->validateDataConsistency(); - DB::table('cases_started')->truncate(); + DB::table('cases_started')->delete(); echo PHP_EOL . ' Populating case_started from process_requests' . PHP_EOL; $startTime = microtime(true); // Start the timer @@ -83,26 +83,23 @@ private function createTemporaryTableWithNonSystemRequests() $query = DB::table('process_requests') ->join('processes', 'process_requests.process_id', '=', 'processes.id') ->join('process_categories', 'processes.process_category_id', '=', 'process_categories.id') - ->whereNull('process_requests.parent_request_id') // Filter out subrequests ->where('process_categories.is_system', false) // Filter out system categories + ->whereNotNull('process_requests.case_number') + ->whereNull('process_requests.parent_request_id') ->whereNotIn('process_requests.case_number', function ($subquery) { // Filter out requests that have already been populated in the cases_started table $subquery->select('case_number')->from('cases_started'); }) ->select( - 'process_requests.id', + DB::raw('min(process_requests.id) as id'), 'process_requests.case_number', - 'process_requests.user_id', - 'process_requests.case_title', - 'process_requests.case_title_formatted', - 'process_requests.initiated_at', - 'process_requests.created_at', - 'process_requests.completed_at', - 'process_requests.updated_at', - 'process_requests.name', - 'process_requests.parent_request_id', - 'processes.id as process_id', - 'processes.name as process_name', + DB::raw('min(process_requests.user_id) as user_id'), + DB::raw('max(process_requests.case_title) as case_title'), + DB::raw('max(process_requests.case_title_formatted) as case_title_formatted'), + DB::raw('min(process_requests.initiated_at) as initiated_at'), + DB::raw('min(process_requests.created_at) as created_at'), + DB::raw('max(process_requests.completed_at) as completed_at'), + DB::raw('max(process_requests.updated_at) as updated_at'), DB::raw(' JSON_ARRAYAGG( JSON_OBJECT( @@ -120,22 +117,44 @@ private function createTemporaryTableWithNonSystemRequests() ) ) as requests '), // Collect requests in an array of objects - DB::raw("IF(process_requests.status = 'ACTIVE', 'IN_PROGRESS', process_requests.status) as status") + DB::raw("max(IF(process_requests.status = 'ACTIVE', 'IN_PROGRESS', process_requests.status)) as status") ) ->groupBy( - 'process_requests.id', - 'process_requests.case_number', - 'process_requests.user_id', - 'process_requests.case_title', - 'process_requests.case_title_formatted', - 'process_requests.initiated_at', - 'process_requests.created_at', - 'process_requests.completed_at', - 'process_requests.updated_at', - DB::raw("IF(process_requests.status = 'ACTIVE', 'IN_PROGRESS', process_requests.status)") + 'process_requests.case_number' ); // Group by all selected fields that are not aggregated DB::statement('CREATE TEMPORARY TABLE process_requests_temp AS ' . $query->toSql(), $query->getBindings()); + + DB::statement(<<join('process_requests_temp as temp', 'pr.process_request_id', '=', 'temp.id') + ->join('process_requests as temp', 'pr.process_request_id', '=', 'temp.id') ->join('participants_temp as part', 'temp.case_number', '=', 'part.case_number') ->select( 'temp.case_number', @@ -228,30 +248,17 @@ private function insertIntoCasesStarted() prt1.initiated_at, CONCAT('cn_', prt1.case_number, ' ', prt1.case_title) as keywords, COALESCE(prt2.participants, JSON_ARRAY()) as participants, - prt1.processes, + JSON_MERGE_PRESERVE(prt1.processes, COALESCE(prtc.processes, JSON_ARRAY())) as processes, COALESCE(prt2.request_tokens, JSON_ARRAY()) as request_tokens, - prt1.requests, + JSON_MERGE_PRESERVE(prt1.requests, COALESCE(prtc.requests, JSON_ARRAY())) as requests, COALESCE(prt2.tasks, JSON_ARRAY()) as tasks, prt1.updated_at, prt1.user_id FROM process_requests_temp as prt1 + LEFT JOIN process_requests_children_temp as prtc + ON prt1.case_number = prtc.case_number LEFT JOIN process_request_tokens_tmp as prt2 ON prt1.case_number = prt2.case_number - LEFT JOIN JSON_TABLE( - COALESCE(prt2.participants, JSON_ARRAY()), - "$[*]" COLUMNS ( - participant JSON PATH "$" - ) - ) AS jt - ON 1 = 1 - GROUP BY - prt1.case_number, prt1.status, prt1.case_title, - prt1.case_title_formatted, prt1.completed_at, - prt1.created_at, prt1.initiated_at, prt1.processes, - prt2.request_tokens, prt1.requests, prt1.updated_at, - prt1.user_id, - prt2.participants, - prt2.tasks SQL ); } @@ -317,7 +324,27 @@ private function validateDataConsistency() ->first(); if (!is_null($results)) { - throw new Exception('Inconsistency detected, multiple records with null parent for the same request.'); + $warning = 'Inconsistency detected, multiple records with null parent for the same request. ' + . 'Case number: ' . $results->case_number . ' Count of parent Requests: ' . $results->total; + echo PHP_EOL . $warning . PHP_EOL; + // Ask to continue + if ($this->confirm($warning . ' Do you want to continue?')) { + return; + } } } + + function confirm($message) + { + // Show the confirmation message with a "yes/no" prompt + echo $message . " (yes/no): "; + + // Get user input from the command line + $handle = fopen("php://stdin", "r"); + $response = trim(fgets($handle)); + fclose($handle); + + // Check if the response is "yes" + return strtolower($response) === 'yes'; + } } diff --git a/upgrades/2024_10_09_152947_populate_cases_participated.php b/upgrades/2024_10_09_152947_populate_cases_participated.php index a2b63d838d..1984b90719 100644 --- a/upgrades/2024_10_09_152947_populate_cases_participated.php +++ b/upgrades/2024_10_09_152947_populate_cases_participated.php @@ -1,9 +1,6 @@ truncate(); - - $this->createProcessRequestsTempTable(); - $this->createProcessRequestTokensTempTable(); - $this->process_request_participants_temp(); - - $this->getProcessRequests() - ->chunk(1000, function ($rows) { - $casesParticipated = []; - - foreach ($rows as $row) { - $processes = CaseUtils::storeProcesses(collect(json_decode($row->processes))); - $requests = CaseUtils::storeRequests(collect(json_decode($row->requests))); - $requestTokens = CaseUtils::storeRequestTokens(collect(json_decode($row->request_tokens))); - $tasks = CaseUtils::storeTasks(collect(json_decode($row->tasks))); - $participants = CaseUtils::storeParticipants(collect(json_decode($row->participants))); - - $dataKeywords = [ - 'case_number' => $row->case_number, - 'case_title' => $row->case_title, - ]; - - array_push($casesParticipated, [ - 'user_id' => $row->user_id, - 'case_number' => $row->case_number, - 'case_title' => $row->case_title, - 'case_title_formatted' => $row->case_title_formatted, - 'case_status' => $row->case_status, - 'processes' => $processes, - 'requests' => $requests, - 'request_tokens' => $requestTokens, - 'tasks' => $tasks, - 'participants' => $participants, - 'initiated_at' => $row->initiated_at, - 'completed_at' => $row->completed_at, - 'created_at' => $row->created_at, - 'updated_at' => $row->updated_at, - 'keywords' => CaseUtils::getKeywords($dataKeywords), - ]); - } - - DB::table('cases_participated')->insert($casesParticipated); - - Log::info('Inserted ' . count($casesParticipated) . ' cases participated records'); - }); - } catch (Exception $e) { - Log::error($e->getMessage()); - echo $e->getMessage(); - } + $total_participants = $this->validateDataConsistency(); + + DB::table('cases_participated')->delete(); + echo PHP_EOL . ' Populating case_participated from cases_started' . PHP_EOL; + + $startTime = microtime(true); // Start the timer + + $this->createTemporaryParticipantsTable(); + $this->logTimeElapsed('Created temporary table with participants', $startTime); + + $this->insertIntoCasesParticipated(); + $this->logTimeElapsed('Inserted data into cases_participated', $startTime); + + $count = DB::table('cases_participated')->count(); + + echo PHP_EOL . "Cases Started participants. Total cases started participants: {$total_participants}" . PHP_EOL; + echo PHP_EOL . "Cases Participated have been populated successfully. Total cases participated: {$count}" . PHP_EOL; + + echo PHP_EOL; } /** @@ -74,116 +40,109 @@ public function up() */ public function down() { - DB::table('cases_participated')->truncate(); + DB::table('cases_participated')->delete(); } - protected function createProcessRequestsTempTable(): void + /** + * Log the time elapsed since the start of the process. + * + * @param string $message Message to log + * @param float $startTime Time when the processing started (in microseconds) + * @return void + */ + private function logTimeElapsed(string $message, float $startTime): void { - DB::statement('DROP TEMPORARY TABLE IF EXISTS process_requests_temp'); - - $query = DB::table('process_requests as pr') - ->select( - 'pr.id', - 'pr.name', - 'pr.case_number', - 'pr.case_title', - 'pr.case_title_formatted', - 'pr.status', - 'pr.parent_request_id', - 'pr.initiated_at', - 'pr.completed_at', - 'pr.created_at', - 'pr.updated_at', - 'pc.id as process_id', - 'pc.name as process_name' - ) - ->join('processes as pc', 'pr.process_id', '=', 'pc.id') - ->whereIn('pr.status', ['ACTIVE', 'COMPLETED']) - ->whereNotNull('pr.case_number'); - - DB::statement("CREATE TEMPORARY TABLE IF NOT EXISTS process_requests_temp AS ({$query->toSql()})", $query->getBindings()); + $currentTime = microtime(true); + $timeElapsed = $currentTime - $startTime; + + // Format the elapsed time to 4 decimal places for higher precision + echo " {$message} - Time elapsed: " . number_format($timeElapsed, 4) . ' seconds' . PHP_EOL; } - protected function createProcessRequestTokensTempTable(): void + /** + * Creates a temporary table from process_request_tokens, + * obtaining unique user_id by case_number + * + * @return void + * + * @throws Exception If there is an error creating the temporary table + */ + private function createTemporaryParticipantsTable() { - DB::statement('DROP TEMPORARY TABLE IF EXISTS process_request_tokens_temp'); + DB::statement('DROP TEMPORARY TABLE IF EXISTS participants_temp2'); - $query = DB::table('process_request_tokens as prt') + // Build the query for `participants_temp2` + $query = DB::table('cases_started as cs') ->select([ - 'prt.id', - DB::raw('CAST(prt.id AS CHAR(50)) as task_id'), - 'prt.element_name', - 'prt.element_id', - 'prt.element_type', - 'prt.process_id', - 'prt.status', - 'prt.user_id', - 'prt.process_request_id', + DB::raw('participants.item as user_id'), + 'cs.case_number', + 'cs.case_title', + 'cs.case_title_formatted', + 'cs.case_status', + 'cs.processes', + 'cs.requests', + 'cs.request_tokens', + 'cs.tasks', + 'cs.participants', + 'cs.initiated_at', + 'cs.completed_at', + 'cs.created_at', + 'cs.updated_at', + 'cs.keywords', ]) - ->join('process_requests_temp as prt2', 'prt.process_request_id', '=', 'prt2.id') - ->whereIn('prt.element_type', ['task', 'callActivity', 'scriptTask']) - ->whereNotNull('prt.user_id'); - - DB::statement("CREATE TEMPORARY TABLE IF NOT EXISTS process_request_tokens_temp AS ({$query->toSql()})", $query->getBindings()); + ->join( + DB::raw('JSON_TABLE(cs.participants, \'$[*]\' COLUMNS(item INT PATH \'$\')) AS participants'), + function ($join) { + // The join condition is essentially empty, just joins for each item in participants + } + ); + + // Execute the query and create the temporary table + DB::statement('CREATE TEMPORARY TABLE participants_temp2 AS ' . $query->toSql(), $query->getBindings()); } - protected function process_request_participants_temp(): void + private function insertIntoCasesParticipated() { - DB::statement('DROP TEMPORARY TABLE IF EXISTS process_request_participants_temp'); - - $query = DB::table('process_request_tokens_temp as prt2') + $insertQuery = DB::table('participants_temp2 as part') ->select([ - DB::raw('JSON_ARRAYAGG(prt2.user_id) as participants'), - 'pr2.case_number' - ]) - ->join('process_requests_temp as pr2', 'prt2.process_request_id', '=', 'pr2.id') - ->groupBy('pr2.case_number'); - - DB::statement("CREATE TEMPORARY TABLE IF NOT EXISTS process_request_participants_temp AS ({$query->toSql()})", $query->getBindings()); + 'part.user_id', + 'part.case_number', + 'part.case_title', + 'part.case_title_formatted', + 'part.case_status', + 'part.processes', + 'part.requests', + 'part.request_tokens', + 'part.tasks', + 'part.participants', + 'part.initiated_at', + 'part.completed_at', + 'part.created_at', + 'part.updated_at', + 'part.keywords', + ]); + + // Perform the insert and return the number of affected rows + return DB::table('cases_participated')->insertUsing([ + 'user_id', 'case_number', 'case_title', 'case_title_formatted', 'case_status', + 'processes', 'requests', 'request_tokens', 'tasks', 'participants', + 'initiated_at', 'completed_at', 'created_at', 'updated_at', 'keywords', + ], $insertQuery); } - protected function getProcessRequests(): Builder + /** + * Check if exist inconsistency in "process_request" table + */ + private function validateDataConsistency() { - return DB::table('process_requests_temp as pr') - ->select([ - 'prt.user_id', - 'pr.case_number', - 'pr.case_title', - 'pr.case_title_formatted', - DB::raw("IF(pr.status = 'ACTIVE', 'IN_PROGRESS', pr.status) as case_status"), - DB::raw("JSON_ARRAYAGG(JSON_OBJECT('id', pr.process_id, 'name', pr.process_name)) as processes"), - DB::raw("JSON_ARRAYAGG(JSON_OBJECT('id', pr.id, 'name', pr.name, 'parent_request_id', pr.parent_request_id)) as requests"), - DB::raw("JSON_ARRAYAGG(prt.id) as request_tokens"), - DB::raw("JSON_ARRAYAGG( - IF(prt.element_type != 'callActivity', - JSON_OBJECT( - 'id', prt.task_id, - 'name', prt.element_name, - 'element_id', prt.element_id, - 'process_id', prt.process_id, - 'status', prt.status - ), JSON_OBJECT()) - ) as tasks"), - 'par.participants', - 'pr.initiated_at', - 'pr.completed_at', - 'pr.created_at', - 'pr.updated_at' - ]) - ->join('process_request_tokens_temp as prt', 'pr.id', '=', 'prt.process_request_id') - ->join('process_request_participants_temp as par', 'pr.case_number', '=', 'par.case_number') - ->groupBy( - 'prt.user_id', - 'pr.case_number', - 'pr.case_title', - 'pr.case_title_formatted', - DB::raw("IF(pr.status = 'ACTIVE', 'IN_PROGRESS', pr.status)"), - 'par.participants', - 'pr.initiated_at', - 'pr.completed_at', - 'pr.created_at', - 'pr.updated_at' - ) - ->orderBy('pr.case_number'); + $results = DB::table('cases_started') + ->select(DB::raw('sum(json_length(participants)) total_participants')) + ->first(); + + if (is_null($results)) { + throw new Exception('Inconsistency detected, multiple records with null parent for the same request.'); + } + + return $results->total_participants; } }