Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature zms 1808 appoinrment redirect #100

Merged
merged 2 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions zmsadmin/routing.php
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,9 @@
\App::$slim->map(['GET','POST'], '/workstation/process/finished/', \BO\Zmsadmin\WorkstationProcessFinished::class)
->setName("workstationProcessFinished");

\App::$slim->map(['GET','POST'], '/workstation/process/redirect/', \BO\Zmsadmin\WorkstationProcessRedirect::class)
->setName("workstationProcessRedirect");

\App::$slim->get('/workstation/call/{id:\d+}/', \BO\Zmsadmin\WorkstationProcessCall::class)
->setName("workstationProcessCall");

Expand Down
87 changes: 87 additions & 0 deletions zmsadmin/src/Zmsadmin/WorkstationProcessRedirect.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php
/**
* @package Zmsadmin
* @copyright BerlinOnline Stadtportal GmbH & Co. KG
**/

namespace BO\Zmsadmin;

use \Psr\Http\Message\RequestInterface;

class WorkstationProcessRedirect extends BaseController
{
/**
* @SuppressWarnings(Param)
* @return String
*/
public function readResponse(
RequestInterface $request,
\Psr\Http\Message\ResponseInterface $response,
array $args
) {
$workstation = \App::$http->readGetResult('/workstation/', ['resolveReferences' => 2])->getEntity();
$department = \App::$http
->readGetResult(
'/scope/' . $workstation->scope['id'] . '/department/',
['resolveReferences' => 2]
)->getEntity();
$input = $request->getParsedBody();
$process = $workstation->process;

if ($request->getMethod() === 'POST') {
$validator = $request->getAttribute('validator');
$selectedLocation = $validator->getParameter('location')->isNumber()->getValue();

if (empty($selectedLocation)) {
return \BO\Slim\Render::redirect(
'workstationProcessRedirect',
[],
[
'errors' => [
'location' => 'Bitte wählen Sie einen Standort aus.'
]
]
);
}

$scope = \App::$http
->readGetResult(
'/scope/' . $selectedLocation . '/',
['resolveReferences' => 2]
)->getEntity();

$process = \App::$http
->readGetResult(
'/process/'. $process->getId() .'/'. $process->getAuthKey() .'/',
['resolveReferences' => 2]
)->getEntity();

$newProcess = clone $process;
$newProcess->scope = $scope;
$newProcess->appointments[0]->scope = $scope;
$newProcess->amendment = $input['amendment'];

$process = \App::$http->readPostResult('/process/status/redirect/', $newProcess)->getEntity();

return \BO\Slim\Render::redirect(
$workstation->getVariantName(),
array(),
array()
);
}

return \BO\Slim\Render::withHtml(
$response,
'page/workstationProcessRedirect.twig',
array(
'title' => 'Kundendaten',
'workstation' => $workstation,
'department' => $department,
'scope' => $workstation->scope,
'scopes' => $department->getScopeList(),
'menuActive' => 'workstation',
'errors' => $request->getParam('errors')
)
);
}
}
57 changes: 57 additions & 0 deletions zmsadmin/templates/block/appointment/formRedirect.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{% embed "block/scaffholding/board.twig" with {'class': 'appointment-form'} %}

{% from 'element/helper/form.twig' import formgroup, formbutton, checkboxfield, selectfield, inputfield %}

{% block board_title %}
Termin Weiterleiten
{% endblock %}

{% block board_body %}
{% include "element/helper/messageHandler.twig" %}
{% from 'element/helper/form.twig' import formgroup, formbutton, inputfield, providername %}

<form data-formData="{{ formData|json_encode }}" data-saved-process="{{ selectedProcess.id }}" method="POST">
<div class="aural" id="auralmessage" aria-live="polite" data-aural='{"clean":"{{ cleanupRequestAuralMessage|trans }}", "add":"{{ addRequestAuralMessage|trans }}","remove":"{{ removeRequestAuralMessage|trans }}", "chooseRequestFirst":"{{ chooseRequestFirst|trans }}"}'></div>

{% set scopeOptionsGroup = [{ 'value' : '', 'name' : '-- bitte auswählen --'}] %}
{% set scopeOptionsGroupOptions = [] %}
{% for scopeOption in scopes|filter((s) => s.name != '' and s.id != scope.id) %}
{% set scopeOptionsGroupOptions = scopeOptionsGroupOptions|merge([{ "value": scopeOption.id, "name": providername(scopeOption) }]) %}
{% endfor %}
{% set scopeOptionsGroup = scopeOptionsGroup|merge([{ 'name' : department.name, 'options' : scopeOptionsGroupOptions|msort('name') }]) %}

