first commit
This commit is contained in:
193
app/Http/Controllers/Api/Reports/DashboardController.php
Normal file
193
app/Http/Controllers/Api/Reports/DashboardController.php
Normal file
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\Reports;
|
||||
|
||||
use App\Enums\DashboardSortBy;
|
||||
use App\Enums\SortDirection;
|
||||
use App\Helpers\ReportHelper;
|
||||
use App\Http\Requests\Reports\DashboardRequest;
|
||||
use App\Jobs\GenerateAndSendReport;
|
||||
use App\Models\Project;
|
||||
use App\Models\User;
|
||||
use App\Reports\DashboardExport;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Contracts\Bus\Dispatcher;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Settings;
|
||||
use Throwable;
|
||||
|
||||
class DashboardController
|
||||
{
|
||||
/**
|
||||
* @api {post} /report/dashboard Dashboard Data
|
||||
* @apiDescription Retrieve dashboard data based on provided parameters.
|
||||
*
|
||||
* @apiVersion 4.0.0
|
||||
* @apiName DashboardData
|
||||
* @apiGroup Dashboard
|
||||
*
|
||||
* @apiUse AuthHeader
|
||||
*
|
||||
* @apiParam {String} start_at Start date-time in "Y-m-d H:i:s" format.
|
||||
* @apiParam {String} end_at End date-time in "Y-m-d H:i:s" format.
|
||||
* @apiParam {String} user_timezone User's timezone.
|
||||
* @apiParam {Array} [users] Array of user IDs. If not provided, all users are considered.
|
||||
* @apiParam {Array} [projects] Array of project IDs. If not provided, all projects are considered.
|
||||
*
|
||||
* @apiParamExample {json} Request Example
|
||||
* {
|
||||
* "start_at": "2006-05-31 16:15:09",
|
||||
* "end_at": "2006-05-31 16:20:07",
|
||||
* "user_timezone": "Asia/Omsk"
|
||||
* }
|
||||
*
|
||||
* @apiSuccess {Object} data Dashboard data keyed by user ID.
|
||||
* @apiSuccess {Array} data.7 Array of records for user with ID 7.
|
||||
* @apiSuccess {String} data.7.start_at Start date-time of the record.
|
||||
* @apiSuccess {Integer} data.7.activity_fill Activity fill percentage.
|
||||
* @apiSuccess {Integer} data.7.mouse_fill Mouse activity fill percentage.
|
||||
* @apiSuccess {Integer} data.7.keyboard_fill Keyboard activity fill percentage.
|
||||
* @apiSuccess {String} data.7.end_at End date-time of the record.
|
||||
* @apiSuccess {Boolean} data.7.is_manual Indicates if the record is manual.
|
||||
* @apiSuccess {String} data.7.user_email User's email address.
|
||||
* @apiSuccess {Integer} data.7.id Record ID.
|
||||
* @apiSuccess {Integer} data.7.project_id Project ID.
|
||||
* @apiSuccess {String} data.7.project_name Project name.
|
||||
* @apiSuccess {Integer} data.7.task_id Task ID.
|
||||
* @apiSuccess {String} data.7.task_name Task name.
|
||||
* @apiSuccess {Integer} data.7.user_id User ID.
|
||||
* @apiSuccess {String} data.7.full_name User's full name.
|
||||
* @apiSuccess {Integer} data.7.duration Duration in seconds.
|
||||
* @apiSuccess {Integer} data.7.from_midnight Time from midnight in seconds.
|
||||
* @apiSuccess {Object} data.7.durationByDay Duration grouped by day.
|
||||
* @apiSuccess {Integer} data.7.durationByDay.2018-05-31 Duration for the day 2018-05-31.
|
||||
* @apiSuccess {Integer} data.7.durationByDay.2018-06-04 Duration for the day 2018-06-04.
|
||||
* @apiSuccess {Integer} data.7.durationAtSelectedPeriod Duration for the selected period.
|
||||
*
|
||||
* @apiSuccessExample {json} Response Example
|
||||
* HTTP/1.1 200 OK
|
||||
* {
|
||||
* "status": 200,
|
||||
* "success": true,
|
||||
* "data": {
|
||||
* "7": [
|
||||
* {
|
||||
* "start_at": "2018-05-31 10:43:45",
|
||||
* "activity_fill": 111,
|
||||
* "mouse_fill": 64,
|
||||
* "keyboard_fill": 47,
|
||||
* "end_at": "2018-06-03 22:03:45",
|
||||
* "is_manual": 0,
|
||||
* "user_email": "projectManager1231@example.com",
|
||||
* "id": 2109,
|
||||
* "project_id": 159,
|
||||
* "project_name": "Voluptas ab et ea.",
|
||||
* "task_id": 54,
|
||||
* "task_name": "Quo consequatur mollitia nam.",
|
||||
* "user_id": 7,
|
||||
* "full_name": "Dr. Adaline Toy",
|
||||
* "duration": 300000,
|
||||
* "from_midnight": 38625,
|
||||
* "durationByDay": {
|
||||
* "2018-05-31": 285375,
|
||||
* "2018-06-04": 14625
|
||||
* },
|
||||
* "durationAtSelectedPeriod": 14625
|
||||
* }
|
||||
* ]
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @apiUse 400Error
|
||||
* @apiUse ValidationError
|
||||
* @apiUse UnauthorizedError
|
||||
*/
|
||||
public function __invoke(DashboardRequest $request): JsonResponse
|
||||
{
|
||||
$companyTimezone = Settings::scope('core')->get('timezone', 'UTC');
|
||||
|
||||
return responder()->success(
|
||||
DashboardExport::init(
|
||||
$request->input('users') ?? User::all()->pluck('id')->toArray(),
|
||||
$request->input('projects') ?? Project::all()->pluck('id')->toArray(),
|
||||
Carbon::parse($request->input('start_at'))->setTimezone($companyTimezone),
|
||||
Carbon::parse($request->input('end_at'))->setTimezone($companyTimezone),
|
||||
$companyTimezone,
|
||||
$request->input('user_timezone'),
|
||||
)->collection()->all(),
|
||||
)->respond();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Throwable
|
||||
* @api {post} /report/dashboard/download Download Dashboard Report
|
||||
* @apiDescription Generate and download a dashboard report
|
||||
*
|
||||
* @apiVersion 4.0.0
|
||||
* @apiName DownloadDashboardReport
|
||||
* @apiGroup Report
|
||||
*
|
||||
* @apiUse AuthHeader
|
||||
*
|
||||
* @apiHeader {String} Accept Specifies the content type of the response. (Example: `text/csv`)
|
||||
* @apiHeader {String} Authorization Bearer token for API access. (Example: `82|LosbyrFljFDJqUcqMNG6UveCgrclt6OzTrCWdnJBEZ1fee08e6`)
|
||||
* @apiPermission report_generate
|
||||
* @apiPermission report_full_access
|
||||
*
|
||||
* @apiParam {String} start_at Start date and time (ISO 8601 format)
|
||||
* @apiParam {String} end_at End date and time (ISO 8601 format)
|
||||
* @apiParam {String} user_timezone User's timezone
|
||||
* @apiParam {String} sort_column Column to sort by
|
||||
* @apiParam {String} sort_direction Direction to sort (asc/desc)
|
||||
*
|
||||
* @apiParamExample {json} Request Example
|
||||
* {
|
||||
* "start_at": "2024-08-06T18:00:00.000Z",
|
||||
* "end_at": "2024-08-07T17:59:59.999Z",
|
||||
* "user_timezone": "Asia/Omsk",
|
||||
* "sort_column": "user",
|
||||
* "sort_direction": "asc",
|
||||
* }
|
||||
*
|
||||
* @apiSuccess {String} url URL to download the generated report
|
||||
*
|
||||
* @apiSuccessExample {json} Response Example
|
||||
* HTTP/1.1 200 OK
|
||||
* {
|
||||
* "status": 200,
|
||||
* "success": true,
|
||||
* "data": {
|
||||
* "url": "/storage/reports/f7ac500e-a741-47ee-9e61-1b62a341fb8d/Dashboard_Report.csv"
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @apiUse 400Error
|
||||
* @apiUse ValidationError
|
||||
* @apiUse UnauthorizedError
|
||||
* @apiUse ForbiddenError
|
||||
* @apiUse ItemNotFoundError
|
||||
*/
|
||||
public function download(DashboardRequest $request): JsonResponse
|
||||
{
|
||||
$companyTimezone = Settings::scope('core')->get('timezone', 'UTC');
|
||||
|
||||
$job = new GenerateAndSendReport(
|
||||
DashboardExport::init(
|
||||
$request->input('users') ?? User::all()->pluck('id')->toArray(),
|
||||
$request->input('projects') ?? Project::all()->pluck('id')->toArray(),
|
||||
Carbon::parse($request->input('start_at'))->setTimezone($companyTimezone),
|
||||
Carbon::parse($request->input('end_at'))->setTimezone($companyTimezone),
|
||||
$companyTimezone,
|
||||
$request->input('user_timezone'),
|
||||
DashboardSortBy::tryFrom($request->input('sort_column')),
|
||||
SortDirection::tryFrom($request->input('sort_direction')),
|
||||
),
|
||||
$request->user(),
|
||||
ReportHelper::getReportFormat($request),
|
||||
);
|
||||
|
||||
app(Dispatcher::class)->dispatchSync($job);
|
||||
|
||||
return responder()->success(['url' => $job->getPublicPath()])->respond();
|
||||
}
|
||||
}
|
||||
159
app/Http/Controllers/Api/Reports/PlannedTimeReportController.php
Normal file
159
app/Http/Controllers/Api/Reports/PlannedTimeReportController.php
Normal file
@@ -0,0 +1,159 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\Reports;
|
||||
|
||||
use App\Helpers\ReportHelper;
|
||||
use App\Http\Requests\Reports\PlannedTimeReportRequest;
|
||||
use App\Jobs\GenerateAndSendReport;
|
||||
use App\Models\Project;
|
||||
use App\Reports\PlannedTimeReportExport;
|
||||
use Illuminate\Contracts\Bus\Dispatcher;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Throwable;
|
||||
|
||||
class PlannedTimeReportController
|
||||
{
|
||||
/**
|
||||
* @api {post} /report/planned-time Planned Time Report
|
||||
* @apiDescription Generate a report on planned tasks and associated time for a given project
|
||||
*
|
||||
* @apiVersion 4.0.0
|
||||
* @apiName PlannedTimeReport
|
||||
* @apiGroup Report
|
||||
*
|
||||
* @apiUse AuthHeader
|
||||
*
|
||||
* @apiPermission report_generate
|
||||
* @apiPermission report_full_access
|
||||
*
|
||||
* @apiParam {Integer} id Project ID
|
||||
*
|
||||
* @apiParamExample {json} Request Example
|
||||
* {
|
||||
* "id": 1
|
||||
* }
|
||||
*
|
||||
* @apiSuccess {Object} reportData Report data object
|
||||
* @apiSuccess {Integer} reportData.id Project ID
|
||||
* @apiSuccess {Integer} reportData.company_id Company ID
|
||||
* @apiSuccess {String} reportData.name Project name
|
||||
* @apiSuccess {String} reportData.description Project description
|
||||
* @apiSuccess {String} reportData.deleted_at Deleted timestamp (null if not deleted)
|
||||
* @apiSuccess {String} reportData.created_at Creation timestamp
|
||||
* @apiSuccess {String} reportData.updated_at Update timestamp
|
||||
* @apiSuccess {Boolean} reportData.important Whether the project is marked as important
|
||||
* @apiSuccess {String} reportData.source Source of the project (e.g., "internal")
|
||||
* @apiSuccess {Integer} reportData.screenshots_state Screenshots state (1 if active)
|
||||
* @apiSuccess {Integer} reportData.default_priority_id Default priority ID (null if not set)
|
||||
* @apiSuccess {Integer} reportData.total_spent_time Total time spent on the project
|
||||
* @apiSuccess {Object[]} reportData.tasks List of tasks under the project
|
||||
* @apiSuccess {Integer} reportData.tasks.id Task ID
|
||||
* @apiSuccess {String} reportData.tasks.task_name Task name
|
||||
* @apiSuccess {String} reportData.tasks.due_date Task due date (null if not set)
|
||||
* @apiSuccess {String} reportData.tasks.estimate Estimated time for the task (null if not set)
|
||||
* @apiSuccess {Integer} reportData.tasks.project_id Project ID to which the task belongs
|
||||
* @apiSuccess {Integer} reportData.tasks.total_spent_time Total time spent on the task
|
||||
* @apiSuccess {Object[]} reportData.tasks.workers List of workers assigned to the task
|
||||
*
|
||||
* @apiSuccessExample {json} Response Example
|
||||
* HTTP/1.1 200 OK
|
||||
* {
|
||||
* "reportData": [
|
||||
* {
|
||||
* "id": 2,
|
||||
* "company_id": 5,
|
||||
* "name": "Et veniam velit tempore.",
|
||||
* "description": "Consequatur nulla distinctio reprehenderit rerum omnis debitis. Fugit illum ratione quia harum. Optio porro consequatur enim esse.",
|
||||
* "deleted_at": null,
|
||||
* "created_at": "2023-10-26T10:26:42.000000Z",
|
||||
* "updated_at": "2023-10-26T10:26:42.000000Z",
|
||||
* "important": 1,
|
||||
* "source": "internal",
|
||||
* "default_priority_id": null,
|
||||
* "screenshots_state": 1,
|
||||
* "total_spent_time": null,
|
||||
* "tasks": [
|
||||
* {
|
||||
* "id": 11,
|
||||
* "task_name": "Qui velit fugiat magni accusantium.",
|
||||
* "due_date": null,
|
||||
* "estimate": null,
|
||||
* "project_id": 2,
|
||||
* "total_spent_time": null,
|
||||
* "workers": []
|
||||
* },
|
||||
* ...
|
||||
* ]
|
||||
* }
|
||||
* ]
|
||||
*
|
||||
* }
|
||||
*
|
||||
* @apiUse 400Error
|
||||
* @apiUse ValidationError
|
||||
* @apiUse UnauthorizedError
|
||||
* @apiUse ForbiddenError
|
||||
* @apiUse ItemNotFoundError
|
||||
*/
|
||||
public function __invoke(PlannedTimeReportRequest $request): JsonResponse
|
||||
{
|
||||
return responder()->success(
|
||||
PlannedTimeReportExport::init(
|
||||
$request->input('projects', Project::all()->pluck('id')->toArray()),
|
||||
)->collection()->all(),
|
||||
)->respond();
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {post} /report/planned-time/download Download Planned Time Report
|
||||
* @apiDescription Generate and download a report on planned time for specific projects.
|
||||
*
|
||||
* @apiVersion 4.0.0
|
||||
* @apiName DownloadPlannedTimeReport
|
||||
* @apiGroup Report
|
||||
*
|
||||
* @apiUse AuthHeader
|
||||
*
|
||||
* @apiHeader {String} Accept Specifies the content type of the response. (Example: `text/csv`)
|
||||
* @apiHeader {String} Authorization Bearer token for API access. (Example: `82|LosbyrFljFDJqUcqMNG6UveCgrclt6OzTrCWdnJBEZ1fee08e6`)
|
||||
* @apiPermission report_generate
|
||||
* @apiPermission report_full_access
|
||||
*
|
||||
* @apiParam {Array} projects Array of project IDs to include in the report. If not provided, all projects will be included.
|
||||
*
|
||||
* @apiParamExample {json} Request Example
|
||||
* {
|
||||
* "projects": [2]
|
||||
* }
|
||||
*
|
||||
* @apiSuccess {String} url URL to the generated report file.
|
||||
*
|
||||
* @apiSuccessExample {json} Response Example
|
||||
* HTTP/1.1 200 OK
|
||||
* {
|
||||
* "url": "/storage/reports/0611766a-2807-4524-9add-2e8be33c3e58/PlannedTime_Report.csv"
|
||||
* }
|
||||
*
|
||||
* @apiUse 400Error
|
||||
* @apiUse ValidationError
|
||||
* @apiUse UnauthorizedError
|
||||
* @apiUse ForbiddenError
|
||||
*/
|
||||
/**
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function download(PlannedTimeReportRequest $request): JsonResponse
|
||||
{
|
||||
$job = new GenerateAndSendReport(
|
||||
PlannedTimeReportExport::init(
|
||||
$request->input('projects', Project::all()->pluck('id')->toArray()),
|
||||
),
|
||||
$request->user(),
|
||||
ReportHelper::getReportFormat($request),
|
||||
);
|
||||
|
||||
app(Dispatcher::class)->dispatchSync($job);
|
||||
|
||||
return responder()->success(['url' => $job->getPublicPath()])->respond();
|
||||
}
|
||||
}
|
||||
228
app/Http/Controllers/Api/Reports/ProjectReportController.php
Normal file
228
app/Http/Controllers/Api/Reports/ProjectReportController.php
Normal file
@@ -0,0 +1,228 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\Reports;
|
||||
|
||||
use App\Helpers\ReportHelper;
|
||||
use App\Http\Requests\Reports\ProjectReportRequest;
|
||||
use App\Jobs\GenerateAndSendReport;
|
||||
use App\Models\User;
|
||||
use App\Models\Project;
|
||||
use App\Reports\ProjectReportExport;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Contracts\Bus\Dispatcher;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Settings;
|
||||
use Throwable;
|
||||
|
||||
class ProjectReportController
|
||||
{
|
||||
/**
|
||||
* @api {post} /report/project Project Report
|
||||
* @apiDescription Retrieve detailed project report data including user tasks and time intervals.
|
||||
*
|
||||
* @apiVersion 4.0.0
|
||||
* @apiName ProjectReport
|
||||
* @apiGroup Report
|
||||
* @apiUse AuthHeader
|
||||
* @apiPermission report_view
|
||||
* @apiPermission report_full_access
|
||||
*
|
||||
* @apiParam {String} start_at The start date and time for the report period (ISO 8601 format).
|
||||
* @apiParam {String} end_at The end date and time for the report period (ISO 8601 format).
|
||||
* @apiParam {String} user_timezone The timezone of the user making the request.
|
||||
*
|
||||
* @apiParamExample {json} Request Example
|
||||
* {
|
||||
* "start_at": "2023-05-31 16:15:09",
|
||||
* "end_at": "2023-11-30 16:20:07",
|
||||
* "user_timezone": "Asia/Omsk"
|
||||
* }
|
||||
*
|
||||
* @apiSuccess {Object[]} data List of projects.
|
||||
* @apiSuccess {Integer} data.id Project ID.
|
||||
* @apiSuccess {String} data.name Project name.
|
||||
* @apiSuccess {Integer} data.time Total time spent on the project.
|
||||
* @apiSuccess {Object[]} data.users List of users associated with the project.
|
||||
* @apiSuccess {Integer} data.users.id User ID.
|
||||
* @apiSuccess {String} data.users.full_name User's full name.
|
||||
* @apiSuccess {String} data.users.email User's email address.
|
||||
* @apiSuccess {Integer} data.users.time Total time spent by the user on the project.
|
||||
* @apiSuccess {Object[]} data.users.tasks List of tasks associated with the user.
|
||||
* @apiSuccess {Integer} data.users.tasks.id Task ID.
|
||||
* @apiSuccess {String} data.users.tasks.task_name Task name.
|
||||
* @apiSuccess {Integer} data.users.tasks.time Total time spent on the task.
|
||||
* @apiSuccess {Object[]} data.users.tasks.intervals List of time intervals for the task.
|
||||
* @apiSuccess {String} data.users.tasks.intervals.date Date of the interval.
|
||||
* @apiSuccess {Integer} data.users.tasks.intervals.time Time spent in the interval.
|
||||
* @apiSuccess {Object[]} data.users.tasks.intervals.items Detailed breakdown of intervals.
|
||||
* @apiSuccess {String} data.users.tasks.intervals.items.start_at Start time of the interval.
|
||||
* @apiSuccess {Integer} data.users.tasks.intervals.items.activity_fill Activity fill percentage during the interval.
|
||||
* @apiSuccess {Integer} data.users.tasks.intervals.items.mouse_fill Mouse activity fill percentage.
|
||||
* @apiSuccess {Integer} data.users.tasks.intervals.items.keyboard_fill Keyboard activity fill percentage.
|
||||
* @apiSuccess {String} data.users.tasks.intervals.items.end_at End time of the interval.
|
||||
* @apiSuccess {String} data.users.tasks.intervals.items.user_email User's email associated with the interval.
|
||||
* @apiSuccess {Integer} data.users.tasks.intervals.items.id Interval ID.
|
||||
* @apiSuccess {Integer} data.users.tasks.intervals.items.project_id Project ID associated with the interval.
|
||||
* @apiSuccess {String} data.users.tasks.intervals.items.project_name Project name associated with the interval.
|
||||
* @apiSuccess {Integer} data.users.tasks.intervals.items.task_id Task ID associated with the interval.
|
||||
* @apiSuccess {String} data.users.tasks.intervals.items.task_name Task name associated with the interval.
|
||||
* @apiSuccess {Integer} data.users.tasks.intervals.items.user_id User ID associated with the interval.
|
||||
* @apiSuccess {String} data.users.tasks.intervals.items.full_name User's full name associated with the interval.
|
||||
* @apiSuccess {Integer} data.users.tasks.intervals.items.hour Hour of the day for the interval.
|
||||
* @apiSuccess {String} data.users.tasks.intervals.items.day Day of the interval.
|
||||
* @apiSuccess {Integer} data.users.tasks.intervals.items.minute Minute of the hour for the interval.
|
||||
* @apiSuccess {Integer} data.users.tasks.intervals.items.duration Duration of the interval.
|
||||
* @apiSuccess {Object} data.users.tasks.intervals.items.durationByDay Duration of the interval by day.
|
||||
* @apiSuccess {Integer} data.users.tasks.intervals.items.durationAtSelectedPeriod Duration at the selected period.
|
||||
*
|
||||
* @apiSuccessExample {json} Response Example
|
||||
* HTTP/1.1 200 OK
|
||||
* {
|
||||
* "status": 200,
|
||||
* "success": true,
|
||||
* "data": [
|
||||
* {
|
||||
* "id": 159,
|
||||
* "name": "Voluptas ab et ea.",
|
||||
* "time": 3851703975,
|
||||
* "users": [
|
||||
* {
|
||||
* "id": 7,
|
||||
* "full_name": "Dr. Adaline Toy",
|
||||
* "email": "projectManager1231@example.com",
|
||||
* "time": 3851703975,
|
||||
* "tasks": [
|
||||
* {
|
||||
* "id": 54,
|
||||
* "task_name": "Quo consequatur mollitia nam.",
|
||||
* "time": 550243425,
|
||||
* "intervals": [
|
||||
* {
|
||||
* "date": "2006-05-29",
|
||||
* "time": 43425,
|
||||
* "items": [
|
||||
* {
|
||||
* "start_at": "2006-05-29 00:43:45",
|
||||
* "activity_fill": 87,
|
||||
* "mouse_fill": 81,
|
||||
* "keyboard_fill": 6,
|
||||
* "end_at": "2006-06-01 12:03:45",
|
||||
* "user_email": "projectManager1231@example.com",
|
||||
* "id": 3372,
|
||||
* "project_id": 159,
|
||||
* "project_name": "Voluptas ab et ea.",
|
||||
* "task_id": 54,
|
||||
* "task_name": "Quo consequatur mollitia nam.",
|
||||
* "user_id": 7,
|
||||
* "full_name": "Dr. Adaline Toy",
|
||||
* "hour": 0,
|
||||
* "day": "2006-05-29",
|
||||
* "minute": 40,
|
||||
* "duration": 300000,
|
||||
* "durationByDay": {
|
||||
* "2006-05-29": 256575,
|
||||
* "2006-06-01": 43425
|
||||
* },
|
||||
* "durationAtSelectedPeriod": 43425
|
||||
* }
|
||||
* ]
|
||||
* },
|
||||
* // More intervals...
|
||||
* ]
|
||||
* }
|
||||
* // More tasks...
|
||||
* ]
|
||||
* }
|
||||
* // More users...
|
||||
* ]
|
||||
* }
|
||||
* // More projects...
|
||||
* ]
|
||||
* }
|
||||
*
|
||||
* @apiUse 400Error
|
||||
* @apiUse ValidationError
|
||||
* @apiUse UnauthorizedError
|
||||
* @apiUse ForbiddenError
|
||||
*/
|
||||
public function __invoke(ProjectReportRequest $request): JsonResponse
|
||||
{
|
||||
$companyTimezone = Settings::scope('core')->get('timezone', 'UTC');
|
||||
|
||||
return responder()->success(
|
||||
ProjectReportExport::init(
|
||||
$request->input('users', User::all()->pluck('id')->toArray()),
|
||||
$request->input('projects', Project::all()->pluck('id')->toArray()),
|
||||
Carbon::parse($request->input('start_at'))->setTimezone($companyTimezone),
|
||||
Carbon::parse($request->input('end_at'))->setTimezone($companyTimezone),
|
||||
$companyTimezone
|
||||
)->collection()->all(),
|
||||
)->respond();
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {post} /api/report/dashboard/download Download Dashboard Report
|
||||
* @apiDescription Downloads a dashboard report in the specified file format.
|
||||
*
|
||||
* @apiVersion 4.0.0
|
||||
* @apiName DownloadDashboardReport
|
||||
* @apiGroup Reports
|
||||
* @apiUse AuthHeader
|
||||
* @apiHeader {String} Accept Accept mime type. Example: `text/csv`.
|
||||
*
|
||||
* @apiParam {String} start_at The start date and time for the report in ISO 8601 format.
|
||||
* @apiParam {String} end_at The end date and time for the report in ISO 8601 format.
|
||||
* @apiParam {String} user_timezone The timezone of the user. Example: `Asia/Omsk`.
|
||||
* @apiParam {Array} users List of user IDs to include in the report.
|
||||
* @apiParam {Array} projects List of project IDs to include in the report.
|
||||
*
|
||||
* @apiParamExample {json} Request Example:
|
||||
* {
|
||||
* "start_at": "2023-11-01T16:15:09Z",
|
||||
* "end_at": "2023-11-30T23:59:07Z",
|
||||
* "user_timezone": "Asia/Omsk",
|
||||
* "users": [7],
|
||||
* "projects": [159]
|
||||
* }
|
||||
*
|
||||
* @apiSuccess {String} url The URL where the generated report can be downloaded.
|
||||
*
|
||||
* @apiSuccessExample {json} Success Response:
|
||||
* HTTP/1.1 200 OK
|
||||
* {
|
||||
* "status": 200,
|
||||
* "success": true,
|
||||
* "data": {
|
||||
* "url": "/storage/reports/1b11d8f9-c5a3-4fe5-86bd-ae6a3031352c/Dashboard_Report.csv"
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @apiUse 400Error
|
||||
* @apiUse UnauthorizedError
|
||||
* @apiUse ForbiddenError
|
||||
*/
|
||||
/**
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function download(ProjectReportRequest $request): JsonResponse
|
||||
{
|
||||
$companyTimezone = Settings::scope('core')->get('timezone', 'UTC');
|
||||
|
||||
$job = new GenerateAndSendReport(
|
||||
ProjectReportExport::init(
|
||||
$request->input('users', User::all()->pluck('id')->toArray()),
|
||||
$request->input('projects', Project::all()->pluck('id')->toArray()),
|
||||
Carbon::parse($request->input('start_at'))->setTimezone($companyTimezone),
|
||||
Carbon::parse($request->input('end_at'))->setTimezone($companyTimezone),
|
||||
$companyTimezone
|
||||
),
|
||||
$request->user(),
|
||||
ReportHelper::getReportFormat($request),
|
||||
);
|
||||
|
||||
app(Dispatcher::class)->dispatchSync($job);
|
||||
|
||||
return responder()->success(['url' => $job->getPublicPath()])->respond();
|
||||
}
|
||||
|
||||
}
|
||||
98
app/Http/Controllers/Api/Reports/TimeUseReportController.php
Normal file
98
app/Http/Controllers/Api/Reports/TimeUseReportController.php
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\Reports;
|
||||
|
||||
use App\Http\Requests\Reports\TimeUseReportRequest;
|
||||
use App\Models\User;
|
||||
use App\Reports\TimeUseReportExport;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Settings;
|
||||
|
||||
/**
|
||||
* Class TimeUseReportController
|
||||
*
|
||||
*/
|
||||
class TimeUseReportController
|
||||
{
|
||||
/**
|
||||
* @api {post} /api/report/time Get User Time Report
|
||||
* @apiDescription Retrieves the time report for specified users within a given time range.
|
||||
*
|
||||
* @apiVersion 4.0.0
|
||||
* @apiName GetUserTimeReport
|
||||
* @apiGroup Reports
|
||||
*
|
||||
* @apiParam {String} start_at The start date and time for the report in ISO 8601 format.
|
||||
* @apiParam {String} end_at The end date and time for the report in ISO 8601 format.
|
||||
* @apiParam {String} user_timezone The timezone of the user. Example: `Asia/Omsk`.
|
||||
* @apiParam {Array} users List of user IDs to include in the report.
|
||||
*
|
||||
* @apiParamExample {json} Request Example:
|
||||
* {
|
||||
* "start_at": "2023-11-01T16:15:09Z",
|
||||
* "end_at": "2023-11-30T23:59:07Z",
|
||||
* "user_timezone": "Asia/Omsk",
|
||||
* "users": [7]
|
||||
* }
|
||||
*
|
||||
* @apiSuccess {Object[]} data List of users and their respective time logs.
|
||||
* @apiSuccess {Number} data.time Total time logged by the user within the specified period (in seconds).
|
||||
* @apiSuccess {Object} data.user User information.
|
||||
* @apiSuccess {Number} data.user.id User ID.
|
||||
* @apiSuccess {String} data.user.email User's email address.
|
||||
* @apiSuccess {String} data.user.full_name User's full name.
|
||||
* @apiSuccess {Object[]} data.tasks List of tasks the user has logged time for.
|
||||
* @apiSuccess {Number} data.tasks.time Time logged for the task (in seconds).
|
||||
* @apiSuccess {Number} data.tasks.task_id Task ID.
|
||||
* @apiSuccess {String} data.tasks.task_name Task name.
|
||||
* @apiSuccess {Number} data.tasks.project_id Project ID associated with the task.
|
||||
* @apiSuccess {String} data.tasks.project_name Project name associated with the task.
|
||||
*
|
||||
* @apiSuccessExample {json} Success Response:
|
||||
* HTTP/1.1 200 OK
|
||||
* {
|
||||
* "status": 200,
|
||||
* "success": true,
|
||||
* "data": [
|
||||
* {
|
||||
* "time": 2151975,
|
||||
* "user": {
|
||||
* "id": 7,
|
||||
* "email": "projectManager1231@example.com",
|
||||
* "full_name": "Dr. Adaline Toy"
|
||||
* },
|
||||
* "tasks": [
|
||||
* {
|
||||
* "time": 307425,
|
||||
* "task_id": 56,
|
||||
* "task_name": "Similique enim aspernatur.",
|
||||
* "project_id": 159,
|
||||
* "project_name": "Voluptas ab et ea."
|
||||
* },
|
||||
* ...
|
||||
* ]
|
||||
* }
|
||||
* ]
|
||||
* }
|
||||
|
||||
*
|
||||
* @apiUse 400Error
|
||||
* @apiUse UnauthorizedError
|
||||
* @apiUse ForbiddenError
|
||||
*/
|
||||
|
||||
public function __invoke(TimeUseReportRequest $request): JsonResponse
|
||||
{
|
||||
$companyTimezone = Settings::scope('core')->get('timezone', 'UTC');
|
||||
|
||||
return responder()->success(
|
||||
TimeUseReportExport::init(
|
||||
$request->input('users') ?? User::all()->pluck('id')->toArray(),
|
||||
Carbon::parse($request->input('start_at'))->setTimezone($companyTimezone),
|
||||
Carbon::parse($request->input('end_at'))->setTimezone($companyTimezone),
|
||||
$companyTimezone
|
||||
)->collection()->all(),
|
||||
)->respond();
|
||||
}
|
||||
}
|
||||
201
app/Http/Controllers/Api/Reports/UniversalReportController.php
Normal file
201
app/Http/Controllers/Api/Reports/UniversalReportController.php
Normal file
@@ -0,0 +1,201 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\Reports;
|
||||
|
||||
use App\Enums\UniversalReportType;
|
||||
use App\Enums\UniversalReportBase;
|
||||
use App\Exceptions\Entities\NotEnoughRightsException;
|
||||
use App\Helpers\ReportHelper;
|
||||
use App\Http\Requests\Reports\UniversalReport\UniversalReportEditRequest;
|
||||
use App\Http\Requests\Reports\UniversalReport\UniversalReportRequest;
|
||||
use App\Http\Requests\Reports\UniversalReport\UniversalReportShowRequest;
|
||||
use App\Http\Requests\Reports\UniversalReport\UniversalReportStoreRequest;
|
||||
use App\Http\Requests\Reports\UniversalReport\UniversalReportDestroyRequest;
|
||||
|
||||
use App\Jobs\GenerateAndSendReport;
|
||||
use App\Models\Project;
|
||||
use App\Models\UniversalReport;
|
||||
use App\Reports\PlannedTimeReportExport;
|
||||
use App\Reports\UniversalReportExport;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Contracts\Bus\Dispatcher;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Settings;
|
||||
use Throwable;
|
||||
|
||||
class UniversalReportController
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$items = [
|
||||
UniversalReportType::COMPANY->value => [],
|
||||
UniversalReportType::PERSONAL->value => [],
|
||||
];
|
||||
$user = request()->user();
|
||||
|
||||
if (request()->user()->isAdmin()) {
|
||||
UniversalReport::select('id', 'name', 'type')
|
||||
->where([
|
||||
['type', '=', UniversalReportType::COMPANY->value, 'or'],
|
||||
['user_id', '=', request()->user()->id, 'or']
|
||||
])
|
||||
->get()
|
||||
->each(function ($item) use (&$items) {
|
||||
$items[$item->type->value][] = $item->toArray();
|
||||
});
|
||||
|
||||
return responder()->success($items)->respond();
|
||||
}
|
||||
|
||||
UniversalReport::select('id', 'name', 'data_objects', 'base', 'type')->get()->each(function ($item) use (&$items) {
|
||||
if ($item->base->checkAccess($item->data_objects)) {
|
||||
unset($item->data_objects, $item->base);
|
||||
$items[$item->type->value][] = $item->toArray();
|
||||
}
|
||||
});
|
||||
|
||||
return responder()->success($items)->respond();
|
||||
}
|
||||
|
||||
public function getBases()
|
||||
{
|
||||
return responder()->success(UniversalReportBase::bases())->respond();
|
||||
}
|
||||
|
||||
public function getDataObjectsAndFields(Request $request)
|
||||
{
|
||||
$base = UniversalReportBase::tryFrom($request->input('base', null));
|
||||
// dd($base->dataObjects());
|
||||
return responder()->success([
|
||||
'fields' => $base->fields(),
|
||||
'dataObjects' => $base->dataObjects(),
|
||||
'charts' => $base->charts(),
|
||||
])->respond();
|
||||
}
|
||||
|
||||
public function store(UniversalReportStoreRequest $request)
|
||||
{
|
||||
$user = $request->user();
|
||||
|
||||
if ($request->input('type') === UniversalReportType::COMPANY->value) {
|
||||
if ($request->user()->isAdmin()) {
|
||||
$report = $user->universalReports()->create([
|
||||
'name' => $request->name,
|
||||
'type' => $request->type,
|
||||
'base' => $request->base,
|
||||
'data_objects' => $request->dataObjects,
|
||||
'fields' => $request->fields,
|
||||
'charts' => $request->charts,
|
||||
]);
|
||||
return responder()->success(['message' => "The report was saved successfully", 'id' => $report->id])->respond(200);
|
||||
} else {
|
||||
return throw new NotEnoughRightsException('User rights do not allow saving the report for the company');
|
||||
}
|
||||
}
|
||||
|
||||
$report = $user->universalReports()->create([
|
||||
'name' => $request->name,
|
||||
'type' => $request->type,
|
||||
'base' => $request->base,
|
||||
'data_objects' => $request->dataObjects,
|
||||
'fields' => $request->fields,
|
||||
'charts' => $request->charts,
|
||||
]);
|
||||
|
||||
return responder()->success(['message' => "The report was saved successfully", 'id' => $report->id])->respond(200);
|
||||
}
|
||||
|
||||
public function show(UniversalReportShowRequest $request)
|
||||
{
|
||||
return responder()->success(UniversalReport::find($request->id))->respond();
|
||||
}
|
||||
|
||||
public function edit(UniversalReportEditRequest $request)
|
||||
{
|
||||
if ($request->input('type') === UniversalReportType::COMPANY->value) {
|
||||
if ($request->user()->isAdmin()) {
|
||||
UniversalReport::where('id', $request->id)->update([
|
||||
'name' => $request->name,
|
||||
'type' => $request->type,
|
||||
'base' => $request->base,
|
||||
'data_objects' => $request->dataObjects,
|
||||
'fields' => $request->fields,
|
||||
'charts' => $request->charts,
|
||||
]);
|
||||
} else {
|
||||
return throw new NotEnoughRightsException('User rights do not allow saving the report for the company');
|
||||
}
|
||||
}
|
||||
|
||||
UniversalReport::where('id', $request->id)->update([
|
||||
'name' => $request->name,
|
||||
'type' => $request->type,
|
||||
'base' => $request->base,
|
||||
'data_objects' => $request->dataObjects,
|
||||
'fields' => $request->fields,
|
||||
'charts' => $request->charts,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
public function __invoke(UniversalReportRequest $request): JsonResponse
|
||||
{
|
||||
$companyTimezone = Settings::scope('core')->get('timezone', 'UTC');
|
||||
|
||||
return responder()->success(
|
||||
UniversalReportExport::init(
|
||||
$request->input('id'),
|
||||
Carbon::parse($request->input('start_at'))->setTimezone($companyTimezone),
|
||||
Carbon::parse($request->input('end_at'))->setTimezone($companyTimezone),
|
||||
Settings::scope('core')->get('timezone', 'UTC'),
|
||||
)->collection()->all(),
|
||||
)->respond();
|
||||
}
|
||||
|
||||
public function destroy(UniversalReportDestroyRequest $request)
|
||||
{
|
||||
UniversalReport::find($request->input('id', null))->delete();
|
||||
|
||||
return responder()->success()->respond(204);
|
||||
}
|
||||
|
||||
public function download(UniversalReportRequest $request): JsonResponse
|
||||
{
|
||||
$companyTimezone = Settings::scope('core')->get('timezone', 'UTC');
|
||||
$job = new GenerateAndSendReport(
|
||||
UniversalReportExport::init(
|
||||
$request->id,
|
||||
Carbon::parse($request->start_at) ?? Carbon::parse(),
|
||||
Carbon::parse($request->end_at) ?? Carbon::parse(),
|
||||
Settings::scope('core')->get('timezone', 'UTC'),
|
||||
$request->user()?->timezone ?? 'UTC',
|
||||
),
|
||||
|
||||
$request->user(),
|
||||
ReportHelper::getReportFormat($request),
|
||||
);
|
||||
|
||||
$job->handle();
|
||||
// app(Dispatcher::class)->dispatchSync($job);
|
||||
|
||||
return responder()->success(['url' => $job->getPublicPath()])->respond();
|
||||
}
|
||||
// /**
|
||||
// * @throws Throwable
|
||||
// */
|
||||
// public function download(UniversalReportRequest $request): JsonResponse
|
||||
// {
|
||||
// $job = new GenerateAndSendReport(
|
||||
// PlannedTimeReportExport::init(
|
||||
// $request->input('projects', Project::all()->pluck('id')->toArray()),
|
||||
// ),
|
||||
// $request->user(),
|
||||
// ReportHelper::getReportFormat($request),
|
||||
// );
|
||||
|
||||
// app(Dispatcher::class)->dispatchSync($job);
|
||||
|
||||
// return responder()->success(['url' => $job->getPublicPath()])->respond();
|
||||
// }
|
||||
}
|
||||
Reference in New Issue
Block a user