Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FOUR-18130 #7476

Merged
merged 12 commits into from
Oct 7, 2024
44 changes: 43 additions & 1 deletion ProcessMaker/Http/Controllers/Api/CommentController.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class CommentController extends Controller
*
* @param Request $request
*
* @return \ProcessMaker\Http\Resources\ApiCollection
* @return ApiCollection
*
* @return \Illuminate\Http\Response
*/
Expand Down Expand Up @@ -87,6 +87,48 @@ public function index(Request $request)
return new ApiCollection($response);
}

/**
* Display comments related to the case
*
* @param Request $request
*
* @return ApiCollection
*
* @return \Illuminate\Http\Response
*/
public function getCommentsByCase(Request $request)
{
$request->validate([
'case_number' => 'required|integer',
]);

$query = Comment::query()
->with('user')
->with('repliedMessage');

$flag = 'visible';
if (\Auth::user()->is_administrator) {
$flag = 'all';
}
$query->hidden($flag);
$caseNumber = $request->input('case_number', null);

$query->where('case_number', $caseNumber);

if ($request->has('type')) {
$types = explode(',', $request->input('type'));
$query->whereIn('type', $types);
}

$response =
$query->orderBy(
$request->input('order_by', 'created_at'),
$request->input('order_direction', 'ASC')
)->paginate($request->input('per_page', 100));

return new ApiCollection($response);
}