{{ formgroup(
{"label": "Weiterleiten zu Standort", "required": true, "errors": [errors.location]},
[{
"type": "select",
"required": true,
"parameter": {
"name": "location",
"options": scopeOptionsGroup
}
}]
) }}

{{ formgroup(
{
"label": "Anmerkung",
"checked": scope.preferences.client.amendmentActivated,
"class": "form-group--nomaxwidth",
"errors": formData.amendment.messages
},
[{
"type":"textarea",
"parameter": {
"name": "amendment",
"rows": "3",
"maxlength": 300,
"value": workstation.process.amendment,
"accesskey":"w"
}
}]
) }}

<button class="button button--positive button-submit process-reserve" accesskey="h">{{ "%s"|format("Termin buchen")|trans }}</button>
</form>
{% endblock %}
{% endembed %}
10 changes: 7 additions & 3 deletions zmsadmin/templates/block/process/info.twig
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,13 @@
{% endif %}
</dd>
</dl>

<a class="button button--positive button--fullwidth button-finish right" href="{{ urlGet("workstationProcessFinished", {}, {}) }}" style="margin: 0.5em 0;">Fertig stellen</a>
<button type="button" class="button button--destructive button--fullwidth button-cancel left" style="margin: 0.5em 0;">Abbruch</button>
<a class="button button--positive button--fullwidth button-finish right" href="{{ urlGet("workstationProcessFinished", {}, {}) }}" style="margin: 0.5em 0;">Fertig stellen</a>

{% if workstation.process.withAppointment %}
<a class="button button--default button--fullwidth button-finish right" href="{{ urlGet("workstationProcessRedirect", {}, {}) }}" style="margin: 0.5em 0;">Weiterleiten</a>
{% endif %}

<button type="button" class="button button--destructive button--fullwidth button-cancel left" style="margin: 0.5em 0;">Abbruch</button>
{% endif %}

{% endblock %}
Expand Down
42 changes: 42 additions & 0 deletions zmsadmin/templates/page/workstationProcessRedirect.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{% extends "layout/main.twig" %}
{% from 'element/helper/snippets.twig' import headline1 %}

{% block headline %}
{{ headline1("Sachbearbeiterplatz") }}
{% endblock %}

{% block content %}
<div class="workstation-view"
data-includeurl="{{ includeUrl() }}"
data-selected-date="{{ selectedDate }}"
data-selected-time="{{ selectedTime }}"
data-selected-process="{{ selectedProcess }}"
data-cluster-enabled="{{ workstation.queue.clusterEnabled }}"
data-selected-scope="{% if workstation.queue.clusterEnabled == 0 %}{{ workstation.scope.id }}{% else %}{{ selectedScope }}{% endif %}"
data-called-process="{{ calledProcess }}">
<div class="grid">
<div class="grid__item three-twelfths" id="liveregionClientNext" data-client-next>
{% include "block/process/nextContainer.twig" %}
</div>
<div class="grid__item six-twelfths">
{% include "block/appointment/formRedirect.twig" with {
'scopes': scopes,
'workstation': workstation
} %}
</div>
<div class="grid__item three-twelfths" aria-live="off" id="liveregionCalendarBox" data-calendar-box>
<div data-calendar>
{% include "block/calendar/calendarContainer.twig" with {source: "workstation"} %}
</div>
<div style="margin-top:-2em;">
{% include "block/calendar/legend.twig" with {"view": "calendar"} %}
</div>
</div>
</div>
<div class="grid">
<div class="grid__item" aria-live="off" id="liveregionQueueTable" data-queue-table>
{% include "block/queue/queueContainer.twig" %}
</div>
</div>
</div>
{% endblock %}
44 changes: 44 additions & 0 deletions zmsapi/routing.php
Original file line number Diff line number Diff line change
Expand Up @@ -3282,6 +3282,50 @@
)
->setName("ProcessPickup");

