This commit is contained in:
Dennis Eichhorn 2024-04-07 17:31:42 +00:00
parent 8329c8e773
commit a4d02a8411
12 changed files with 40 additions and 376 deletions

View File

@ -74,8 +74,8 @@
"from": "Support",
"permission": { "permission": 2, "category": null, "element": null },
"parent": 1002901001,
"children": [
]
"children": [],
"status": 3
},
{
"id": 1002901301,

View File

@ -49,31 +49,5 @@
"foreignKey": "support_app_id"
}
}
},
"support_ticket_element": {
"name": "support_ticket_element",
"fields": {
"support_ticket_element_id": {
"name": "support_ticket_element_id",
"type": "INT",
"null": false,
"primary": true,
"autoincrement": true
},
"support_ticket_element_task_element": {
"name": "support_ticket_element_task_element",
"type": "INT",
"null": false,
"foreignTable": "task_element",
"foreignKey": "task_element_id"
},
"support_ticket_element_ticket": {
"name": "support_ticket_element_ticket",
"type": "INT",
"null": false,
"foreignTable": "support_ticket",
"foreignKey": "support_ticket_id"
}
}
}
}

View File

@ -22,6 +22,7 @@ return [
[
'dest' => '\Modules\Support\Controller\BackendController:viewSupportList',
'verb' => RouteVerb::GET,
'active' => true,
'permission' => [
'module' => BackendController::NAME,
'type' => PermissionType::READ,
@ -29,10 +30,11 @@ return [
],
],
],
'^/support/ticket(\?.*$|$)' => [
'^/support/ticket/view(\?.*$|$)' => [
[
'dest' => '\Modules\Support\Controller\BackendController:viewSupportTicket',
'verb' => RouteVerb::GET,
'active' => true,
'permission' => [
'module' => BackendController::NAME,
'type' => PermissionType::READ,
@ -44,6 +46,7 @@ return [
[
'dest' => '\Modules\Support\Controller\BackendController:viewSupportCreate',
'verb' => RouteVerb::GET,
'active' => true,
'permission' => [
'module' => BackendController::NAME,
'type' => PermissionType::CREATE,
@ -51,10 +54,11 @@ return [
],
],
],
'^/support/analysis(\?.*$|$)' => [
'^/support/analysis/dashboard(\?.*$|$)' => [
[
'dest' => '\Modules\Support\Controller\BackendController:viewSupportAnalysis',
'verb' => RouteVerb::GET,
'active' => true,
'permission' => [
'module' => BackendController::NAME,
'type' => PermissionType::READ,
@ -66,6 +70,7 @@ return [
[
'dest' => '\Modules\Support\Controller\BackendController:viewSupportSettings',
'verb' => RouteVerb::GET,
'active' => false,
'permission' => [
'module' => BackendController::NAME,
'type' => PermissionType::READ,

View File

@ -22,9 +22,8 @@ use Modules\Support\Models\SettingsEnum;
use Modules\Support\Models\SupportApp;
use Modules\Support\Models\SupportAppMapper;
use Modules\Support\Models\Ticket;
use Modules\Support\Models\TicketElement;
use Modules\Support\Models\TicketElementMapper;
use Modules\Support\Models\TicketMapper;
use Modules\Tasks\Models\TaskElementMapper;
use Modules\Tasks\Models\TaskMapper;
use Modules\Tasks\Models\TaskStatus;
use Modules\Tasks\Models\TaskType;
@ -232,7 +231,7 @@ final class ApiController extends Controller
*/
private function createTicketFromRequest(RequestAbstract $request) : Ticket
{
$request->setData('redirect', 'support/ticket?for={$id}');
$request->setData('redirect', 'support/ticket/view?for={$id}');
$task = $this->app->moduleManager->get('Tasks')->createTaskFromRequest($request);
$task->type = TaskType::HIDDEN;
@ -351,70 +350,32 @@ final class ApiController extends Controller
return;
}
// @question Consider to use the apiTaskElementCreate() function
/** @var \Modules\Support\Models\Ticket $ticket */
$ticket = TicketMapper::get()
->with('task')
->where('id', (int) ($request->getData('ticket')))
->execute();
$element = $this->createTicketElementFromRequest($request, $ticket);
$element = $this->app->moduleManager->get('Tasks')->createTaskElementFromRequest($request, $ticket->task);
$old = clone $ticket->task;
$ticket->task->status = $element->taskElement->status;
$ticket->task->priority = $element->taskElement->priority;
$ticket->task->due = $element->taskElement->due;
$ticket->task->status = $element->status;
$ticket->task->priority = $element->priority;
$ticket->task->due = $element->due;
$this->createModel($request->header->account, $element, TicketElementMapper::class, 'ticket_element', $request->getOrigin());
$this->createModel($request->header->account, $element, TaskElementMapper::class, 'ticket_element', $request->getOrigin());
$this->updateModel($request->header->account, $old, $ticket->task, TaskMapper::class, 'ticket', $request->getOrigin());
$ticket->task->taskElements[] = $element->taskElement;
$ticket->task->taskElements[] = $element;
$this->notifyEmail($ticket, $response->header->l11n->language);
$this->createStandardCreateResponse($request, $response, $element);
}
/**
* Method to create ticket element from request.
*
* @param RequestAbstract $request Request
* @param Ticket $ticket Ticket
*
* @return TicketElement Returns the ticket created from the request
*
* @since 1.0.0
*/
private function createTicketElementFromRequest(RequestAbstract $request, Ticket $ticket) : TicketElement
{
$taskElement = $this->app->moduleManager->get('Tasks')->createTaskElementFromRequest($request, $ticket->task);
$ticketElement = new TicketElement($taskElement);
$ticketElement->ticket = $ticket->id;
return $ticketElement;
}
/**
* Api method to get a ticket
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
* @param array $data Generic data
*
* @return void
*
* @api
*
* @since 1.0.0
*/
public function apiTicketElementGet(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void
{
/** @var \Modules\Support\Models\TicketElement $ticket */
$ticket = TicketElementMapper::get()->where('id', (int) $request->getData('id'))->execute();
$this->createStandardReturnResponse($request, $response, $ticket);
}
/**
* Api method to update a ticket
*
@ -430,14 +391,12 @@ final class ApiController extends Controller
*/
public function apiTicketElementSet(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void
{
/** @var \Modules\Support\Models\TicketElement $old */
$old = TicketElementMapper::get()->where('id', (int) $request->getData('id'))->execute();
$new = $this->updateTicketElementFromRequest($request, $response, clone $old);
$this->updateModel($request->header->account, $old, $new, TicketElementMapper::class, 'ticket_element', $request->getOrigin());
$this->app->moduleManager->get('Tasks')->apiTaskElementSet($request, $response);
$new = $response->getData($request->uri->__toString())['response'];
$ticket = TicketMapper::get()
->with('task')
->where('task', $new->taskElement->task)
->where('task', $new->task)
->execute();
$this->notifyEmail($ticket, $response->header->l11n->language);
@ -446,23 +405,6 @@ final class ApiController extends Controller
$this->createStandardUpdateResponse($request, $response, $new);
}
/**
* Method to update an ticket element from a request
*
* @param RequestAbstract $request Request
*
* @return TicketElement Returns the updated ticket element from the request
*
* @since 1.0.0
*/
private function updateTicketElementFromRequest(RequestAbstract $request, ResponseAbstract $response, TicketElement $new) : TicketElement
{
$request->setData('id', $new->taskElement->task, true);
$this->app->moduleManager->get('Tasks')->apiTaskElementSet($request, $response);
return $new;
}
/**
* Api method to create a category
*

View File

@ -17,7 +17,7 @@ namespace Modules\Support\Models;
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
/**
* Mapper class.
* SupportApp mapper class.
*
* @package Modules\Support\Models
* @license OMS License 2.0

View File

@ -51,14 +51,6 @@ class Ticket
*/
public SupportApp $app;
/**
* Ticket elements.
*
* @var TicketElement[]
* @since 1.0.0
*/
public array $ticketElements = [];
/**
* Constructor.
*
@ -73,84 +65,6 @@ class Ticket
$this->app = new SupportApp();
}
/**
* Adding new task element.
*
* @param TicketElement $element Ticket element
*
* @return int
*
* @since 1.0.0
*/
public function addElement(TicketElement $element) : int
{
$this->ticketElements[] = $element;
\end($this->ticketElements);
$key = (int) \key($this->ticketElements);
\reset($this->ticketElements);
return $key;
}
/**
* Remove Element from list.
*
* @param int $id Ticket element
*
* @return bool
*
* @since 1.0.0
*/
public function removeElement($id) : bool
{
if (isset($this->ticketElements[$id])) {
unset($this->ticketElements[$id]);
return true;
}
return false;
}
/**
* Get ticket elements.
*
* @return TicketElement[]
*
* @since 1.0.0
*/
public function getTicketElements() : array
{
return $this->ticketElements;
}
/**
* Get ticket elements in inverted order.
*
* @return TicketElement[]
*
* @since 1.0.0
*/
public function invertTicketElements() : array
{
return \array_reverse($this->ticketElements);
}
/**
* Get ticket elements.
*
* @param int $id Element id
*
* @return TicketElement
*
* @since 1.0.0
*/
public function getTicketElement(int $id) : TicketElement
{
return $this->ticketElements[$id] ?? new NullTicketElement();
}
/**
* {@inheritdoc}
*/
@ -160,7 +74,6 @@ class Ticket
'id' => $this->id,
'task' => $this->task,
'app' => $this->app,
'ticketElements' => $this->ticketElements,
];
}

View File

@ -1,84 +0,0 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package Modules\Support\Models
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace Modules\Support\Models;
use Modules\Tasks\Models\TaskElement;
/**
* Ticket element class.
*
* @package Modules\Support\Models
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class TicketElement implements \JsonSerializable
{
/**
* Id.
*
* @var int
* @since 1.0.0
*/
public int $id = 0;
/**
* Ticket.
*
* @var int
* @since 1.0.0
*/
public int $ticket = 0;
/**
* Task element
*
* @var TaskElement
* @since 1.0.0
*/
public TaskElement $taskElement;
/**
* Constructor.
*
* @param null|TaskElement $taskElement Creates a ticket elmenet from a task element
*
* @since 1.0.0
*/
public function __construct(?TaskElement $taskElement = null)
{
$this->taskElement = $taskElement ?? new TaskElement();
}
/**
* {@inheritdoc}
*/
public function toArray() : array
{
return [
'id' => $this->id,
'ticket' => $this->ticket,
'taskElement' => $this->taskElement,
];
}
/**
* {@inheritdoc}
*/
public function jsonSerialize() : mixed
{
return $this->toArray();
}
}

View File

@ -1,73 +0,0 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package Modules\Support\Models
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace Modules\Support\Models;
use Modules\Tasks\Models\TaskElementMapper;
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
/**
* Mapper class.
*
* @package Modules\Support\Models
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*
* @template T of TicketElement
* @extends DataMapperFactory<T>
*/
final class TicketElementMapper extends DataMapperFactory
{
/**
* Columns.
*
* @var array<string, array{name:string, type:string, internal:string, autocomplete?:bool, readonly?:bool, writeonly?:bool, annotations?:array}>
* @since 1.0.0
*/
public const COLUMNS = [
'support_ticket_element_id' => ['name' => 'support_ticket_element_id', 'type' => 'int', 'internal' => 'id'],
'support_ticket_element_task_element' => ['name' => 'support_ticket_element_task_element', 'type' => 'int', 'internal' => 'taskElement'],
'support_ticket_element_ticket' => ['name' => 'support_ticket_element_ticket', 'type' => 'int', 'internal' => 'ticket'],
];
/**
* Has one relation.
*
* @var array<string, array{mapper:class-string, external:string, by?:string, column?:string, conditional?:bool}>
* @since 1.0.0
*/
public const OWNS_ONE = [
'taskElement' => [
'mapper' => TaskElementMapper::class,
'external' => 'support_ticket_element_task_element',
],
];
/**
* Primary table.
*
* @var string
* @since 1.0.0
*/
public const TABLE = 'support_ticket_element';
/**
* Primary field name.
*
* @var string
* @since 1.0.0
*/
public const PRIMARYFIELD = 'support_ticket_element_id';
}

View File

@ -25,7 +25,7 @@ use phpOMS\DataStorage\Database\Query\Builder;
use phpOMS\Stdlib\Base\SmartDateTime;
/**
* Mapper class.
* Ticket mapper class.
*
* @package Modules\Support\Models
* @license OMS License 2.0
@ -62,21 +62,6 @@ final class TicketMapper extends DataMapperFactory
],
];
/**
* Has many relation.
*
* @var array<string, array{mapper:class-string, table:string, self?:?string, external?:?string, column?:string}>
* @since 1.0.0
*/
public const HAS_MANY = [
'ticketElements' => [
'mapper' => TicketElementMapper::class,
'table' => 'support_ticket_element',
'self' => 'support_ticket_element_ticket',
'external' => null,
],
];
/**
* Belongs to.
*

View File

@ -53,7 +53,7 @@ return ['Support' => [
'Stats' => 'Stats',
'Status' => 'Status',
'Support' => 'Unterstützung',
'Ticket' => 'Fahrkarte',
'Ticket' => 'Ticket',
'Tickets' => 'Tickets',
'Title' => 'Titel',
'To' => 'Zu',

View File

@ -40,7 +40,7 @@ echo $this->data['nav']->render(); ?>
<?php
$c = 0;
foreach ($this->data['open'] as $key => $ticket) : ++$c;
$url = UriFactory::build('{/base}/support/ticket?{?}&id=' . $ticket->id);
$url = UriFactory::build('{/base}/support/ticket/view?{?}&id=' . $ticket->id);
?>
<tr data-href="<?= $url; ?>">
<td><a href="<?= $url; ?>">
@ -81,7 +81,7 @@ echo $this->data['nav']->render(); ?>
<?php
$c = 0;
foreach ($this->data['tickets'] as $key => $ticket) : ++$c;
$url = UriFactory::build('{/base}/support/ticket?{?}&id=' . $ticket->id);
$url = UriFactory::build('{/base}/support/ticket/view?{?}&id=' . $ticket->id);
?>
<tr data-href="<?= $url; ?>">
<td><a href="<?= $url; ?>">
@ -112,11 +112,11 @@ echo $this->data['nav']->render(); ?>
<div class="portlet-head"><?= $this->getHtml('Stats'); ?></div>
<div class="portlet-body">
<table class="list">
<tr><th><?= $this->getHtml('Unassigned'); ?><td><?= $this->data['stats']['unassigned']; ?>
<tr><th><?= $this->getHtml('Open'); ?><td><?= $this->data['stats']['open']; ?>
<tr><th><?= $this->getHtml('InProgress'); ?><td><?= $this->data['stats']['inprogress']; ?>
<tr><th><?= $this->getHtml('Closed'); ?><td><?= $this->data['stats']['closed']; ?>
<tr><th><?= $this->getHtml('Total'); ?><td><?= $this->data['stats']['total']; ?>
<tr><th><?= $this->getHtml('Unassigned'); ?><td><?= $this->data['stats']['unassigned'] ?? 0; ?>
<tr><th><?= $this->getHtml('Open'); ?><td><?= $this->data['stats']['open'] ?? 0; ?>
<tr><th><?= $this->getHtml('InProgress'); ?><td><?= $this->data['stats']['inprogress'] ?? 0; ?>
<tr><th><?= $this->getHtml('Closed'); ?><td><?= $this->data['stats']['closed'] ?? 0; ?>
<tr><th><?= $this->getHtml('Total'); ?><td><?= $this->data['stats']['total'] ?? 0; ?>
</table>
</div>
</section>

View File

@ -415,10 +415,11 @@ echo $this->data['nav']->render(); ?>
$count = 0;
foreach ($this->data['tickets'] as $value) :
++$count;
$url = UriFactory::build('{/base}/support/ticket/view?{?}&id=' . $value->id);
?>
<tr>
<td><?= $this->printHtml($value->task->title); ?>
<td><?= $value->task->createdAt->format('Y-m-d'); ?>
<tr data-href="<?= $url; ?>">
<td><a href="<?= $url; ?>"><?= $this->printHtml($value->task->title); ?></a>
<td><a href="<?= $url; ?>"><?= $value->task->createdAt->format('Y-m-d'); ?></a>
<?php endforeach; ?>
<?php if ($count === 0) : ?>
<tr><td colspan="2" class="empty"><?= $this->getHtml('Empty', '0', '0'); ?>
@ -441,10 +442,11 @@ echo $this->data['nav']->render(); ?>
$count = 0;
foreach ($this->data['contracts'] as $value) :
++$count;
$url = UriFactory::build('{/base}/contract/view?{?}&id=' . $value->id);
?>
<tr>
<td><?= $this->printHtml($value->title); ?>
<td><?= $value->createdAt->format('Y-m-d'); ?>
<tr data-href="<?= $url; ?>">
<td><a href="<?= $url; ?>"><?= $this->printHtml($value->title); ?></a>
<td><a href="<?= $url; ?>"><?= $value->createdAt->format('Y-m-d'); ?></a>
<?php endforeach; ?>
<?php if ($count === 0) : ?>
<tr><td colspan="2" class="empty"><?= $this->getHtml('Empty', '0', '0'); ?>