Refactor addressee history management

This commit refactors the management of addressees history in the ticketing system. Instead of individual addition and removal events for addressees, a new event 'addressees_state' is introduced to capture the state of addressees at any given point in the history. The structure and logic of normalized tickets have been adjusted accordingly.
This commit is contained in:
Julien Fastré 2024-05-31 23:43:32 +02:00
parent d2a61ce69b
commit 498572b96e
Signed by: julienfastre
GPG Key ID: BDE2190974723FCB
5 changed files with 95 additions and 50 deletions

View File

@ -64,13 +64,18 @@ export interface AddresseeHistory {
updatedAt: DateTime|null,
}
export interface AddresseeState {
addressees: UserGroupOrUser[],
}
interface AddPersonEvent extends TicketHistory<"add_person", PersonHistory> {};
interface AddCommentEvent extends TicketHistory<"add_comment", Comment> {};
interface SetMotiveEvent extends TicketHistory<"set_motive", MotiveHistory> {};
interface AddAddressee extends TicketHistory<"add_addressee", AddresseeHistory> {};
interface RemoveAddressee extends TicketHistory<"remove_addressee", AddresseeHistory> {};
//interface AddAddressee extends TicketHistory<"add_addressee", AddresseeHistory> {};
//interface RemoveAddressee extends TicketHistory<"remove_addressee", AddresseeHistory> {};
interface AddresseesStateEvent extends TicketHistory<"addressees_state", AddresseeState> {};
type TicketHistoryLine = AddPersonEvent | AddCommentEvent | SetMotiveEvent | AddAddressee | RemoveAddressee;
type TicketHistoryLine = AddPersonEvent | AddCommentEvent | SetMotiveEvent | /*AddAddressee | RemoveAddressee | */ AddresseesStateEvent;
export interface Ticket {
type: "ticket_ticket",

View File

@ -100,7 +100,7 @@
: (activeTab = 'add_addressee')
"
>
<i :class="actionIcons['add_addressee']"></i>
<i :class="actionIcons['addressees_state']"></i>
{{ $t("add_addressee.title") }}
</button>
</li>

View File

@ -4,51 +4,33 @@
v-for="history_line in history"
:key="history.indexOf(history_line)"
>
<template v-if="!Array.isArray(history_line)">
<div class="card-header">
<i :class="`${actionIcons[history_line.event_type]} me-1`"></i>
<span class="fw-bold fst-italic mx-1">
{{ formatDate(history_line.at) }}
</span>
<span class="badge bg-white text-black mx-1">
{{ history_line.by.username }}
</span>
</div>
<div class="card-body row">
<ticket-history-person-component
:personHistory="history_line.data"
v-if="history_line.event_type == 'add_person'"
/>
<ticket-history-motive-component
:motiveHistory="history_line.data"
v-else-if="history_line.event_type == 'set_motive'"
/>
<ticket-history-comment-component
:commentHistory="history_line.data"
v-else-if="history_line.event_type == 'add_comment'"
/>
</div>
</template>
<template v-else>
<div class="card-header">
<i class="fa fa-paper-plane me-1"></i>
<span class="fw-bold fst-italic mx-1">
{{ formatDate(history_line[0].at) }}
</span>
<span class="badge bg-white text-black mx-1">
{{ history_line[0].by.username }}
</span>
</div>
<div class="card-body row">
<ticket-history-addressee-component
:addressees="
history_line
.map((line) => line.data)
.map((data) => data.addressee)
"
/>
</div>
</template>
<div class="card-header">
<i :class="`${actionIcons[history_line.event_type]} me-1`"></i>
<span class="fw-bold fst-italic mx-1">
{{ formatDate(history_line.at) }}
</span>
<span class="badge bg-white text-black mx-1">
{{ history_line.by.username }}
</span>
</div>
<div class="card-body row">
<ticket-history-person-component
:personHistory="history_line.data"
v-if="history_line.event_type == 'add_person'"
/>
<ticket-history-motive-component
:motiveHistory="history_line.data"
v-else-if="history_line.event_type == 'set_motive'"
/>
<ticket-history-comment-component
:commentHistory="history_line.data"
v-else-if="history_line.event_type == 'add_comment'"
/>
<ticket-history-addressee-component
:addressees="history_line.data.addressees"
v-else-if="history_line.event_type == 'addressees_state'"
/>
</div>
</div>
</template>

View File

@ -15,7 +15,8 @@ export const moduleTicket: Module<State, RootState> = {
add_person: "fa fa-eyedropper",
add_comment: "fa fa-comment",
set_motive: "fa fa-paint-brush",
add_addressee: "fa fa-paper-plane",
//add_addressee: "fa fa-paper-plane",
addressees_state: "fa fa-paper-plane",
},
toto: "toto",
}),

View File

@ -11,6 +11,8 @@ declare(strict_types=1);
namespace Chill\TicketBundle\Serializer\Normalizer;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\UserGroup;
use Chill\TicketBundle\Entity\AddresseeHistory;
use Chill\TicketBundle\Entity\Comment;
use Chill\TicketBundle\Entity\MotiveHistory;
@ -82,6 +84,7 @@ final class TicketNormalizer implements NormalizerInterface, NormalizerAwareInte
],
$ticket->getComments()->toArray(),
),
/*
...array_map(
fn (AddresseeHistory $history) => [
'event_type' => 'add_addressee',
@ -100,6 +103,8 @@ final class TicketNormalizer implements NormalizerInterface, NormalizerAwareInte
],
$ticket->getAddresseeHistories()->filter(fn (AddresseeHistory $history) => null !== $history->getEndDate())->toArray()
),
*/
...$this->addresseesStates($ticket),
];
usort(
@ -119,4 +124,56 @@ final class TicketNormalizer implements NormalizerInterface, NormalizerAwareInte
$events
);
}
private function addresseesStates(Ticket $ticket): array
{
/** @var array{string, array{added: list<AddresseeHistory>, removed: list<AddresseeHistory>}} $changes */
$changes = [];
$dateFormat = 'Y-m-d-m-Y-H-i-s';
foreach ($ticket->getAddresseeHistories() as $history) {
$changes[$history->getStartDate()->format($dateFormat)]['added'][] = $history;
}
foreach ($ticket->getAddresseeHistories() as $history) {
if (null !== $history->getEndDate()) {
$changes[$history->getEndDate()->format($dateFormat)]['removed'][] = $history;
}
}
ksort($changes);
$currents = [];
$steps = [];
foreach ($changes as $change) {
$historiesAdded = $change['added'] ?? [];
$historiesRemoved = $change['removed'] ?? [];
if (0 < count($historiesAdded)) {
$at = $historiesAdded[0]->getStartDate();
$by = $historiesAdded[0]->getCreatedBy();
} elseif (0 < count($historiesRemoved)) {
$at = $historiesRemoved[0]->getStartDate();
$by = $historiesRemoved[0]->getRemovedBy();
} else {
throw new \LogicException('it should have at least one history');
}
$removed = array_map(fn (AddresseeHistory $history) => $history->getAddressee(), $historiesRemoved);
$currents = array_filter($currents, fn (User|UserGroup $a) => !in_array($a, $removed, true));
foreach ($historiesAdded as $history) {
$currents[] = $history->getAddressee();
}
$steps[] = [
'event_type' => 'addressees_state',
'at' => $at,
'by' => $by,
'data' => [
'addressees' => array_values($currents),
],
];
}
return $steps;
}
}