/**
* @swagger
* "/process/status/redirect/":
* post:
* summary: Find or create a process to be used to redirect documents.
* x-since: 2.11
* description: Only process.queue.number is a necessary input. But it is possible to create a full process with a given waiting number. If the process already exists, an update is only performed, if process.id and process.authkey matches. Information about the scope are taken from the workstation fetches by X-Authkey
* tags:
* - process
* parameters:
* - name: X-Authkey
* required: true
* description: authentication key to identify user for testing access rights
* in: header
* type: string
* - name: process
* description: process data to create
* required: true
* in: body
* schema:
* $ref: "schema/process.json"
* responses:
* 200:
* description: you are able to call this process now
* schema:
* type: object
* properties:
* meta:
* $ref: "schema/metaresult.json"
* data:
* type: array
* items:
* $ref: "schema/process.json"
* 400:
* description: "Invalid input"
* 403:
* description: "authkey does not match"
*/
\App::$slim->post(
'/process/status/redirect/',
'\BO\Zmsapi\ProcessRedirect'
)
->setName("ProcessRedirect");

/**
* @swagger
* "/process/status/queued/":
Expand Down
106 changes: 106 additions & 0 deletions zmsapi/src/Zmsapi/ProcessRedirect.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?php
/**
* @package ZMS API
* @copyright BerlinOnline Stadtportal GmbH & Co. KG
**/

namespace BO\Zmsapi;

use \BO\Slim\Render;
use \BO\Mellon\Validator;
use BO\Zmsdb\Process;
use \BO\Zmsdb\Process as Query;
use \BO\Zmsdb\ProcessStatusQueued;
use BO\Zmsdb\Workstation;

/**
* @SuppressWarnings(Coupling)
*/
class ProcessRedirect extends BaseController
{
/**
* @SuppressWarnings(Param)
* @return String
*/
public function readResponse(
\Psr\Http\Message\RequestInterface $request,
\Psr\Http\Message\ResponseInterface $response,
array $args
) {
$workstation = (new Helper\User($request))->checkRights();
$input = Validator::input()->isJson()->assertValid()->getValue();
$entity = new \BO\Zmsentities\Process($input);
$newProcess = new \BO\Zmsentities\Process($input);



$process = $this->readValidProcess($workstation, $entity, $input);
$process = (new Process())->readEntity($process->id, $process->authKey, 2);
$requests = $process->getRequests();
$newProcess->requests = $requests;

$this->testProcessAccess($workstation, $process);

\BO\Zmsdb\Connection\Select::getWriteConnection();
$processStatusArchived = new \BO\Zmsdb\ProcessStatusArchived();

$process->status = 'finished';
$process = (new Query)->updateEntity($process, \App::$now, 0, 'processing');
(new Workstation)->writeRemovedProcess($workstation);
$processStatusArchived->writeEntityFinished($process, \App::$now, true);

$newProcess = (new \BO\Zmsdb\Process())->redirectToScope($newProcess, $process->scope, $process->id);

$message = Response\Message::create($request);
$message->data = $newProcess;
$response = Render::withLastModified($response, time(), '0');

return Render::withJson($response, $message->setUpdatedMetaData(), $message->getStatuscode());
}

protected function testProcessData($entity)
{
$entity->testValid();
$authCheck = (new Query())->readAuthKeyByProcessId($entity->id);
if (! $authCheck) {
throw new Exception\Process\ProcessNotFound();
} elseif ($authCheck['authKey'] != $entity->authKey && $authCheck['authName'] != $entity->authKey) {
throw new Exception\Process\AuthKeyMatchFailed();
}
}

protected function testProcessAccess($workstation, $process)
{
$cluster = (new \BO\Zmsdb\Cluster)->readByScopeId($workstation->scope['id'], 1);
$workstation->testMatchingProcessScope($workstation->getScopeList($cluster), $process);
if ($workstation->process && $workstation->process->hasId() && $workstation->process->id != $process->id) {
$exception = new Exception\Workstation\WorkstationHasAssignedProcess();
$exception->data = [
'process' => $workstation->process
];
throw $exception;
}
}

protected function readValidProcess($workstation, $entity, $input)
{
if ($entity->hasProcessCredentials()) {
$this->testProcessData($entity);
$entity->addData($input);
$process = (new Query())->updateEntity($entity, \App::$now);
} elseif ($entity->hasQueueNumber()) {
// Allow waitingnumbers over 1000 with the fourth parameter
$process = ProcessStatusQueued::init()
->readByQueueNumberAndScope($entity['queue']['number'], $workstation->scope['id'], 0, 100000000);
if (! $process->id) {
$workstation = (new \BO\Zmsdb\Workstation)->readResolvedReferences($workstation, 1);
$process = (new Query())->writeNewPickup($workstation->scope, \App::$now, $entity['queue']['number']);
}
$process->testValid();
} else {
$entity->testValid();
throw new Exception\Process\ProcessInvalid();
}
return $process;
}
}
Loading
Loading