Skip to content

Commit

Permalink
feat(ZMSKVR-72): create closure for specific day and office
Browse files Browse the repository at this point in the history
  • Loading branch information
manjencic committed Feb 28, 2025
1 parent dfa4415 commit 0154a8a
Show file tree
Hide file tree
Showing 23 changed files with 613 additions and 6 deletions.
4 changes: 4 additions & 0 deletions zmsadmin/routing.php
Original file line number Diff line number Diff line change
Expand Up @@ -490,3 +490,7 @@
\App::$slim->getContainer()->offsetSet('phpErrorHandler', function ($container) {
return new \BO\Zmsadmin\Helper\TwigExceptionHandler($container);
});


\App::$slim->post('/scope/{id:\d+}/availability/day/{date:\d\d\d\d-\d\d-\d\d}/closure/toggle/', \BO\Zmsadmin\ScopeAvailabilityDayClosure::class)
->setName("scopeAvailabilityDayClosure");
45 changes: 45 additions & 0 deletions zmsadmin/src/Zmsadmin/ScopeAvailabilityDayClosure.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

/**
* @package Zmsadmin
* @copyright BerlinOnline Stadtportal GmbH & Co. KG
**/

namespace BO\Zmsadmin;

use BO\Slim\Render;
use BO\Zmsdb\Closure;
use BO\Zmsentities\Collection\AvailabilityList;
use Psr\Http\Message\ResponseInterface;

class ScopeAvailabilityDayClosure extends BaseController
{
/**
* @SuppressWarnings(Param)
* @return ResponseInterface
*/
public function readResponse(
\Psr\Http\Message\RequestInterface $request,
\Psr\Http\Message\ResponseInterface $response,
array $args
): ResponseInterface {
$scopeId = $args['id'];
$date = $args['date'];

try {
$closureToggled = \App::$http->readPostResult(
'/scope/' . $scopeId . '/availability/' . $date . '/closure/toggle/',
new \BO\Zmsentities\Closure()
)->getEntity();
} catch (\Exception $e) {
var_dump($e->getMessage());exit;
}

return \BO\Slim\Render::withJson(
$response,
[
'closure' => $closureToggled
]
);
}
}
2 changes: 2 additions & 0 deletions zmsadmin/src/Zmsadmin/ScopeAvailabilityMonth.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

use BO\Mellon\Validator;
use BO\Zmsentities\Calendar;
use BO\Zmsentities\Closure;
use BO\Zmsentities\Collection\AvailabilityList;
use BO\Zmsentities\Collection\ProcessList;

Expand Down Expand Up @@ -67,6 +68,7 @@ public function readResponse(
'conflicts' => $processConflictList,
'calendar' => $calendar,
'dayoffList' => $scope->getDayoffList(),
'closureList' => $scope->getClosureList(),
'dateTime' => $dateTime,
'timestamp' => $dateTime->getTimeStamp(),
'month' => $month,
Expand Down
6 changes: 5 additions & 1 deletion zmsadmin/templates/block/availability/monthtable.twig
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,14 @@
{% endif %}
</div>
<div class="row icons palm-hide">
{% if closureList.hasEntityByDate(day.toDateTime()) %}
{{ openingCalendarIcon('X', 'red daystatus--conflict', 1, 'Gesperrt') }}
{% endif %}
{% if day.freeAppointments.public > 0 %}<i class="fas fa-globe" role="img" title="Buchbar per Internet"></i>{% endif %}
{% if day.freeAppointments.callcenter > 0 %}<i class="fas fa-phone" role="img" title="Buchbar per Callcenter"></i>{% endif %}
</div>
<div class="row holiday palm-hide">{% if dayoffList.hasEntityByDate(day.toDateTime()) %}
<div class="row holiday palm-hide">
{% if dayoffList.hasEntityByDate(day.toDateTime()) %}
{{ dayoffList.getByDate(day.toDateTime()).name }}
{% endif %}
</div>
Expand Down
1 change: 1 addition & 0 deletions zmsadmin/templates/block/calendar/legend.twig
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
<ul class="list--clean">
<li><i class="fas fa-globe"></i> Buchbar per Internet</li>
<li><i class="fas fa-phone"></i> Buchbar per Callcenter</li>
<li>{{ openingCalendarIcon('X','red', 1, 'Gesperrt') }} Gesperrt</li>
</ul>
</div>
{% endif %}
Expand Down
56 changes: 56 additions & 0 deletions zmsadmin/templates/page/availabilityday.twig
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,56 @@
{% endblock %}

{% block content %}
<div>
<div class="closure"
data-scope="{{scope | json_encode}}"
data-dateString="{{dateString}}"></div>

{% set locked = false %}
{% for closure in scope.closure %}
{% if closure.date|date('Y-m-d') == dateString %}
{% set locked = true %}
{% endif %}
{% endfor %}
<div id="closure-close" class="message message--warning {% if not locked %}hidden{% endif %}">
Die Terminbuchung für diesen Tag ist gesperrt. <input class="button btn" style="margin-top: -6px;" type="button" onclick="toggleClosure()" value="Entsperren">
</div>
<div id="closure-open" class="message message--info {% if locked %}hidden{% endif %}">
Die Terminbuchung für diesen Tag ist NICHT gesperrt. <input class="button btn" style="margin-top: -6px;" onclick="toggleClosure()" type="button" value="Sperren">
</div>

<script>
function toggleClosure() {
const ok = confirm('Möchten Sie wirklich Die Terminbuchung für diesen Tag {% if locked %}entsperren{% else %}sperren{% endif %}?')
if (!ok) {
return
}
const currentDate = '{{ dateString }}'
const url = `{{ includeUrl() }}/scope/{{ scope.id }}/availability/day/${currentDate}/closure/toggle/`
$.ajax(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
data: JSON.stringify({})
}).done(data => {
if (data.closure.existing) {
document.getElementById('closure-close').classList.remove('hidden')
document.getElementById('closure-open').classList.add('hidden')
} else {
document.getElementById('closure-close').classList.add('hidden')
document.getElementById('closure-open').classList.remove('hidden')
}
}).fail(err => {
console.log('error', err)
})
}
</script>

