mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-14 03:02:15 +01:00
Added shareable reports
This commit is contained in:
committed by
Constantin Graf
parent
9c82efdf07
commit
0860aa9d24
@@ -102,6 +102,7 @@ class ProjectController extends Controller
|
||||
$project->is_billable = (bool) $request->input('is_billable');
|
||||
$project->billable_rate = $request->getBillableRate();
|
||||
$project->client_id = $request->input('client_id');
|
||||
$project->is_public = $request->getIsPublic();
|
||||
if ($this->canAccessPremiumFeatures($organization) && $request->has('estimated_time')) {
|
||||
$project->estimated_time = $request->getEstimatedTime();
|
||||
}
|
||||
@@ -127,6 +128,9 @@ class ProjectController extends Controller
|
||||
if ($request->has('is_archived')) {
|
||||
$project->archived_at = $request->getIsArchived() ? Carbon::now() : null;
|
||||
}
|
||||
if ($request->has('is_public')) {
|
||||
$project->is_public = $request->boolean('is_public');
|
||||
}
|
||||
if ($this->canAccessPremiumFeatures($organization) && $request->has('estimated_time')) {
|
||||
$project->estimated_time = $request->getEstimatedTime();
|
||||
}
|
||||
|
||||
@@ -4,9 +4,14 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers\Api\V1\Public;
|
||||
|
||||
use App\Enums\TimeEntryAggregationType;
|
||||
use App\Http\Controllers\Api\V1\Controller;
|
||||
use App\Http\Resources\V1\Report\DetailedReportResource;
|
||||
use App\Http\Resources\V1\Report\DetailedWithDataReportResource;
|
||||
use App\Models\Report;
|
||||
use App\Models\TimeEntry;
|
||||
use App\Service\Dto\ReportPropertiesDto;
|
||||
use App\Service\TimeEntryAggregationService;
|
||||
use App\Service\TimeEntryFilter;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -22,7 +27,7 @@ class ReportController extends Controller
|
||||
*
|
||||
* @operationId getPublicReport
|
||||
*/
|
||||
public function show(Request $request): DetailedReportResource
|
||||
public function show(Request $request, TimeEntryAggregationService $timeEntryAggregationService): DetailedWithDataReportResource
|
||||
{
|
||||
$shareSecret = $request->header('X-Api-Key');
|
||||
if (! is_string($shareSecret)) {
|
||||
@@ -30,6 +35,9 @@ class ReportController extends Controller
|
||||
}
|
||||
|
||||
$report = Report::query()
|
||||
->with([
|
||||
'organization',
|
||||
])
|
||||
->where('share_secret', '=', $shareSecret)
|
||||
->where('is_public', '=', true)
|
||||
->where(function (Builder $builder): void {
|
||||
@@ -38,7 +46,45 @@ class ReportController extends Controller
|
||||
->orWhere('public_until', '>', now());
|
||||
})
|
||||
->firstOrFail();
|
||||
/** @var ReportPropertiesDto $properties */
|
||||
$properties = $report->properties;
|
||||
|
||||
return new DetailedReportResource($report);
|
||||
$timeEntriesQuery = TimeEntry::query()
|
||||
->whereBelongsTo($report->organization, 'organization');
|
||||
|
||||
$filter = new TimeEntryFilter($timeEntriesQuery);
|
||||
$filter->addStart($properties->start);
|
||||
$filter->addEnd($properties->end);
|
||||
$filter->addActive($properties->active);
|
||||
$filter->addBillable($properties->billable);
|
||||
$filter->addMemberIdsFilter($properties->memberIds?->toArray());
|
||||
$filter->addProjectIdsFilter($properties->projectIds?->toArray());
|
||||
$filter->addTagIdsFilter($properties->tagIds?->toArray());
|
||||
$filter->addTaskIdsFilter($properties->taskIds?->toArray());
|
||||
$filter->addClientIdsFilter($properties->clientIds?->toArray());
|
||||
$timeEntriesQuery = $filter->get();
|
||||
|
||||
$data = $timeEntryAggregationService->getAggregatedTimeEntriesWithDescriptions(
|
||||
$timeEntriesQuery->clone(),
|
||||
$report->properties->group,
|
||||
$report->properties->subGroup,
|
||||
$report->properties->timezone,
|
||||
$report->properties->weekStart,
|
||||
false,
|
||||
$report->properties->start,
|
||||
$report->properties->end,
|
||||
);
|
||||
$historyData = $timeEntryAggregationService->getAggregatedTimeEntriesWithDescriptions(
|
||||
$timeEntriesQuery->clone(),
|
||||
TimeEntryAggregationType::fromInterval($report->properties->historyGroup),
|
||||
null,
|
||||
$report->properties->timezone,
|
||||
$report->properties->weekStart,
|
||||
true,
|
||||
$report->properties->start,
|
||||
$report->properties->end,
|
||||
);
|
||||
|
||||
return new DetailedWithDataReportResource($report, $data, $historyData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,15 +4,17 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers\Api\V1;
|
||||
|
||||
use App\Enums\TimeEntryAggregationType;
|
||||
use App\Enums\Weekday;
|
||||
use App\Http\Requests\V1\Report\ReportStoreRequest;
|
||||
use App\Http\Requests\V1\Report\ReportUpdateRequest;
|
||||
use App\Http\Resources\V1\Report\DetailedReportResource;
|
||||
use App\Http\Resources\V1\Report\ReportCollection;
|
||||
use App\Http\Resources\V1\Report\ReportResource;
|
||||
use App\Models\Organization;
|
||||
use App\Models\Report;
|
||||
use App\Service\Dto\ReportPropertiesDto;
|
||||
use App\Service\ReportService;
|
||||
use App\Service\TimezoneService;
|
||||
use Illuminate\Auth\Access\AuthorizationException;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
@@ -32,6 +34,8 @@ class ReportController extends Controller
|
||||
/**
|
||||
* Get reports
|
||||
*
|
||||
* @return ReportCollection<ReportResource>
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
*
|
||||
* @operationId getReports
|
||||
@@ -69,9 +73,10 @@ class ReportController extends Controller
|
||||
*
|
||||
* @operationId createReport
|
||||
*/
|
||||
public function store(Organization $organization, ReportStoreRequest $request): DetailedReportResource
|
||||
public function store(Organization $organization, ReportStoreRequest $request, TimezoneService $timezoneService, ReportService $reportService): DetailedReportResource
|
||||
{
|
||||
$this->checkPermission($organization, 'reports:create');
|
||||
$user = $this->user();
|
||||
|
||||
$report = new Report;
|
||||
$report->name = $request->getName();
|
||||
@@ -79,11 +84,32 @@ class ReportController extends Controller
|
||||
$isPublic = $request->getIsPublic();
|
||||
$report->is_public = $isPublic;
|
||||
$properties = new ReportPropertiesDto;
|
||||
$properties->group = TimeEntryAggregationType::from($request->input('properties.group'));
|
||||
$properties->subGroup = TimeEntryAggregationType::from($request->input('properties.sub_group'));
|
||||
$properties->group = $request->getPropertyGroup();
|
||||
$properties->subGroup = $request->getPropertySubGroup();
|
||||
$properties->historyGroup = $request->getPropertyHistoryGroup();
|
||||
$properties->start = $request->getPropertyStart();
|
||||
$properties->end = $request->getPropertyEnd();
|
||||
$properties->active = $request->getPropertyActive();
|
||||
$properties->setMemberIds($request->input('properties.member_ids', null));
|
||||
$properties->billable = $request->getPropertyBillable();
|
||||
$properties->setClientIds($request->input('properties.client_ids', null));
|
||||
$properties->setProjectIds($request->input('properties.project_ids', null));
|
||||
$properties->setTagIds($request->input('properties.tag_ids', null));
|
||||
$properties->setTaskIds($request->input('properties.task_ids', null));
|
||||
$properties->weekStart = $request->has('properties.week_start') ? Weekday::from($request->input('properties.week_start')) : $user->week_start;
|
||||
$timezone = $user->timezone;
|
||||
if ($request->has('properties.timezone')) {
|
||||
if ($timezoneService->isValid($request->input('properties.timezone'))) {
|
||||
$timezone = $request->input('properties.timezone');
|
||||
}
|
||||
if ($timezoneService->mapLegacyTimezone($request->input('properties.timezone')) !== null) {
|
||||
$timezone = $timezoneService->mapLegacyTimezone($request->input('properties.timezone'));
|
||||
}
|
||||
}
|
||||
$properties->timezone = $timezone;
|
||||
$report->properties = $properties;
|
||||
if ($isPublic) {
|
||||
$report->share_secret = app(ReportService::class)->generateSecret();
|
||||
$report->share_secret = $reportService->generateSecret();
|
||||
$report->public_until = $request->getPublicUntil();
|
||||
} else {
|
||||
$report->share_secret = null;
|
||||
@@ -102,7 +128,7 @@ class ReportController extends Controller
|
||||
*
|
||||
* @operationId updateReport
|
||||
*/
|
||||
public function update(Organization $organization, Report $report, ReportUpdateRequest $request): DetailedReportResource
|
||||
public function update(Organization $organization, Report $report, ReportUpdateRequest $request, ReportService $reportService): DetailedReportResource
|
||||
{
|
||||
$this->checkPermission($organization, 'reports:update', $report);
|
||||
|
||||
@@ -116,7 +142,7 @@ class ReportController extends Controller
|
||||
$isPublic = $request->getIsPublic();
|
||||
$report->is_public = $isPublic;
|
||||
if ($isPublic) {
|
||||
$report->share_secret = app(ReportService::class)->generateSecret();
|
||||
$report->share_secret = $reportService->generateSecret();
|
||||
$report->public_until = $request->getPublicUntil();
|
||||
} else {
|
||||
$report->share_secret = null;
|
||||
|
||||
@@ -68,9 +68,18 @@ class ProjectStoreRequest extends FormRequest
|
||||
'min:0',
|
||||
'max:2147483647',
|
||||
],
|
||||
// Whether the project is public
|
||||
'is_public' => [
|
||||
'boolean',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function getIsPublic(): bool
|
||||
{
|
||||
return $this->has('is_public') && $this->boolean('is_public');
|
||||
}
|
||||
|
||||
public function getBillableRate(): ?int
|
||||
{
|
||||
$input = $this->input('billable_rate');
|
||||
|
||||
@@ -50,6 +50,9 @@ class ProjectUpdateRequest extends FormRequest
|
||||
'is_archived' => [
|
||||
'boolean',
|
||||
],
|
||||
'is_public' => [
|
||||
'boolean',
|
||||
],
|
||||
'client_id' => [
|
||||
'nullable',
|
||||
ExistsEloquent::make(Client::class, null, function (Builder $builder): Builder {
|
||||
|
||||
@@ -5,6 +5,8 @@ declare(strict_types=1);
|
||||
namespace App\Http\Requests\V1\Report;
|
||||
|
||||
use App\Enums\TimeEntryAggregationType;
|
||||
use App\Enums\TimeEntryAggregationTypeInterval;
|
||||
use App\Enums\Weekday;
|
||||
use App\Models\Organization;
|
||||
use Illuminate\Contracts\Validation\Rule as LegacyValidationRule;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
@@ -49,11 +51,11 @@ class ReportStoreRequest extends FormRequest
|
||||
'array',
|
||||
],
|
||||
'properties.start' => [
|
||||
'nullable',
|
||||
'required',
|
||||
'date_format:Y-m-d\TH:i:s\Z',
|
||||
],
|
||||
'properties.end' => [
|
||||
'nullable',
|
||||
'required',
|
||||
'date_format:Y-m-d\TH:i:s\Z',
|
||||
],
|
||||
'properties.active' => [
|
||||
@@ -80,6 +82,7 @@ class ReportStoreRequest extends FormRequest
|
||||
'string',
|
||||
'uuid',
|
||||
],
|
||||
// Filter by project IDs, project IDs are OR combined
|
||||
'properties.project_ids' => [
|
||||
'nullable',
|
||||
'array',
|
||||
@@ -88,6 +91,7 @@ class ReportStoreRequest extends FormRequest
|
||||
'string',
|
||||
'uuid',
|
||||
],
|
||||
// Filter by tag IDs, tag IDs are OR combined
|
||||
'properties.tag_ids' => [
|
||||
'nullable',
|
||||
'array',
|
||||
@@ -108,11 +112,22 @@ class ReportStoreRequest extends FormRequest
|
||||
'required',
|
||||
Rule::enum(TimeEntryAggregationType::class),
|
||||
],
|
||||
|
||||
'properties.sub_group' => [
|
||||
'required',
|
||||
Rule::enum(TimeEntryAggregationType::class),
|
||||
],
|
||||
'properties.history_group' => [
|
||||
'required',
|
||||
Rule::enum(TimeEntryAggregationTypeInterval::class),
|
||||
],
|
||||
'properties.week_start' => [
|
||||
'nullable',
|
||||
Rule::enum(Weekday::class),
|
||||
],
|
||||
'properties.timezone' => [
|
||||
'nullable',
|
||||
'timezone:all',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -137,4 +152,57 @@ class ReportStoreRequest extends FormRequest
|
||||
|
||||
return $publicUntil === null ? null : Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $publicUntil);
|
||||
}
|
||||
|
||||
public function getPropertyStart(): Carbon
|
||||
{
|
||||
$start = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $this->input('properties.start'));
|
||||
if ($start === null) {
|
||||
throw new \LogicException('Start date validation is not working');
|
||||
}
|
||||
|
||||
return $start;
|
||||
}
|
||||
|
||||
public function getPropertyEnd(): Carbon
|
||||
{
|
||||
$end = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $this->input('properties.end'));
|
||||
if ($end === null) {
|
||||
throw new \LogicException('End date validation is not working');
|
||||
}
|
||||
|
||||
return $end;
|
||||
}
|
||||
|
||||
public function getPropertyActive(): ?bool
|
||||
{
|
||||
if ($this->has('properties.active') && $this->input('properties.active') !== null) {
|
||||
return (bool) $this->input('properties.active');
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getPropertyBillable(): ?bool
|
||||
{
|
||||
if ($this->has('properties.billable') && $this->input('properties.billable') !== null) {
|
||||
return (bool) $this->input('properties.billable');
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getPropertyGroup(): TimeEntryAggregationType
|
||||
{
|
||||
return TimeEntryAggregationType::from($this->input('properties.group'));
|
||||
}
|
||||
|
||||
public function getPropertySubGroup(): TimeEntryAggregationType
|
||||
{
|
||||
return TimeEntryAggregationType::from($this->input('properties.sub_group'));
|
||||
}
|
||||
|
||||
public function getPropertyHistoryGroup(): TimeEntryAggregationTypeInterval
|
||||
{
|
||||
return TimeEntryAggregationTypeInterval::from($this->input('properties.history_group'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,21 +34,23 @@ class TimeEntryAggregateExportRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
// Data format of the export
|
||||
'format' => [
|
||||
'required',
|
||||
'string',
|
||||
Rule::enum(ExportFormat::class),
|
||||
],
|
||||
// Type of first grouping
|
||||
'group' => [
|
||||
'required',
|
||||
Rule::enum(TimeEntryAggregationType::class),
|
||||
],
|
||||
|
||||
// Type of second grouping
|
||||
'sub_group' => [
|
||||
'required',
|
||||
Rule::enum(TimeEntryAggregationType::class),
|
||||
],
|
||||
|
||||
// Type of grouping of the historic aggregation (time chart)
|
||||
'history_group' => [
|
||||
'required',
|
||||
'nullable',
|
||||
@@ -178,12 +180,22 @@ class TimeEntryAggregateExportRequest extends FormRequest
|
||||
|
||||
public function getStart(): Carbon
|
||||
{
|
||||
return Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $this->input('start'), 'UTC');
|
||||
$start = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $this->input('start'), 'UTC');
|
||||
if ($start === null) {
|
||||
throw new \LogicException('Start date validation is not working');
|
||||
}
|
||||
|
||||
return $start;
|
||||
}
|
||||
|
||||
public function getEnd(): Carbon
|
||||
{
|
||||
return Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $this->input('end'), 'UTC');
|
||||
$end = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $this->input('end'), 'UTC');
|
||||
if ($end === null) {
|
||||
throw new \LogicException('End date validation is not working');
|
||||
}
|
||||
|
||||
return $end;
|
||||
}
|
||||
|
||||
public function getFormatValue(): ExportFormat
|
||||
|
||||
@@ -32,12 +32,13 @@ class TimeEntryAggregateRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
// Type of first grouping
|
||||
'group' => [
|
||||
'nullable',
|
||||
'required_with:sub_group',
|
||||
Rule::enum(TimeEntryAggregationType::class),
|
||||
],
|
||||
|
||||
// Type of second grouping
|
||||
'sub_group' => [
|
||||
'nullable',
|
||||
Rule::enum(TimeEntryAggregationType::class),
|
||||
|
||||
@@ -28,6 +28,8 @@ class PersonalMembershipResource extends BaseResource
|
||||
'id' => $this->resource->organization->id,
|
||||
/** @var string $name Name of organization */
|
||||
'name' => $this->resource->organization->name,
|
||||
/** @var string $currency Currency code (ISO 4217) of organization */
|
||||
'currency' => $this->resource->organization->currency,
|
||||
],
|
||||
/** @var string $role Role */
|
||||
'role' => $this->resource->role,
|
||||
|
||||
@@ -45,6 +45,8 @@ class OrganizationResource extends BaseResource
|
||||
'billable_rate' => $this->showBillableRate ? $this->resource->billable_rate : null,
|
||||
/** @var bool $employees_can_see_billable_rates Can members of the organization with role "employee" see the billable rates */
|
||||
'employees_can_see_billable_rates' => $this->resource->employees_can_see_billable_rates,
|
||||
/** @var string $currency Currency code (ISO 4217) */
|
||||
'currency' => $this->resource->currency,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,8 @@ class ProjectResource extends BaseResource
|
||||
'estimated_time' => $this->resource->estimated_time,
|
||||
/** @var int $spent_time Spent time on this project in seconds (sum of the duration of all associated time entries, excl. still running time entries) */
|
||||
'spent_time' => $this->resource->spent_time,
|
||||
/** @var bool $is_public Whether the project is public */
|
||||
'is_public' => $this->resource->is_public,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,21 +34,35 @@ class DetailedReportResource extends BaseResource
|
||||
/** @var string|null $shareable_link Get link to access the report externally, not set if the report is private */
|
||||
'shareable_link' => $this->resource->getShareableLink(),
|
||||
'properties' => [
|
||||
/** @var string $group Type of first grouping */
|
||||
'group' => $this->resource->properties->group->value,
|
||||
/** @var string $sub_group Type of second grouping */
|
||||
'sub_group' => $this->resource->properties->subGroup->value,
|
||||
/** @var string|null $start Start date of the report */
|
||||
'start' => $this->resource->properties->start?->toIso8601ZuluString(),
|
||||
/** @var string|null $end End date of the report */
|
||||
'end' => $this->resource->properties->end?->toIso8601ZuluString(),
|
||||
/** @var string $history_group Type of grouping of the historic aggregation (time chart) */
|
||||
'history_group' => $this->resource->properties->historyGroup->value,
|
||||
/** @var string $start Start date of the report */
|
||||
'start' => $this->resource->properties->start->toIso8601ZuluString(),
|
||||
/** @var string $end End date of the report */
|
||||
'end' => $this->resource->properties->end->toIso8601ZuluString(),
|
||||
/** @var bool|null $active Whether the report is active */
|
||||
'active' => $this->resource->properties->active,
|
||||
/** @var array<string>|null $member_ids Filter by multiple member IDs, member IDs are OR combined */
|
||||
'member_ids' => $this->resource->properties->memberIds?->toArray(),
|
||||
/** @var bool|null $billable Filter by billable status */
|
||||
'billable' => $this->resource->properties->billable,
|
||||
/** @var array<string>|null $client_ids Filter by client IDs, client IDs are OR combined */
|
||||
'client_ids' => $this->resource->properties->clientIds?->toArray(),
|
||||
/** @var array<string>|null $project_ids Filter by project IDs, project IDs are OR combined */
|
||||
'project_ids' => $this->resource->properties->projectIds?->toArray(),
|
||||
/** @var array<string>|null $tags_ids Filter by tag IDs, tag IDs are OR combined */
|
||||
'tag_ids' => $this->resource->properties->tagIds?->toArray(),
|
||||
/** @var array<string>|null $task_ids Filter by task IDs, task IDs are OR combined */
|
||||
'task_ids' => $this->resource->properties->taskIds?->toArray(),
|
||||
],
|
||||
/** @var string $created_at Date when the report was created */
|
||||
'created_at' => $this->resource->created_at?->toIso8601ZuluString(),
|
||||
/** @var string $updated_at Date when the report was last updated */
|
||||
'updated_at' => $this->resource->updated_at?->toIso8601ZuluString(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
134
app/Http/Resources/V1/Report/DetailedWithDataReportResource.php
Normal file
134
app/Http/Resources/V1/Report/DetailedWithDataReportResource.php
Normal file
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Resources\V1\Report;
|
||||
|
||||
use App\Http\Resources\V1\BaseResource;
|
||||
use App\Models\Report;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* @property Report $resource
|
||||
*
|
||||
* @phpstan-type Data array{
|
||||
* grouped_type: string|null,
|
||||
* grouped_data: null|array<array{
|
||||
* key: string|null,
|
||||
* description: string|null,
|
||||
* color: string|null,
|
||||
* seconds: int,
|
||||
* cost: int,
|
||||
* grouped_type: string|null,
|
||||
* grouped_data: null|array<array{
|
||||
* key: string|null,
|
||||
* description: string|null,
|
||||
* color: string|null,
|
||||
* seconds: int,
|
||||
* cost: int,
|
||||
* grouped_type: null,
|
||||
* grouped_data: null
|
||||
* }>
|
||||
* }>,
|
||||
* seconds: int,
|
||||
* cost: int
|
||||
* }
|
||||
*/
|
||||
class DetailedWithDataReportResource extends BaseResource
|
||||
{
|
||||
/**
|
||||
* @var Data
|
||||
*/
|
||||
private array $data;
|
||||
|
||||
/**
|
||||
* @var Data
|
||||
*/
|
||||
private array $historyData;
|
||||
|
||||
/**
|
||||
* @param Data $data
|
||||
* @param Data $historyData
|
||||
*/
|
||||
public function __construct(Report $resource, array $data, array $historyData)
|
||||
{
|
||||
parent::__construct($resource);
|
||||
$this->data = $data;
|
||||
$this->historyData = $historyData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @return array<string, string|bool|int|null|Data|array<string, string|bool|int|null|array<int, string>>>
|
||||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return [
|
||||
/** @var string $name Name */
|
||||
'name' => $this->resource->name,
|
||||
/** @var string|null $email Description */
|
||||
'description' => $this->resource->description,
|
||||
/** @var string|null $public_until Date until the report is public */
|
||||
'public_until' => $this->resource->public_until?->toIso8601ZuluString(),
|
||||
/** @var string $currency Currency code (ISO 4217) */
|
||||
'currency' => $this->resource->organization->currency,
|
||||
'properties' => [
|
||||
/** @var string $group Type of first grouping */
|
||||
'group' => $this->resource->properties->group->value,
|
||||
/** @var string $sub_group Type of second grouping */
|
||||
'sub_group' => $this->resource->properties->subGroup->value,
|
||||
/** @var string $history_group Type of grouping of the historic aggregation (time chart) */
|
||||
'history_group' => $this->resource->properties->historyGroup->value,
|
||||
/** @var string $start Start date of the report */
|
||||
'start' => $this->resource->properties->start->toIso8601ZuluString(),
|
||||
/** @var string $end End date of the report */
|
||||
'end' => $this->resource->properties->end->toIso8601ZuluString(),
|
||||
],
|
||||
/** @var array{
|
||||
* grouped_type: string|null,
|
||||
* grouped_data: null|array<array{
|
||||
* key: string|null,
|
||||
* description: string|null,
|
||||
* seconds: int,
|
||||
* cost: int,
|
||||
* grouped_type: string|null,
|
||||
* grouped_data: null|array<array{
|
||||
* key: string|null,
|
||||
* description: string|null,
|
||||
* seconds: int,
|
||||
* cost: int,
|
||||
* grouped_type: null,
|
||||
* grouped_data: null
|
||||
* }>
|
||||
* }>,
|
||||
* seconds: int,
|
||||
* cost: int
|
||||
* } $data Aggregated data
|
||||
*/
|
||||
'data' => $this->data,
|
||||
/** @var array{
|
||||
* grouped_type: string|null,
|
||||
* grouped_data: null|array<array{
|
||||
* key: string|null,
|
||||
* description: string|null,
|
||||
* seconds: int,
|
||||
* cost: int,
|
||||
* grouped_type: string|null,
|
||||
* grouped_data: null|array<array{
|
||||
* key: string|null,
|
||||
* description: string|null,
|
||||
* seconds: int,
|
||||
* cost: int,
|
||||
* grouped_type: null,
|
||||
* grouped_data: null
|
||||
* }>
|
||||
* }>,
|
||||
* seconds: int,
|
||||
* cost: int
|
||||
* } $history_data Historic aggregated data
|
||||
*/
|
||||
'history_data' => $this->historyData,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,10 @@ class ReportResource extends BaseResource
|
||||
'public_until' => $this->resource->public_until?->toIso8601ZuluString(),
|
||||
/** @var string|null $shareable_link Get link to access the report externally, not set if the report is private */
|
||||
'shareable_link' => $this->resource->getShareableLink(),
|
||||
/** @var string $created_at Date when the report was created */
|
||||
'created_at' => $this->resource->created_at?->toIso8601ZuluString(),
|
||||
/** @var string $updated_at Date when the report was last updated */
|
||||
'updated_at' => $this->resource->updated_at?->toIso8601ZuluString(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user