fixed missing features
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Tickets;
|
||||
|
||||
use App\Models\Ticket;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class BuildProjectTicketUpdateAttributes
|
||||
{
|
||||
/**
|
||||
* @param array<string, mixed> $validated
|
||||
* @return array{
|
||||
* acceptance_criteria: string|null,
|
||||
* assignee_user_id: int|null,
|
||||
* author_user_id: int|null,
|
||||
* blocked_comment: string|null,
|
||||
* description: string|null,
|
||||
* is_blocked: bool,
|
||||
* parent_ticket_id: int|null,
|
||||
* story_points: int|null,
|
||||
* ticket_priority_id: int,
|
||||
* ticket_type_id: int,
|
||||
* title: string
|
||||
* }
|
||||
*/
|
||||
public function handle(Ticket $ticket, array $validated): array
|
||||
{
|
||||
return [
|
||||
'acceptance_criteria' => Arr::get($validated, 'acceptance_criteria'),
|
||||
'assignee_user_id' => Arr::exists($validated, 'assignee_user_id')
|
||||
? Arr::get($validated, 'assignee_user_id')
|
||||
: $ticket->assignee_user_id,
|
||||
'author_user_id' => Arr::exists($validated, 'author_user_id')
|
||||
? Arr::get($validated, 'author_user_id')
|
||||
: $ticket->author_user_id,
|
||||
'blocked_comment' => Arr::get($validated, 'blocked_comment'),
|
||||
'description' => Arr::get($validated, 'description'),
|
||||
'is_blocked' => Arr::get($validated, 'is_blocked', false),
|
||||
'parent_ticket_id' => Arr::get($validated, 'parent_ticket_id'),
|
||||
'story_points' => Arr::exists($validated, 'story_points')
|
||||
? Arr::get($validated, 'story_points')
|
||||
: $ticket->story_points,
|
||||
'ticket_priority_id' => Arr::get($validated, 'ticket_priority_id'),
|
||||
'ticket_type_id' => Arr::get($validated, 'ticket_type_id'),
|
||||
'title' => Arr::get($validated, 'title'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Actions\Tickets;
|
||||
|
||||
use App\Enums\TicketWorklogEntryType;
|
||||
use App\Models\Project;
|
||||
use App\Models\Ticket;
|
||||
use App\Models\TicketStatus;
|
||||
@@ -56,7 +57,7 @@ class CreateProjectTicket
|
||||
$this->createTicketWorklogEntry->handle(
|
||||
$ticket,
|
||||
$actor,
|
||||
'created',
|
||||
TicketWorklogEntryType::Created,
|
||||
"Ticket was created in {$ticketStatus->name}.",
|
||||
[
|
||||
'from' => null,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Actions\Tickets;
|
||||
|
||||
use App\Enums\TicketWorklogEntryType;
|
||||
use App\Models\Ticket;
|
||||
use App\Models\TicketWorklogEntry;
|
||||
use App\Models\User;
|
||||
@@ -14,7 +15,7 @@ class CreateTicketWorklogEntry
|
||||
public function handle(
|
||||
Ticket $ticket,
|
||||
?User $actor,
|
||||
string $entryType,
|
||||
TicketWorklogEntryType $entryType,
|
||||
string $summary,
|
||||
?array $changes = null,
|
||||
): TicketWorklogEntry {
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Tickets;
|
||||
|
||||
use App\Models\Ticket;
|
||||
use App\Models\TicketFieldDefinition;
|
||||
use App\Models\TicketFieldValue;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class SyncProjectTicketFieldValues
|
||||
{
|
||||
/**
|
||||
* @param Collection<int, TicketFieldDefinition> $fieldDefinitions
|
||||
* @param Collection<int, TicketFieldValue> $existingFieldValues
|
||||
* @param array<int, array{
|
||||
* ticket_field_definition_id: int,
|
||||
* value_number?: float|int|string|null,
|
||||
* value_user_id?: int|string|null
|
||||
* }> $fieldValueAttributes
|
||||
* @return array{
|
||||
* changes: array<int, array<string, mixed>>,
|
||||
* summary_labels: array<int, string>
|
||||
* }
|
||||
*/
|
||||
public function handle(
|
||||
Ticket $ticket,
|
||||
Collection $fieldDefinitions,
|
||||
Collection $existingFieldValues,
|
||||
array $fieldValueAttributes,
|
||||
): array {
|
||||
$changes = [];
|
||||
$summaryLabels = [];
|
||||
|
||||
foreach ($fieldValueAttributes as $fieldValueAttribute) {
|
||||
$fieldDefinition = $fieldDefinitions->get((int) $fieldValueAttribute['ticket_field_definition_id']);
|
||||
|
||||
if ($fieldDefinition === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$existingFieldValue = $existingFieldValues->get($fieldDefinition->id);
|
||||
|
||||
if ($fieldDefinition->field_type === 'user') {
|
||||
$this->syncUserFieldValue(
|
||||
$changes,
|
||||
$existingFieldValue,
|
||||
$fieldDefinition,
|
||||
$fieldValueAttribute,
|
||||
$summaryLabels,
|
||||
$ticket,
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->syncNumberFieldValue(
|
||||
$changes,
|
||||
$existingFieldValue,
|
||||
$fieldDefinition,
|
||||
$fieldValueAttribute,
|
||||
$summaryLabels,
|
||||
$ticket,
|
||||
);
|
||||
}
|
||||
|
||||
return [
|
||||
'changes' => $changes,
|
||||
'summary_labels' => $summaryLabels,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, array<string, mixed>> $changes
|
||||
* @param array{value_user_id?: int|string|null} $fieldValueAttribute
|
||||
* @param array<int, string> $summaryLabels
|
||||
*/
|
||||
private function syncUserFieldValue(
|
||||
array &$changes,
|
||||
?TicketFieldValue $existingFieldValue,
|
||||
TicketFieldDefinition $fieldDefinition,
|
||||
array $fieldValueAttribute,
|
||||
array &$summaryLabels,
|
||||
Ticket $ticket,
|
||||
): void {
|
||||
$newUserId = $fieldValueAttribute['value_user_id'] ?? null;
|
||||
$newUserId = $newUserId === null || $newUserId === '' ? null : (int) $newUserId;
|
||||
|
||||
if ($existingFieldValue?->value_user_id === $newUserId) {
|
||||
return;
|
||||
}
|
||||
|
||||
$oldUserName = $existingFieldValue?->userValue?->name;
|
||||
$newUserName = $newUserId === null ? null : User::query()->find($newUserId)?->name;
|
||||
|
||||
$changes[$fieldDefinition->id] = [
|
||||
'field' => $fieldDefinition->label,
|
||||
'from' => $oldUserName,
|
||||
'to' => $newUserName,
|
||||
];
|
||||
$summaryLabels[] = "{$fieldDefinition->label} field";
|
||||
|
||||
if ($newUserId === null) {
|
||||
$existingFieldValue?->delete();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$ticket->fieldValues()->updateOrCreate(
|
||||
[
|
||||
'ticket_field_definition_id' => $fieldDefinition->id,
|
||||
],
|
||||
[
|
||||
'value_number' => null,
|
||||
'value_user_id' => $newUserId,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, array<string, mixed>> $changes
|
||||
* @param array{value_number?: float|int|string|null} $fieldValueAttribute
|
||||
* @param array<int, string> $summaryLabels
|
||||
*/
|
||||
private function syncNumberFieldValue(
|
||||
array &$changes,
|
||||
?TicketFieldValue $existingFieldValue,
|
||||
TicketFieldDefinition $fieldDefinition,
|
||||
array $fieldValueAttribute,
|
||||
array &$summaryLabels,
|
||||
Ticket $ticket,
|
||||
): void {
|
||||
$newNumber = $fieldValueAttribute['value_number'] ?? null;
|
||||
$newNumber = $newNumber === null || $newNumber === '' ? null : (float) $newNumber;
|
||||
$oldNumber = $existingFieldValue?->value_number;
|
||||
|
||||
if ($oldNumber === $newNumber) {
|
||||
return;
|
||||
}
|
||||
|
||||
$changes[$fieldDefinition->id] = [
|
||||
'field' => $fieldDefinition->label,
|
||||
'from' => $this->formatNumber($oldNumber),
|
||||
'to' => $this->formatNumber($newNumber),
|
||||
];
|
||||
$summaryLabels[] = "{$fieldDefinition->label} field";
|
||||
|
||||
if ($newNumber === null) {
|
||||
$existingFieldValue?->delete();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$ticket->fieldValues()->updateOrCreate(
|
||||
[
|
||||
'ticket_field_definition_id' => $fieldDefinition->id,
|
||||
],
|
||||
[
|
||||
'value_number' => $newNumber,
|
||||
'value_user_id' => null,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
private function formatNumber(?float $value): ?string
|
||||
{
|
||||
if ($value === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return rtrim(rtrim(number_format($value, 2, '.', ''), '0'), '.');
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Actions\Tickets;
|
||||
|
||||
use App\Enums\TicketWorklogEntryType;
|
||||
use App\Models\Ticket;
|
||||
use App\Models\TicketFieldDefinition;
|
||||
use App\Models\TicketFieldValue;
|
||||
@@ -13,6 +14,7 @@ class UpdateProjectTicket
|
||||
{
|
||||
public function __construct(
|
||||
private readonly CreateTicketWorklogEntry $createTicketWorklogEntry,
|
||||
private readonly SyncProjectTicketFieldValues $syncProjectTicketFieldValues,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -179,36 +181,19 @@ class UpdateProjectTicket
|
||||
$ticket->save();
|
||||
}
|
||||
|
||||
foreach ($fieldValueAttributes as $fieldValueAttribute) {
|
||||
$fieldDefinition = $fieldDefinitions->get((int) $fieldValueAttribute['ticket_field_definition_id']);
|
||||
$fieldValueChangeSet = $this->syncProjectTicketFieldValues->handle(
|
||||
$ticket,
|
||||
$fieldDefinitions,
|
||||
$existingFieldValues,
|
||||
$fieldValueAttributes,
|
||||
);
|
||||
|
||||
if ($fieldDefinition === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$existingFieldValue = $existingFieldValues->get($fieldDefinition->id);
|
||||
|
||||
if ($fieldDefinition->field_type === 'user') {
|
||||
$this->syncUserFieldValue(
|
||||
$changes,
|
||||
$existingFieldValue,
|
||||
$fieldDefinition,
|
||||
$fieldValueAttribute,
|
||||
$summaryLabels,
|
||||
$ticket,
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->syncNumberFieldValue(
|
||||
$changes,
|
||||
$existingFieldValue,
|
||||
$fieldDefinition,
|
||||
$fieldValueAttribute,
|
||||
$summaryLabels,
|
||||
$ticket,
|
||||
);
|
||||
if ($fieldValueChangeSet['changes'] !== []) {
|
||||
$changes['field_values'] = $fieldValueChangeSet['changes'];
|
||||
$summaryLabels = [
|
||||
...$summaryLabels,
|
||||
...$fieldValueChangeSet['summary_labels'],
|
||||
];
|
||||
}
|
||||
|
||||
if ($summaryLabels === []) {
|
||||
@@ -218,7 +203,7 @@ class UpdateProjectTicket
|
||||
$this->createTicketWorklogEntry->handle(
|
||||
$ticket->fresh(),
|
||||
$actor,
|
||||
'updated',
|
||||
TicketWorklogEntryType::Updated,
|
||||
$this->buildSummary($summaryLabels),
|
||||
$changes,
|
||||
);
|
||||
@@ -273,98 +258,6 @@ class UpdateProjectTicket
|
||||
$summaryLabels[] = $summaryLabel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $changes
|
||||
* @param array{value_user_id?: int|string|null} $fieldValueAttribute
|
||||
* @param array<int, string> $summaryLabels
|
||||
*/
|
||||
private function syncUserFieldValue(
|
||||
array &$changes,
|
||||
?TicketFieldValue $existingFieldValue,
|
||||
TicketFieldDefinition $fieldDefinition,
|
||||
array $fieldValueAttribute,
|
||||
array &$summaryLabels,
|
||||
Ticket $ticket,
|
||||
): void {
|
||||
$newUserId = $fieldValueAttribute['value_user_id'] ?? null;
|
||||
$newUserId = $newUserId === null || $newUserId === '' ? null : (int) $newUserId;
|
||||
|
||||
if ($existingFieldValue?->value_user_id === $newUserId) {
|
||||
return;
|
||||
}
|
||||
|
||||
$oldUserName = $existingFieldValue?->userValue?->name;
|
||||
$newUserName = $newUserId === null ? null : User::query()->find($newUserId)?->name;
|
||||
|
||||
$changes['field_values'][$fieldDefinition->id] = [
|
||||
'field' => $fieldDefinition->label,
|
||||
'from' => $oldUserName,
|
||||
'to' => $newUserName,
|
||||
];
|
||||
$summaryLabels[] = "{$fieldDefinition->label} field";
|
||||
|
||||
if ($newUserId === null) {
|
||||
$existingFieldValue?->delete();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$ticket->fieldValues()->updateOrCreate(
|
||||
[
|
||||
'ticket_field_definition_id' => $fieldDefinition->id,
|
||||
],
|
||||
[
|
||||
'value_number' => null,
|
||||
'value_user_id' => $newUserId,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $changes
|
||||
* @param array{value_number?: float|int|string|null} $fieldValueAttribute
|
||||
* @param array<int, string> $summaryLabels
|
||||
*/
|
||||
private function syncNumberFieldValue(
|
||||
array &$changes,
|
||||
?TicketFieldValue $existingFieldValue,
|
||||
TicketFieldDefinition $fieldDefinition,
|
||||
array $fieldValueAttribute,
|
||||
array &$summaryLabels,
|
||||
Ticket $ticket,
|
||||
): void {
|
||||
$newNumber = $fieldValueAttribute['value_number'] ?? null;
|
||||
$newNumber = $newNumber === null || $newNumber === '' ? null : (float) $newNumber;
|
||||
$oldNumber = $existingFieldValue?->value_number;
|
||||
|
||||
if ($oldNumber === $newNumber) {
|
||||
return;
|
||||
}
|
||||
|
||||
$changes['field_values'][$fieldDefinition->id] = [
|
||||
'field' => $fieldDefinition->label,
|
||||
'from' => $this->formatNumber($oldNumber),
|
||||
'to' => $this->formatNumber($newNumber),
|
||||
];
|
||||
$summaryLabels[] = "{$fieldDefinition->label} field";
|
||||
|
||||
if ($newNumber === null) {
|
||||
$existingFieldValue?->delete();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$ticket->fieldValues()->updateOrCreate(
|
||||
[
|
||||
'ticket_field_definition_id' => $fieldDefinition->id,
|
||||
],
|
||||
[
|
||||
'value_number' => $newNumber,
|
||||
'value_user_id' => null,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, string> $summaryLabels
|
||||
*/
|
||||
@@ -386,13 +279,4 @@ class UpdateProjectTicket
|
||||
|
||||
return 'Updated '.$uniqueLabels->implode(', ').', and '.$lastLabel.'.';
|
||||
}
|
||||
|
||||
private function formatNumber(?float $value): ?string
|
||||
{
|
||||
if ($value === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return rtrim(rtrim(number_format($value, 2, '.', ''), '0'), '.');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user