{% set a = getNow()|date('Y-m-d') %}
{% if scope.closure.hasEntityByDate('2025-02-24') %}
X
{% endif %}
</div>
<div class="availabilityDayRoot"
data-today="{{ today }}"
data-availabilityList="{{availabilityList | json_encode}}"
Expand All @@ -35,6 +85,12 @@
data-slotbuckets={{ slotBuckets|json_encode }}
data-maxslots="{{ maxSlotsForAvailabilities|json_encode }}"
data-busyslots="{{ busySlotsForAvailabilities|json_encode }}" ></div>

<style>
.hidden {
display: none;
}
</style>
{% endblock %}

{% block javascript %}
Expand Down
5 changes: 3 additions & 2 deletions zmsapi/cron/cronjob.minutly
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ DIR=$(dirname ${BASH_SOURCE[0]})
BIN=$DIR/../vendor/bin
API=$DIR/../bin/api
EXPORT=$DIR/../data/

echo 'asdasda'
set -a
[ -z "$ZMS_ENV" ] && [ -e /etc/sysconfig/zms ] && source /etc/sysconfig/zms
set +a

if [[ $ZMS_CRONROOT =~ ^1|on|true|yes$ ]]; then
if [[ $ZMS_ENV =~ ^prod|dev|stage$ ]]; then
$API config cron deleteUnconfirmedAppointmentData|grep -q "$ZMS_ENV" && $BIN/deleteUnconfirmedAppointmentData --commit
echo 'zzzzzzzzzzzzzzzz'
$API config cron deleteUnconfirmedAppointmentData|grep -q "$ZMS_ENV" && $BIN/deleteUnconfirmedAppointmentData --commit
$API config cron deallocateAppointmentData|grep -q "$ZMS_ENV" && $BIN/deallocateAppointmentData --commit
$API config cron deleteSessionData|grep -q "$ZMS_ENV" && $BIN/deleteSessionData Zmsappointment 30 --commit
$API config cron sendMailReminder|grep -q "$ZMS_ENV" && $BIN/sendMailReminder 120 --commit
Expand Down
45 changes: 45 additions & 0 deletions zmsapi/routing.php
Original file line number Diff line number Diff line change
Expand Up @@ -4139,6 +4139,51 @@
)
->setName("RequestListByScope");

/**
* @swagger
* "/scope/{id}/availability/{date}/closure/toggle/":
* get:
* summary: Toogle availability closure for specific day
* x-since: 2.11
* tags:
* - scope
* - closure
* parameters:
* - name: id
* description: scope ID
* in: path
* required: true
* type: integer
* - name: date
* description: day in format YYYY-MM-DD
* in: path
* required: true
* type: integer
* - name: X-Authkey
* required: true
* description: authentication key to identify user for testing access rights
* in: header
* type: string
* responses:
* 200:
* description: "success, closure is deleted if existed before or created when didn't exist before"
* schema:
* type: object
* properties:
* meta:
* $ref: "schema/metaresult.json"
* data:
* type: array
* items:
* $ref: "schema/process.json"
*/
\App::$slim->post(
'/scope/{id:\d{1,11}}/availability/{date:\d\d\d\d-\d\d-\d\d}/closure/toggle/',
'\BO\Zmsapi\AvailabilityClosureToggle'
)
->setName("AvailabilityClosureToggle");


