diff --git a/zmsadmin/routing.php b/zmsadmin/routing.php index 3de7a9adc..298272915 100644 --- a/zmsadmin/routing.php +++ b/zmsadmin/routing.php @@ -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"); diff --git a/zmsadmin/src/Zmsadmin/WorkstationProcessRedirect.php b/zmsadmin/src/Zmsadmin/WorkstationProcessRedirect.php new file mode 100644 index 000000000..d8d8d9482 --- /dev/null +++ b/zmsadmin/src/Zmsadmin/WorkstationProcessRedirect.php @@ -0,0 +1,87 @@ +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') + ) + ); + } +} diff --git a/zmsadmin/templates/block/appointment/formRedirect.twig b/zmsadmin/templates/block/appointment/formRedirect.twig new file mode 100644 index 000000000..fee338aa3 --- /dev/null +++ b/zmsadmin/templates/block/appointment/formRedirect.twig @@ -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 %} + +
+
+ + {% 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" + } + }] + ) }} + + +
+ {% endblock %} +{% endembed %} diff --git a/zmsadmin/templates/block/process/info.twig b/zmsadmin/templates/block/process/info.twig index a7736f16d..0f13d108a 100644 --- a/zmsadmin/templates/block/process/info.twig +++ b/zmsadmin/templates/block/process/info.twig @@ -63,9 +63,13 @@ {% endif %} - - Fertig stellen - + Fertig stellen + + {% if workstation.process.withAppointment %} + Weiterleiten + {% endif %} + + {% endif %} {% endblock %} diff --git a/zmsadmin/templates/page/workstationProcessRedirect.twig b/zmsadmin/templates/page/workstationProcessRedirect.twig new file mode 100644 index 000000000..c50a9a37f --- /dev/null +++ b/zmsadmin/templates/page/workstationProcessRedirect.twig @@ -0,0 +1,42 @@ +{% extends "layout/main.twig" %} +{% from 'element/helper/snippets.twig' import headline1 %} + +{% block headline %} + {{ headline1("Sachbearbeiterplatz") }} +{% endblock %} + +{% block content %} +
+
+
+ {% include "block/process/nextContainer.twig" %} +
+
+ {% include "block/appointment/formRedirect.twig" with { + 'scopes': scopes, + 'workstation': workstation + } %} +
+
+
+ {% include "block/calendar/calendarContainer.twig" with {source: "workstation"} %} +
+
+ {% include "block/calendar/legend.twig" with {"view": "calendar"} %} +
+
+
+
+
+ {% include "block/queue/queueContainer.twig" %} +
+
+
+{% endblock %} diff --git a/zmsapi/routing.php b/zmsapi/routing.php index b6fdee181..c4eebe4ab 100644 --- a/zmsapi/routing.php +++ b/zmsapi/routing.php @@ -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/": diff --git a/zmsapi/src/Zmsapi/ProcessRedirect.php b/zmsapi/src/Zmsapi/ProcessRedirect.php new file mode 100644 index 000000000..f42228529 --- /dev/null +++ b/zmsapi/src/Zmsapi/ProcessRedirect.php @@ -0,0 +1,106 @@ +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; + } +} diff --git a/zmsdb/src/Zmsdb/Process.php b/zmsdb/src/Zmsdb/Process.php index e8624da65..a7503f343 100755 --- a/zmsdb/src/Zmsdb/Process.php +++ b/zmsdb/src/Zmsdb/Process.php @@ -1,6 +1,7 @@ writeNewProcess($process, $dateTime); } + public function redirectToScope($process, \BO\Zmsentities\Scope $scope, int $waitingNumber) + { + $datetime = \App::$now; + $process->setStatus('confirmed'); + + $appointment = $process->getFirstAppointment(); + $date = (new \DateTimeImmutable())->setTimestamp($appointment->date); + $date = $date->setTime(0, 0, 0); + $appointment->date = $date->getTimestamp(); + $process->appointments = new AppointmentList([$appointment]); + + $newQueueNumber = (new Scope())->readWaitingNumberUpdated($scope->id, $datetime); + $process->addQueue($newQueueNumber, $datetime); + $process->queue['number'] = $waitingNumber; + + Log::writeLogEntry("CREATE (Process::redirectToScope) $process ", $process->id); + + $process = $this->writeNewProcess($process, $datetime); + $this->writeRequestsToDb($process); + + return $process; + } + public function readSlotCount(\BO\Zmsentities\Process $process) { $scope = new \BO\Zmsentities\Scope($process->scope);