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, updatedAt: DateTime|null,
} }
export interface AddresseeState {
addressees: UserGroupOrUser[],
}
interface AddPersonEvent extends TicketHistory<"add_person", PersonHistory> {}; interface AddPersonEvent extends TicketHistory<"add_person", PersonHistory> {};
interface AddCommentEvent extends TicketHistory<"add_comment", Comment> {}; interface AddCommentEvent extends TicketHistory<"add_comment", Comment> {};
interface SetMotiveEvent extends TicketHistory<"set_motive", MotiveHistory> {}; interface SetMotiveEvent extends TicketHistory<"set_motive", MotiveHistory> {};
interface AddAddressee extends TicketHistory<"add_addressee", AddresseeHistory> {}; //interface AddAddressee extends TicketHistory<"add_addressee", AddresseeHistory> {};
interface RemoveAddressee extends TicketHistory<"remove_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 { export interface Ticket {
type: "ticket_ticket", type: "ticket_ticket",

View File

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

View File

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

View File

@ -15,7 +15,8 @@ export const moduleTicket: Module<State, RootState> = {
add_person: "fa fa-eyedropper", add_person: "fa fa-eyedropper",
add_comment: "fa fa-comment", add_comment: "fa fa-comment",
set_motive: "fa fa-paint-brush", 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", toto: "toto",
}), }),

View File

@ -11,6 +11,8 @@ declare(strict_types=1);
namespace Chill\TicketBundle\Serializer\Normalizer; namespace Chill\TicketBundle\Serializer\Normalizer;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\UserGroup;
use Chill\TicketBundle\Entity\AddresseeHistory; use Chill\TicketBundle\Entity\AddresseeHistory;
use Chill\TicketBundle\Entity\Comment; use Chill\TicketBundle\Entity\Comment;
use Chill\TicketBundle\Entity\MotiveHistory; use Chill\TicketBundle\Entity\MotiveHistory;
@ -82,6 +84,7 @@ final class TicketNormalizer implements NormalizerInterface, NormalizerAwareInte
], ],
$ticket->getComments()->toArray(), $ticket->getComments()->toArray(),
), ),
/*
...array_map( ...array_map(
fn (AddresseeHistory $history) => [ fn (AddresseeHistory $history) => [
'event_type' => 'add_addressee', 'event_type' => 'add_addressee',
@ -100,6 +103,8 @@ final class TicketNormalizer implements NormalizerInterface, NormalizerAwareInte
], ],
$ticket->getAddresseeHistories()->filter(fn (AddresseeHistory $history) => null !== $history->getEndDate())->toArray() $ticket->getAddresseeHistories()->filter(fn (AddresseeHistory $history) => null !== $history->getEndDate())->toArray()
), ),
*/
...$this->addresseesStates($ticket),
]; ];
usort( usort(
@ -119,4 +124,56 @@ final class TicketNormalizer implements NormalizerInterface, NormalizerAwareInte
$events $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;
}
} }