/**
* @swagger
* "/scope/{id}/workstation/":
Expand Down
74 changes: 74 additions & 0 deletions zmsapi/src/Zmsapi/AvailabilityClosureToggle.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

/**
* @package ZMS API
* @copyright BerlinOnline Stadtportal GmbH & Co. KG
**/

namespace BO\Zmsapi;

use BO\Slim\Render;
use BO\Mellon\Validator;
use BO\Zmsdb\Closure;
use BO\Zmsentities\Closure as ClosureEntity;
use BO\Zmsentities\Availability as Entity;
use BO\Zmsentities\Collection\AvailabilityList as Collection;
use BO\Zmsdb\Availability as AvailabilityRepository;
use BO\Zmsdb\Slot as SlotRepository;
use BO\Zmsdb\Config as ConfigRepository;
use BO\Zmsdb\Helper\CalculateSlots as CalculateSlotsHelper;
use BO\Zmsdb\Connection\Select as DbConnection;
use BO\Zmsentities\Collection\ClosureList;
use DateTime;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use BO\Zmsapi\Exception\BadRequest as BadRequestException;
use BO\Zmsapi\Exception\Availability\AvailabilityNotFound as NotfoundException;

/**
* @SuppressWarnings(Coupling)
*/
class AvailabilityClosureToggle extends BaseController
{
/**
* @SuppressWarnings(Param)
* @return ResponseInterface
*/
public function readResponse(
RequestInterface $request,
ResponseInterface $response,
array $args
): ResponseInterface {
(new Helper\User($request))->checkRights();
$input = Validator::input()->isJson()->assertValid()->getValue();
if (! $input || count($input) === 0) {
throw new BadRequestException();
}
$data = [];
$scopeId = $args['id'];
$date = $args['date'];
$closure = null;

try {
$closure = (new Closure())->readByScopeIdAndDate($scopeId, new DateTime($date));
} catch (\Exception $e) {
}

if (empty($closure->getId())) {
$closure = (new Closure())->createOne($scopeId, new DateTime($date));
$closure->existing = true;
$data['message'] = 'Closure has been created';
} else {
(new Closure())->deleteEntity($closure->getId());
$closure->existing = false;
$data['message'] = 'Closure has been deleted';
}

$message = Response\Message::create($request);
$message->data = $closure;

$response = Render::withLastModified($response, time(), '0');
$response = Render::withJson($response, $message->setUpdatedMetaData(), $message->getStatuscode());
return $response;
}
}
12 changes: 12 additions & 0 deletions zmsdb/migrations/91740144530-create-closures-table.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
DROP TABLE IF EXISTS `closures`;
CREATE TABLE `closures` (
`id` INT(5) UNSIGNED AUTO_INCREMENT,
`year` SMALLINT(5),
`month` TINYINT(5),
`day` TINYINT(5),
`StandortID` INT(5) UNSIGNED,
`updateTimestamp` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
INDEX (StandortID),
INDEX (StandortID, year, month, day)
)
70 changes: 70 additions & 0 deletions zmsdb/src/Zmsdb/Closure.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

namespace BO\Zmsdb;

use BO\Zmsentities\Closure as Entity;
use BO\Zmsentities\Collection\ClosureList as Collection;
use DateTime;

class Closure extends Base
{
public function readByScopeId($scopeId = 0)
{
$closureList = new Collection();
$query = new Query\Closure(Query\Base::SELECT);
$query->addEntityMapping()
->addConditionScopeId($scopeId);
$result = $this->fetchList($query, new Entity());
if (count($result)) {
foreach ($result as $entity) {
if ($entity instanceof Entity) {
$closureList->addEntity($entity);
}
}
}
return $closureList;
}

public function readByScopeIdAndDate($scopeId, DateTime $date)
{
$query = new Query\Closure(Query\Base::SELECT);
$query->addEntityMapping()
->addConditionScopeId($scopeId)
->addConditionDate($date);

return $this->fetchOne($query, new \BO\Zmsentities\Closure());
}

public function deleteEntity($itemId)
{
$query = new Query\Closure(Query\Base::DELETE);
$query->addConditionClosureId($itemId);
return ($this->deleteItem($query));
}

public function createOne($scopeId, DateTime $date)
{
$query = new Query\Closure(Query\Base::INSERT);
$query->addValues(
array(
'StandortID' => $scopeId,
'year' => (int) $date->format('Y'),
'month' => (int) $date->format('m'),
'day' => (int) $date->format('d')
)
);
$this->writeItem($query);
$id = $this->getWriter()->lastInsertId();

return $this->readEntity($id);
}

public function readEntity($id)
{
$query = new Query\Closure(Query\Base::SELECT);
$query->addEntityMapping()
->addConditionId($id);

return $this->fetchOne($query, new \BO\Zmsentities\Closure());
}
}
Loading

0 comments on commit 0154a8a

Please sign in to comment.