private function authorizeComment(Request $request)
{
$request->validate([
Expand Down
9 changes: 8 additions & 1 deletion ProcessMaker/Http/Controllers/Api/TaskController.php
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ public function index(Request $request, $getTotal = false, User $user = null)
* @param User $user used by Saved Search package to return accurate counts
* @return array
*/
public function indexCase(Request $request, User $user = null)
public function getTasksByCase(Request $request, User $user = null)
{
if (!$user) {
$user = Auth::user();
Expand All @@ -178,8 +178,11 @@ public function indexCase(Request $request, User $user = null)
'order_direction' => 'nullable|string|in:asc,desc',
'page' => 'nullable|integer|min:1',
'per_page' => 'nullable|integer',
'includeScreen' => 'sometimes|boolean',
]);

$includeScreen = $request->input('includeScreen', false);

// Get only the columns defined
$query = ProcessRequestToken::select($this->defaultCase);
// Filter by case_number
Expand All @@ -199,6 +202,10 @@ public function indexCase(Request $request, User $user = null)

try {
$response = $query->applyPagination($request);

if ($includeScreen) {
$response = $this->addTaskData($response);
}
$response->inOverdue = 0;
} catch (QueryException $e) {
return $this->handleQueryException($e);
Expand Down
21 changes: 17 additions & 4 deletions ProcessMaker/Traits/TaskControllerIndexMethods.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use ProcessMaker\Filters\Filter;
use ProcessMaker\Managers\DataManager;
use ProcessMaker\Models\ProcessRequest;
use ProcessMaker\Models\ProcessRequestToken;
use ProcessMaker\Models\User;
Expand All @@ -17,18 +18,18 @@ trait TaskControllerIndexMethods
private function indexBaseQuery($request)
{
$query = ProcessRequestToken::exclude(['data'])->with([
'processRequest' => fn($q) => $q->exclude(['data']),
'processRequest' => fn ($q) => $q->exclude(['data']),
// review if bpmn is reuiqred here process
'process' => fn($q) => $q->exclude(['svg', 'warnings']),
'process' => fn ($q) => $q->exclude(['svg', 'warnings']),
// review if bpmn is reuiqred here processRequest.process
'processRequest.process' => fn($q) => $q->exclude(['svg', 'warnings']),
'processRequest.process' => fn ($q) => $q->exclude(['svg', 'warnings']),
// The following lines use to much memory but reduce the number of queries
// bpmn is required here in processRequest.processVersion
// 'processRequest.processVersion' => fn($q) => $q->exclude(['svg', 'warnings']),
// review if bpmn is reuiqred here processRequest.processVersion.process
// 'processRequest.processVersion.process' => fn($q) => $q->exclude(['svg', 'warnings']),
'user',
'draft'
'draft',
]);

$include = $request->input('include') ? explode(',', $request->input('include')) : [];
Expand Down Expand Up @@ -123,6 +124,18 @@ private function applyDefaultFiltering($query, $column, $filterByFields, $fieldF
$query->where(is_string($key) ? $key : $column, $operator, $fieldFilter);
}

private function addTaskData($response)
{
$dataManager = new DataManager();
$response->getCollection()->transform(function ($row) use ($dataManager) {
$row->taskData = $dataManager->getData($row);

return $row;
});

return $response;
}

private function excludeNonVisibleTasks($query, $request)
{
$nonSystem = filter_var($request->input('non_system'), FILTER_VALIDATE_BOOLEAN);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('comments', function (Blueprint $table) {
$table->unsignedInteger('case_number')->nullable();

$table->index('type');
});
}

/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('comments', function (Blueprint $table) {
$table->dropColumn('case_number');

$table->dropIndex(['type']);
});
}
};
11 changes: 11 additions & 0 deletions resources/views/requests/show.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,13 @@ class="btn d-block mr-0 ml-auto button-collapse"
</button>
</li>
@endif
<li class="list-group-item">
<button type="button" class="btn btn-outline-custom btn-block" @click="onReturnCase"
aria-haspopup="dialog">
<i class="fa fa-arrow-up"></i>
{{ __('Go to Case') }}
</button>
</li>
<div :class="classStatusCard">
<span style="margin:0; padding:0; line-height:1">@{{ __(statusLabel) }}</span>
</div>
Expand Down Expand Up @@ -486,6 +493,7 @@ class="btn btn-outline-info btn-block"
window.PM4ConfigOverrides = {
requestFiles: @json($request->requestFiles())
};
const request = @json($request);
</script>

<script src="{{ mix('js/requests/show.js') }}"></script>
Expand Down Expand Up @@ -785,6 +793,9 @@ classStatusCard() {
},
);
},
onReturnCase() {
window.open(`../cases/${request.case_number}`);
},
completeRequest() {
ProcessMaker.confirmModal(
this.$t('Caution!'),
Expand Down
3 changes: 2 additions & 1 deletion routes/api.php
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@

// Tasks
Route::get('tasks', [TaskController::class, 'index'])->name('tasks.index'); // Already filtered in controller
Route::get('tasks-by-case', [TaskController::class, 'indexCase'])->name('tasks.indexCase');
Route::get('tasks-by-case', [TaskController::class, 'getTasksByCase'])->name('tasks.index.case');
Route::get('tasks/{task}', [TaskController::class, 'show'])->name('tasks.show')->middleware('can:view,task');
Route::get('tasks/{task}/screen_fields', [TaskController::class, 'getScreenFields'])->name('getScreenFields.show')->middleware('can:view,task');
Route::get('tasks/{task}/screens/{screen}', [TaskController::class, 'getScreen'])->name('tasks.get_screen')->middleware('can:viewScreen,task,screen');
Expand Down Expand Up @@ -263,6 +263,7 @@

// Comments
Route::get('comments', [CommentController::class, 'index'])->name('comments.index');
Route::get('comments-by-case', [CommentController::class, 'getCommentsByCase'])->name('comments.index.case');
Route::get('comments/{comment}', [CommentController::class, 'show'])->name('comments.show');
Route::post('comments', [CommentController::class, 'store'])->name('comments.store');
Route::put('comments/{comment}', [CommentController::class, 'update'])->name('comments.update');
Expand Down
76 changes: 76 additions & 0 deletions tests/Feature/Api/CommentTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ class CommentTest extends TestCase

const API_TEST_URL = '/comments';

const API_COMMENT_BY_CASE = '/comments-by-case';

const STRUCTURE = [
'id',
'user_id',
Expand Down Expand Up @@ -220,4 +222,78 @@ public function testDeleteCommentNotExist()
//Validate the header status code
$response->assertStatus(405);
}

/**
* Test indexCase without case_number.
*
* @return void
*/
public function test_index_case_requires_case_number()
{
// Call the endpoint without the 'case_number' parameter
$response = $this->apiCall('GET', self::API_COMMENT_BY_CASE);

// Check if the response returns a 400 error due to missing 'case_number'
$response->assertStatus(422)
->assertJson(['message' => 'The Case number field is required.']);
}

/**
* Test comments by case
*/
public function testGetCommentByTypeByCase()
{
$this->user = User::factory()->create([
'password' => Hash::make('password'),
'is_administrator' => false,
]);
// Create a request1 then a task related to the request
$request1 = ProcessRequest::factory()->create();
$task1 = ProcessRequestToken::factory()->create([
'user_id' => $this->user->getKey(),
'process_request_id' => $request1->getKey(),
]);
Comment::factory()->count(2)->create([
'commentable_id' => $request1->getKey(),
'commentable_type' => get_class($request1),
'case_number' => $request1->case_number,
'type' => 'LOG',
'hidden' => false,
]);
Comment::factory()->count(2)->create([
'commentable_id' => $task1->getKey(),
'commentable_type' => get_class($task1),
'case_number' => $request1->case_number,
'type' => 'LOG',
'hidden' => false,
]);
// Create a request2 with the same case_number then a task related to the request
$request2 = ProcessRequest::factory()->create([
'parent_request_id' => $request1->getKey(),
]);
$task2 = ProcessRequestToken::factory()->create([
'user_id' => $this->user->getKey(),
'process_request_id' => $request2->getKey(),
]);
Comment::factory()->count(2)->create([
'commentable_id' => $request2->getKey(),
'commentable_type' => get_class($request2),
'case_number' => $request1->case_number,
'type' => 'LOG',
'hidden' => false,
]);
Comment::factory()->count(2)->create([
'commentable_id' => $task2->getKey(),
'commentable_type' => get_class($task2),
'case_number' => $request1->case_number,
'type' => 'LOG',
'hidden' => false,
]);
// Load api
$filter = "?case_number=$request1->case_number";
$response = $this->apiCall('GET', self::API_COMMENT_BY_CASE . $filter);
// Check if the response is successful and contains the expected tasks
$response->assertStatus(200);
$this->assertCount(8, $response->json('data'));
}
}
32 changes: 32 additions & 0 deletions tests/Feature/Api/TaskControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,36 @@ public function test_index_case_returns_inactive_tasks_for_case_number()
'meta',
]);
}

/**
* Test indexCase returns completed tasks related to the case_number.
*
* @return void
*/
public function test_index_cas_returns_with_data()
{
// Simulate an authenticated user
$user = User::factory()->create();
Auth::login($user);

// Create a ProcessRequestToken associated with a specific case_number
$processRequest = ProcessRequest::factory()->create();
ProcessRequestToken::factory()->create([
'user_id' => $user->id,
'status' => 'CLOSED',
'process_request_id' => $processRequest->id, // id del ProcessRequest
]);

// Call the endpoint with the 'case_number' parameter
$filter = "?case_number=$processRequest->case_number&status=CLOSED&includeScreen=" . true;
$response = $this->apiCall('GET', self::API_TASK_BY_CASE . $filter);

// Check if the response is successful and contains the expected tasks
$response->assertStatus(200);
$this->assertCount(1, $response->json('data'));
$response->assertJsonStructure([
'data' => ['*' => array_merge(self::TASK_BY_CASE_STRUCTURE, ['taskData'])],
'meta',
]);
}
}
Loading