Przeglądaj źródła

Merge branch 'master' of ssh://gitea.spawntree.de:1122/spawntree/mpp-tool

master
Florian Eisenmenger 2 lat temu
rodzic
commit
7646912ccf
22 zmienionych plików z 1311 dodań i 1271 usunięć
  1. +1
    -0
      httpdocs/composer.json
  2. +336
    -1
      httpdocs/composer.lock
  3. +2
    -0
      httpdocs/config/packages/doctrine.yaml
  4. +4
    -0
      httpdocs/config/packages/ramsey_uuid_doctrine.yaml
  5. BIN
      httpdocs/import/mpp_import_din.xlsx
  6. +55
    -108
      httpdocs/public/assets/js/my-bim-score.js
  7. +0
    -3
      httpdocs/src/Command/CmdImportDinAssets.php
  8. +88
    -260
      httpdocs/src/Controller/UserController.php
  9. +0
    -222
      httpdocs/src/Entity/Catalogue.php
  10. +0
    -214
      httpdocs/src/Entity/CatalogueDetail.php
  11. +2
    -50
      httpdocs/src/Entity/DinAsset.php
  12. +0
    -96
      httpdocs/src/Entity/Question.php
  13. +0
    -151
      httpdocs/src/Entity/QuestionType.php
  14. +27
    -75
      httpdocs/src/Entity/User.php
  15. +367
    -0
      httpdocs/src/Entity/UserWorksheet.php
  16. +239
    -0
      httpdocs/src/Entity/UserWorksheetTask.php
  17. +9
    -68
      httpdocs/src/Repository/UserRepository.php
  18. +59
    -0
      httpdocs/src/Service/CalculatorService.php
  19. +21
    -0
      httpdocs/symfony.lock
  20. +12
    -1
      httpdocs/templates/pages/risk_analysis.html.twig
  21. +10
    -22
      httpdocs/templates/pages/start.html.twig
  22. +79
    -0
      httpdocs/templates/pages/worksheet.html.twig

+ 1
- 0
httpdocs/composer.json Wyświetl plik

@@ -15,6 +15,7 @@
"dompdf/dompdf": "^1.0",
"phpdocumentor/reflection-docblock": "^5.2",
"phpoffice/phpspreadsheet": "^1.29",
"ramsey/uuid-doctrine": "^2.0",
"sensio/framework-extra-bundle": "^5.1",
"symfony/asset": "5.2.*",
"symfony/console": "5.2.*",


+ 336
- 1
httpdocs/composer.lock Wyświetl plik

@@ -4,8 +4,68 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "11ca8917ee233c35def1ef75d84a8deb",
"content-hash": "358bc2359e8ab59c4f397e9c581de202",
"packages": [
{
"name": "brick/math",
"version": "0.9.3",
"source": {
"type": "git",
"url": "https://github.com/brick/math.git",
"reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/brick/math/zipball/ca57d18f028f84f777b2168cd1911b0dee2343ae",
"reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae",
"shasum": ""
},
"require": {
"ext-json": "*",
"php": "^7.1 || ^8.0"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.2",
"phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.0",
"vimeo/psalm": "4.9.2"
},
"type": "library",
"autoload": {
"psr-4": {
"Brick\\Math\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Arbitrary-precision arithmetic library",
"keywords": [
"Arbitrary-precision",
"BigInteger",
"BigRational",
"arithmetic",
"bigdecimal",
"bignum",
"brick",
"math"
],
"support": {
"issues": "https://github.com/brick/math/issues",
"source": "https://github.com/brick/math/tree/0.9.3"
},
"funding": [
{
"url": "https://github.com/BenMorel",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/brick/math",
"type": "tidelift"
}
],
"time": "2021-08-15T20:50:18+00:00"
},
{
"name": "composer/package-versions-deprecated",
"version": "1.11.99.1",
@@ -2941,6 +3001,281 @@
},
"time": "2017-10-23T01:57:42+00:00"
},
{
"name": "ramsey/collection",
"version": "1.3.0",
"source": {
"type": "git",
"url": "https://github.com/ramsey/collection.git",
"reference": "ad7475d1c9e70b190ecffc58f2d989416af339b4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ramsey/collection/zipball/ad7475d1c9e70b190ecffc58f2d989416af339b4",
"reference": "ad7475d1c9e70b190ecffc58f2d989416af339b4",
"shasum": ""
},
"require": {
"php": "^7.4 || ^8.0",
"symfony/polyfill-php81": "^1.23"
},
"require-dev": {
"captainhook/plugin-composer": "^5.3",
"ergebnis/composer-normalize": "^2.28.3",
"fakerphp/faker": "^1.21",
"hamcrest/hamcrest-php": "^2.0",
"jangregor/phpstan-prophecy": "^1.0",
"mockery/mockery": "^1.5",
"php-parallel-lint/php-console-highlighter": "^1.0",
"php-parallel-lint/php-parallel-lint": "^1.3",
"phpcsstandards/phpcsutils": "^1.0.0-rc1",
"phpspec/prophecy-phpunit": "^2.0",
"phpstan/extension-installer": "^1.2",
"phpstan/phpstan": "^1.9",
"phpstan/phpstan-mockery": "^1.1",
"phpstan/phpstan-phpunit": "^1.3",
"phpunit/phpunit": "^9.5",
"psalm/plugin-mockery": "^1.1",
"psalm/plugin-phpunit": "^0.18.4",
"ramsey/coding-standard": "^2.0.3",
"ramsey/conventional-commits": "^1.3",
"vimeo/psalm": "^5.4"
},
"type": "library",
"extra": {
"captainhook": {
"force-install": true
},
"ramsey/conventional-commits": {
"configFile": "conventional-commits.json"
}
},
"autoload": {
"psr-4": {
"Ramsey\\Collection\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ben Ramsey",
"email": "ben@benramsey.com",
"homepage": "https://benramsey.com"
}
],
"description": "A PHP library for representing and manipulating collections.",
"keywords": [
"array",
"collection",
"hash",
"map",
"queue",
"set"
],
"support": {
"issues": "https://github.com/ramsey/collection/issues",
"source": "https://github.com/ramsey/collection/tree/1.3.0"
},
"funding": [
{
"url": "https://github.com/ramsey",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/ramsey/collection",
"type": "tidelift"
}
],
"time": "2022-12-27T19:12:24+00:00"
},
{
"name": "ramsey/uuid",
"version": "4.2.3",
"source": {
"type": "git",
"url": "https://github.com/ramsey/uuid.git",
"reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ramsey/uuid/zipball/fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df",
"reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df",
"shasum": ""
},
"require": {
"brick/math": "^0.8 || ^0.9",
"ext-json": "*",
"php": "^7.2 || ^8.0",
"ramsey/collection": "^1.0",
"symfony/polyfill-ctype": "^1.8",
"symfony/polyfill-php80": "^1.14"
},
"replace": {
"rhumsaa/uuid": "self.version"
},
"require-dev": {
"captainhook/captainhook": "^5.10",
"captainhook/plugin-composer": "^5.3",
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
"doctrine/annotations": "^1.8",
"ergebnis/composer-normalize": "^2.15",
"mockery/mockery": "^1.3",
"moontoast/math": "^1.1",
"paragonie/random-lib": "^2",
"php-mock/php-mock": "^2.2",
"php-mock/php-mock-mockery": "^1.3",
"php-parallel-lint/php-parallel-lint": "^1.1",
"phpbench/phpbench": "^1.0",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^0.12",
"phpstan/phpstan-mockery": "^0.12",
"phpstan/phpstan-phpunit": "^0.12",
"phpunit/phpunit": "^8.5 || ^9",
"slevomat/coding-standard": "^7.0",
"squizlabs/php_codesniffer": "^3.5",
"vimeo/psalm": "^4.9"
},
"suggest": {
"ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
"ext-ctype": "Enables faster processing of character classification using ctype functions.",
"ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.",
"ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.",
"paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
"ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type."
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "4.x-dev"
},
"captainhook": {
"force-install": true
}
},
"autoload": {
"files": [
"src/functions.php"
],
"psr-4": {
"Ramsey\\Uuid\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "A PHP library for generating and working with universally unique identifiers (UUIDs).",
"keywords": [
"guid",
"identifier",
"uuid"
],
"support": {
"issues": "https://github.com/ramsey/uuid/issues",
"source": "https://github.com/ramsey/uuid/tree/4.2.3"
},
"funding": [
{
"url": "https://github.com/ramsey",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/ramsey/uuid",
"type": "tidelift"
}
],
"time": "2021-09-25T23:10:38+00:00"
},
{
"name": "ramsey/uuid-doctrine",
"version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/ramsey/uuid-doctrine.git",
"reference": "b002676be0e5e342d857c47f1b68e24de6841d08"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ramsey/uuid-doctrine/zipball/b002676be0e5e342d857c47f1b68e24de6841d08",
"reference": "b002676be0e5e342d857c47f1b68e24de6841d08",
"shasum": ""
},
"require": {
"doctrine/dbal": "^2.8 || ^3.0",
"php": "^7.4 || ^8.0",
"ramsey/uuid": "^3.9.7 || ^4.0"
},
"require-dev": {
"captainhook/plugin-composer": "^5.3",
"doctrine/orm": "^2.5",
"ergebnis/composer-normalize": "^2.28.3",
"mockery/mockery": "^1.5",
"php-parallel-lint/php-console-highlighter": "^1.0",
"php-parallel-lint/php-parallel-lint": "^1.3",
"phpcsstandards/phpcsutils": "^1.0.0-alpha4",
"phpstan/extension-installer": "^1.2",
"phpstan/phpstan": "^1.9",
"phpstan/phpstan-mockery": "^1.1",
"phpstan/phpstan-phpunit": "^1.3",
"phpunit/phpunit": "^9.5",
"psalm/plugin-mockery": "^1.1",
"psalm/plugin-phpunit": "^0.18.4",
"ramsey/coding-standard": "^2.0.3",
"ramsey/conventional-commits": "^1.3",
"vimeo/psalm": "^5.4"
},
"type": "library",
"extra": {
"captainhook": {
"force-install": true
},
"ramsey/conventional-commits": {
"configFile": "conventional-commits.json"
}
},
"autoload": {
"psr-4": {
"Ramsey\\Uuid\\Doctrine\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ben Ramsey",
"email": "ben@benramsey.com",
"homepage": "https://benramsey.com"
}
],
"description": "Use ramsey/uuid as a Doctrine field type.",
"keywords": [
"database",
"doctrine",
"guid",
"identifier",
"uuid"
],
"support": {
"issues": "https://github.com/ramsey/uuid-doctrine/issues",
"source": "https://github.com/ramsey/uuid-doctrine/tree/2.0.0"
},
"funding": [
{
"url": "https://github.com/ramsey",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/ramsey/uuid-doctrine",
"type": "tidelift"
}
],
"time": "2022-12-20T23:38:28+00:00"
},
{
"name": "sabberworm/php-css-parser",
"version": "8.4.0",


+ 2
- 0
httpdocs/config/packages/doctrine.yaml Wyświetl plik

@@ -8,6 +8,8 @@ doctrine:
#server_version: '13'
mapping_types:
enum: string
types:
uuid: Symfony\Bridge\Doctrine\Types\UuidType
orm:
auto_generate_proxy_classes: true
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware


+ 4
- 0
httpdocs/config/packages/ramsey_uuid_doctrine.yaml Wyświetl plik

@@ -0,0 +1,4 @@
doctrine:
dbal:
types:
uuid: 'Ramsey\Uuid\Doctrine\UuidType'

BIN
httpdocs/import/mpp_import_din.xlsx Wyświetl plik


+ 55
- 108
httpdocs/public/assets/js/my-bim-score.js Wyświetl plik

@@ -1,9 +1,10 @@
$(document).ready(function() {
addUser();
listing();
catalogue();
onChangeDinAsset();
onFormSubmit();
onCalculate();
onWorksheet();
downloadWorksheet();
});

// Message Box for alerts
@@ -152,29 +153,20 @@ function onChangeDinAsset() {
});
}

function onFormSubmit() {
$("#submit").on("click", function(e) {
function onCalculate() {
$("#calculate").on("click", function (e) {
e.preventDefault();
let cycleVal = $("#cycle").val();
if (cycleVal === '') {
messageBox(false, "Bitte geben Sie Ihren aktuellen Zyklus ein.");
} else {
let cycleMin = parseInt($("#cycle").attr("min"));
if (cycleVal < cycleMin) {
$("#cycle").val(cycleMin);
messageBox(false, "Zyklus an Minimal-Wert '" + cycleMin + "' angepasst.");
}
let cycleMax = parseInt($("#cycle").attr("max"));
if (cycleVal > cycleMax) {
$("#cycle").val(cycleMax);
messageBox(false, "Zyklus an Maximal-Wert '" + cycleMax + "' angepasst.");
}
if (checkInputs()) {
$.ajax({
url: "/calculate-risk",
method: "post",
data: $('#form-risk').serializeArray(),
success: function (data) {
console.log(data);
$('#resInspection').text(data['recCycleInspection']);
$('#resMaintenance').text(data['recCycleMaintenance']);
$('#resPercentage').text(data['costDiffCurRecPercentage'] + " %");
$('#resEuro').text(data['costDiffCurCycleRecCycle'] + " €");
},
error: function (xhr, msg, three) {
messageBox(false, "Fehler bei der Anfrage.");
@@ -185,107 +177,62 @@ function onFormSubmit() {
});
}

let savedCatalogueAnswer,
savedCatalogueNote;
$(document).ready(function() {
savedCatalogueAnswer = $(".form--catalogue input[name='answer']:checked").val();
savedCatalogueNote = $("#inputNote").val();
});
function catalogueAjaxForm(form_data, isOpenQuestion) {
let ajaxRoute = isOpenQuestion ? "/catalogue-detail-unanswered" : "/catalogue-detail";
$.ajax({
url: ajaxRoute,
method: "get",
data: form_data,
success: function (data) {
$("#instruction").hide();
catalogueAnswer = data.catalogueDetail['answer'];
catalogueNote = data.catalogueDetail['note'];
$("[data-js='progressbar'] div").css("width", "calc(" + data.catalogue['numAnswers'] / data.catalogue['numDetails'] * 100% + ")");
$("[data-js='order-no']").text(data.catalogueDetail['orderNo']);
$("[data-js='question-type'] span").text(data.question['questionType']);
$("[data-js='question-text']").text(data.question['questionText']);
$("input[name='answer']").prop('checked', false);
if (catalogueAnswer != null) {
$("input[value='" + catalogueAnswer + "']").prop('checked', true);
savedCatalogueAnswer = catalogueAnswer;
} else {
savedCatalogueAnswer = (function () { return; })();
}
$("#inputNote").val("");
if (catalogueNote !== null) {
$("#inputNote").val(catalogueNote);
savedCatalogueNote = catalogueNote;
} else {
savedCatalogueNote = "";
}
},
error: function (xhr, msg, three) {
messageBox(false, "Fehler bei der Anfrage.");
},
dataType: "json"
});
}
function catalogue() {
$("[data-js='last-question'], [data-js='next-question']").on("click", function(e){
let form = $(this).parents(".form"),
form_data = form.serializeObject(),
isOpenQuestion = $(this).data("openquestion") === "yes";
form_data["direction"] = $(this).data("js") === "last-question" ? 'prev' : 'next';
if (savedCatalogueAnswer === form_data["answer"] && savedCatalogueNote === form_data["note"]) {
catalogueAjaxForm(form_data, isOpenQuestion);
} else {
confirmAction = confirm("Sie haben ungespeicherte Eingaben. Möchten Sie fortfahren?");
if (confirmAction === true) {
catalogueAjaxForm(form_data, isOpenQuestion);
}
}
});
$("[data-js='save-question']").on("click", function(e){
let form = $(this).parents(".form"),
form_data = form.serializeObject();
if ($("input[name='answer']:checked").val()) {
function onWorksheet() {
$("#worksheet").on("click", function (e) {
e.preventDefault();
if (checkInputs()) {
$.ajax({
url: "/catalogue-detail",
method: "patch",
data: form_data,
url: "/create-worksheet",
method: "post",
data: $('#form-risk').serializeArray(),
success: function (data) {
messageBox(true, "Ihre Antwort wurde gespeichert.");
$("[data-js='progressbar'] div").css("width", "calc(" + data.catalogue['numAnswers'] / data.catalogue['numDetails'] * 100 + "%)");
savedCatalogueAnswer = form_data["answer"];
savedCatalogueNote = form_data["note"];
if (data.catalogue['numAnswers'] === data.catalogue['numDetails']) {
$("[data-js='finish-catalogue']").prop("disabled", false);
}
console.log(data);
window.location = "/worksheet/" + data;
},
error: function (xhr, msg, three) {
messageBox(false, "Fehler bei der Anfrage.");
},
dataType: "json"
});
} else {
messageBox(false, "Bitte wählen Sie eine Antwort.");
}
});
}

$("[data-js='finish-catalogue']").on("click", function(e){
e.preventDefault();
let form = $(this).parents(".form"),
form_data = form.serializeObject();
if (confirm("Möchten Sie den Fragenkatalog abschließen? Änderungen sind danach nicht mehr möglich!") === true) {
$.ajax({
url: "/catalogue-finish",
method: "patch",
data: form_data,
success: function (data) {
window.location.href = "/catalogue-finished";
},
error: function (xhr, msg, three) {
messageBox(false, "Fehler bei der Anfrage.");
},
dataType: "json"
});
function checkInputs() {
let cycleVal = $("#cycle").val();
if (cycleVal === '') {
messageBox(false, "Bitte geben Sie Ihren aktuellen Zyklus ein.");
return false;
} else {
let cycleMin = parseInt($("#cycle").attr("min"));
if (cycleVal < cycleMin) {
$("#cycle").val(cycleMin);
messageBox(false, "Zyklus an Minimal-Wert '" + cycleMin + "' angepasst.");
}
let cycleMax = parseInt($("#cycle").attr("max"));
if (cycleVal > cycleMax) {
$("#cycle").val(cycleMax);
messageBox(false, "Zyklus an Maximal-Wert '" + cycleMax + "' angepasst.");
}
}
return true;
}

function downloadWorksheet() {
$("#download").on("click", function (e) {
e.preventDefault();
$.ajax({
url: "/create-worksheet",
method: "post",
data: $('#form-risk').serializeArray(),
success: function (data) {
console.log(data);
window.location = "/download/" + data;
},
error: function (xhr, msg, three) {
messageBox(false, "Fehler bei der Anfrage.");
},
dataType: "json"
});
});
}

+ 0
- 3
httpdocs/src/Command/CmdImportDinAssets.php Wyświetl plik

@@ -3,7 +3,6 @@
namespace App\Command;
use App\Entity\DinAsset;
use App\Entity\DinAssetTask;
use Doctrine\DBAL\Connection;
use Doctrine\ORM\EntityManagerInterface;
use PhpOffice\PhpSpreadsheet\IOFactory;
use Psr\Container\ContainerInterface;
@@ -92,8 +91,6 @@ class CmdImportDinAssets extends Command
$dinAsset->setName($rowData[1]);
$dinAsset->setCycleMonthsMin($rowData[11]);
$dinAsset->setCycleMonthsMax($rowData[12]);
$dinAsset->setCycleMonthsRecInspection($rowData[13]);
$dinAsset->setCycleMonthsRecMaintenance($rowData[14]);
$this->em->persist($dinAsset);
$this->em->flush();
$dinAssetsByDinAndName[$key] = $dinAsset;


+ 88
- 260
httpdocs/src/Controller/UserController.php Wyświetl plik

@@ -7,19 +7,20 @@
*/
namespace App\Controller;

use App\Entity\Catalogue;
use App\Entity\CatalogueDetail;
use App\Entity\DinAsset;
use App\Entity\DinAssetBenchmark;
use App\Entity\DinAssetTask;
use App\Entity\User;
use App\Entity\UserWorksheet;
use App\Entity\UserWorksheetTask;
use App\Repository\UserRepository;
use App\Service\CalculatorService;
use App\Utils\Utils;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Serializer\SerializerInterface;
use Twig\Environment;

/**
@@ -27,12 +28,6 @@ use Twig\Environment;
*/
class UserController extends AbstractController
{
private $serializer;

public function __construct(SerializerInterface $serializer)
{
$this->serializer = $serializer;
}

/**
* @Route("/start", name="start")
@@ -41,24 +36,14 @@ class UserController extends AbstractController
{
/** @var User $user */
$user = $this->getUser();
$catalogues = $user->getCatalogues();
$userHasUnfinishedCatalogue = false;
$userHasFinishedCatalogue = false;
/** @var Catalogue $catalogue */
foreach ($catalogues as $catalogue) {
if (!$catalogue->getFinished() && !$userHasUnfinishedCatalogue) {
$userHasUnfinishedCatalogue = true;
}
if ($catalogue->getFinished() && !$userHasFinishedCatalogue) {
$userHasFinishedCatalogue = true;
}
}

$cntWorksheets = count($user->getWorksheets());
$numWorksheetsLeft = $user->getMaxWorksheets() - $cntWorksheets;

return $this->render('pages/start.html.twig',
[
'userHasUnfinishedCatalogue' => $userHasUnfinishedCatalogue,
'userHasFinishedCatalogue' => $userHasFinishedCatalogue,
'noMoreCatalogues' => !$userHasUnfinishedCatalogue && count($catalogues) >= $user->getMaxCatalogues()
'worksheets' => $user->getWorksheets(),
'numWorksheetsLeft' => $numWorksheetsLeft,
]
);
}
@@ -110,7 +95,6 @@ class UserController extends AbstractController
}

$res = [];
$res['cycleRecommended'] = $dinAsset->getCycleMonthsRecInspection();
$res['cycleMin'] = $dinAsset->getCycleMonthsMin();
$res['cycleMax'] = $dinAsset->getCycleMonthsMax();
$res['benchmarkValues'] = $dinAsset->getBenchMarkSelectValues();
@@ -120,288 +104,132 @@ class UserController extends AbstractController
/**
* @Route("/calculate-risk", name="calculate_risk")
*/
public function calculateRisk(Request $request)
public function calculateRisk(Request $request, CalculatorService $calculatorService)
{
$params = $request->request->all();
$benchmark = $this->getDoctrine()->getRepository(DinAssetBenchmark::class)->find($params['benchmark']);
/** @var DinAsset $asset */
$asset = $benchmark->getDinAsset();
$userCycle = $params['cycle'];

$pointsFailure = Utils::$riskFailure[$params['failure']][1];
$pointsCosts = Utils::$riskCosts[$params['costs']][1];
if ($params['costs'] === Utils::PERSON_DAMAGE_INDEX) {
$pointsCosts = Utils::PERSON_DAMAGE_BASE - $pointsFailure;
}
$riskPoints = $pointsFailure + $pointsCosts;
$riskFactor = Utils::$riskPoints[$riskPoints]['factor'];

$recCycleMaintenance = $asset->getCycleMonthsMax();
if ( ((int)$params['maintenance']) === 1 && ((int)$params['check']) === 1 ) {
$recCycleMaintenance = (int) ($asset->getCycleMonthsMax() * $riskFactor);
if ($recCycleMaintenance < $asset->getCycleMonthsMin()) {
$recCycleMaintenance = $asset->getCycleMonthsMin();
}
}
$costsCurrentPerYear = (12 / $userCycle) * $benchmark->getAverageCosts();
$costsRecPerYear = (12 / $recCycleMaintenance) * $benchmark->getAverageCosts();

$recCycleInspection = $asset->getCycleMonthsMax();
if ( ((int)$params['inspection']) === 1 ) {
$recCycleInspection = (int) ($asset->getCycleMonthsMax() * $riskFactor);
if ($recCycleInspection < $asset->getCycleMonthsMin()) {
$recCycleInspection = $asset->getCycleMonthsMin();
}
}
$costDiffCurCycleRecCycle = $costsCurrentPerYear - $costsRecPerYear;
$costDiffCurRecPercentage = 1 - ($userCycle / $recCycleMaintenance);

$res['recCycleMaintenance'] = $recCycleMaintenance;
$res['recCycleInspection'] = $recCycleInspection;
$res['costDiffCurCycleRecCycle'] = $costDiffCurCycleRecCycle;
$res['costDiffCurRecPercentage'] = $costDiffCurRecPercentage;
$benchMark = $this->getDoctrine()->getRepository(DinAssetBenchmark::class)->find($params['benchmark']);
$res = $calculatorService->calculateRisk($benchMark, $params);
return $this->json($res);
}

/**
* @Route("/download", name="download")
*
* @param Environment $twig
* @return \Symfony\Component\HttpFoundation\JsonResponse
* @throws \Twig\Error\LoaderError
* @throws \Twig\Error\RuntimeError
* @throws \Twig\Error\SyntaxError
* @Route("/create-worksheet", name="create_worksheet")
*/
public function downloadLastCataloguePdf(Environment $twig)
public function createWorksheet(Request $request, CalculatorService $calculatorService)
{
/** @var User $user */
$user = $this->getUser();
$catalogues = $this->getDoctrine()->getRepository(Catalogue::class)->findBy(['user' => $user]);

/** @var Catalogue $catalogue */
$catalogue = null;
/** @var Catalogue $cat */
foreach ($catalogues as $cat) {
if ($cat->getFinished()) {
$catalogue = $cat;
}
}

if ($catalogue === null) {
return $this->json('Kein abgeschlossener Katalog vorhanden', 409);
}

$dompdf = UserRepository::renderCatalogue($this->get('twig'), $catalogue);

// Output the generated PDF to Browser (force download)
$fileName = "Fragenkatalog_".$catalogue->getFinishDate()->format('Y-m-d_H-i');
$dompdf->stream($fileName, [
"Attachment" => true
]);
// NOTE: This is required, since method need a result!
exit(0);
}

/**
* @Route("/catalogue", name="catalogue")
*
* @return \Symfony\Component\HttpFoundation\Response
* @throws \Exception
*/
public function showCatalogue()
{
$em = $this->getDoctrine()->getManager();

/** @var User $user */
$user = $this->getUser();

/** @var Catalogue $catalogue */
$catalogue = $user->getActiveCatalogue();
if ($catalogue === null) {
$catalogue = $user->addNewCatalogue($em);
$em->flush();
}

$catalogueDetail = $catalogue->getCurrentCatalogueDetail();
$question = $catalogueDetail->getQuestion();
$questionType = $question->getQuestionType();
return $this->render('pages/catalogue.html.twig',
[
'catalogue' => $catalogue,
'catalogueDetail' => $catalogueDetail,
'question' => $question,
'questionType' => $questionType
]
);
}

/**
* @Route("/catalogue-detail", name="catalogue_detail_step", methods={"GET"})
*
* @param Request $request
* @return \Symfony\Component\HttpFoundation\Response
*/
public function catalogueDetail(Request $request)
{
$content = (object) $request->query->all();
$direction = $content->direction;
if ($direction !== 'next' && $direction !== 'prev') {
return $this->json('invalid direction', 409);
}

/** @var User $user */
$user = $this->getUser();
$em = $this->getDoctrine()->getManager();
$catalogue = $user->getActiveCatalogue();
if ($catalogue === null) {
return $this->json('Kein aktiver Fragenkatalog vorhanden', 409);
if (count($user->getWorksheets()) >= $user->getMaxWorksheets()) {
return new JsonResponse(null, JsonResponse::HTTP_BAD_REQUEST);
}
$params = $request->request->all();
$benchMark = $em->getRepository(DinAssetBenchmark::class)->find($params['benchmark']);
$calculation = $calculatorService->calculateRisk($benchMark, $params);

$currentCatalogueDetail = $catalogue->getCurrentCatalogueDetail();
/** @var CatalogueDetail $resCatalogueDetail */
$resCatalogueDetail = $direction === 'next' ? $currentCatalogueDetail->getNextCatalogueDetail() : $currentCatalogueDetail->getPrevCatalogueDetail();
if ($resCatalogueDetail === null) {
return $this->json('Katalogeintrag existiert nicht', 409);
}
$catalogue->setCurrentCatalogueDetail($resCatalogueDetail);
$em->flush();
return $this->json(
[
'catalogue' => $catalogue->clientMapper(),
'catalogueDetail' => $resCatalogueDetail->clientMapper(),
'question' => $resCatalogueDetail->getQuestion()->clientMapper(),
]
);
}
$benchmark = $em->getRepository(DinAssetBenchmark::class)->find($params['benchmark']);
/** @var DinAsset $asset */
$asset = $benchmark->getDinAsset();
$assetTasks = $asset->getTasks();

/**
* @Route("/catalogue-detail-unanswered", name="catalogue_detail_unanswered_step", methods={"GET"})
*
* @param Request $request
* @return \Symfony\Component\HttpFoundation\Response
*/
public function catalogueDetailUnanswered(Request $request)
{
$content = (object) $request->query->all();
$direction = $content->direction;
if ($direction !== 'next' && $direction !== 'prev') {
return $this->json('invalid direction', 409);
}
$em->getConnection()->beginTransaction();

/** @var User $user */
$user = $this->getUser();
$em = $this->getDoctrine()->getManager();
$catalogue = $user->getActiveCatalogue();
if ($catalogue === null) {
return $this->json('Kein aktiver Fragenkatalog vorhanden', 409);
}
try {
$worksheet = new UserWorksheet($user);
$worksheet->setDinNumber($asset->getDinNumber());
$worksheet->setDinAssetName($asset->getName());
$worksheet->setFailureProbability(Utils::$riskFailure[$params['failure']][0]);
$worksheet->setFailureDamage(Utils::$riskCosts[$params['costs']][0]);
$worksheet->setMaintenanceAdvantage($params['maintenance']);
$worksheet->setInspectionAdvantage($params['inspection']);
$worksheet->setCheckAdvantage($params['check']);
$worksheet->setUserCycleMonths($params['cycle']);
$worksheet->setBandwidth($benchmark->getBandwidth());
$worksheet->setRecMaintenanceCycleMonths($calculation['recCycleMaintenance']);
$worksheet->setRecInspectionCycleMonths($calculation['recCycleInspection']);
$worksheet->setDeviationPercentage($calculation['costDiffCurRecPercentage']);
$worksheet->setDeviationCosts($calculation['costDiffCurCycleRecCycle']);

$em->persist($worksheet);
$em->flush();

$currentCatalogueDetail = $catalogue->getCurrentCatalogueDetail();
/** @var CatalogueDetail $tmpCatalogueDetail */
$tmpCatalogueDetail = $direction === 'next' ? $currentCatalogueDetail->getNextCatalogueDetail() : $currentCatalogueDetail->getPrevCatalogueDetail();
while($tmpCatalogueDetail->getId() !== $currentCatalogueDetail->getId()) {
if ($tmpCatalogueDetail->getAnswer() === null) {
$catalogue->setCurrentCatalogueDetail($tmpCatalogueDetail);
/** @var DinAssetTask $assetTask */
foreach ($assetTasks as $assetTask) {
$worksheetTask = new UserWorksheetTask();
$worksheetTask->setUserWorksheet($worksheet);
$worksheetTask->setDelimitation($assetTask->getDelimitation());
$worksheetTask->setTask($assetTask->getTask());
$worksheetTask->setInspection($assetTask->getInspection());
$worksheetTask->setMaintenance($assetTask->getMaintenance());
$worksheetTask->setService($assetTask->getService());
$worksheetTask->setExpert($assetTask->getExpert());
$worksheetTask->setSpecialist($assetTask->getSpecialist());
$worksheetTask->setSkilledPersonnel($assetTask->getSkilledPersonnel());
$worksheetTask->setNorm($assetTask->getNorm());
$em->persist($worksheetTask);
$em->flush();
return $this->json(
[
'catalogue' => $catalogue->clientMapper(),
'catalogueDetail' => $tmpCatalogueDetail->clientMapper(),
'question' => $tmpCatalogueDetail->getQuestion()->clientMapper(),
]
);
}
$tmpCatalogueDetail = $direction === 'next' ? $tmpCatalogueDetail->getNextCatalogueDetail() : $tmpCatalogueDetail->getPrevCatalogueDetail();
$em->flush();
$em->getConnection()->commit();

} catch (\Exception $e) {
$em->getConnection()->rollBack();
return new JsonResponse(null, JsonResponse::HTTP_BAD_REQUEST);
}

return $this->json('Kein Eintrag gefunden', 409);
return new JsonResponse($worksheet->getId(), JsonResponse::HTTP_OK);
}

/**
* @Route("/catalogue-detail", name="catalogue_detail_save", methods={"PATCH"})
*
* @param Request $request
* @return \Symfony\Component\HttpFoundation\Response
* @Route("/worksheet/{uuid}", name="show_worksheet")
*/
public function catalogueDetailSave(Request $request)
public function showWorksheet($uuid)
{
$content = (object) $request->request->all();

/** @var User $user */
$user = $this->getUser();
$em = $this->getDoctrine()->getManager();
$catalogue = $user->getActiveCatalogue();
if ($catalogue === null) {
return $this->json('Kein aktiver Fragenkatalog vorhanden', 409);
}

$currentCatalogueDetail = $catalogue->getCurrentCatalogueDetail();
try {
$currentCatalogueDetail->setAnswer($content->answer);
} catch (\Exception $e) {
return $this->json('Invalide Antwort', 409);
}
/** @var UserWorksheet $worksheet */
$worksheet = $em->getRepository(UserWorksheet::class)->findOneBy(['id' => $uuid]);

$currentCatalogueDetail->setNote($content->note);
$em->flush();
if (null === $worksheet || $user->getId() !== $worksheet->getUser()->getId()) {
throw new \Exception('not allowed or not exists');
}

return $this->json(
return $this->render('pages/worksheet.html.twig',
[
'success' => true,
'catalogue' => $catalogue->clientMapper(),
'worksheet' => $worksheet,
'isPdf' => false
]
);
}

/**
* @Route("/catalogue-finish", name="catalogue_finish", methods={"PATCH"})
*
* @param Request $request
* @return \Symfony\Component\HttpFoundation\Response
* @Route("/download/{uuid}", name="download")
*/
public function finishCatalog()
public function downloadLastCataloguePdf(Environment $twig, $uuid)
{
/** @var User $user */
$user = $this->getUser();
$em = $this->getDoctrine()->getManager();
$catalogue = $user->getActiveCatalogue();
if ($catalogue === null) {
return $this->json('Kein aktiver Fragenkatalog vorhanden', 409);
}

try {
$catalogue->setFinished();
} catch (\Exception $e) {
return $this->json('Nicht alle Fragen beantwortet', 409);
}
$em->flush();
return $this->json(true);
}
/** @var UserWorksheet $worksheet */
$worksheet = $em->getRepository(UserWorksheet::class)->findOneBy(['id' => $uuid]);

/**
* @Route("/catalogue-finished", name="catalogue_finished", methods={"GET"})
*
* @param Request $request
* @return \Symfony\Component\HttpFoundation\Response
*/
public function finishedCatalog()
{
/** @var User $user */
$user = $this->getUser();

$catalogues = $user->getCatalogues();
$numFinishedCatalogues = 0;
/** @var Catalogue $catalogue */
foreach ($catalogues as $catalogue) {
$numFinishedCatalogues += $catalogue->getFinished() ? 1 : 0;
if (null === $worksheet || $user->getId() !== $worksheet->getUser()->getId()) {
throw new \Exception('not allowed or not exists');
}

return $this->render('pages/catalogue_finished.html.twig',
[
'remainingCatalogues' => $user->getMaxCatalogues() - $numFinishedCatalogues,
'remainingDays' => $userExpiryDays = (new \DateTime('now'))->diff($user->getValidUntilDate())->days
]
);
$dompdf = UserRepository::renderCatalogue($twig, $worksheet);

// Output the generated PDF to Browser (force download)
$fileName = "Arbeitskarte_".$worksheet->getCreationDate()->format('Y-m-d_H-i');
$dompdf->stream($fileName, [
"Attachment" => true
]);
// NOTE: This is required, since method need a result!
exit(0);
}

/**


+ 0
- 222
httpdocs/src/Entity/Catalogue.php Wyświetl plik

@@ -1,222 +0,0 @@
<?php

namespace App\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\PersistentCollection;
use Doctrine\Persistence\ObjectManager;

/**
* @ORM\Entity
* @ORM\Table(name="catalogue")
*/
class Catalogue
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
protected $id;

/**
* @ORM\ManyToOne(targetEntity="User", inversedBy="catalogues")
* @ORM\JoinColumn(name="user", referencedColumnName="id")
*/
protected $user;

/**
* @ORM\OneToMany(targetEntity="CatalogueDetail", mappedBy="catalogue", cascade={"persist", "remove"})
*/
private $catalogueDetails;

/**
* One Product has One Shipment.
* @ORM\OneToOne(targetEntity="CatalogueDetail")
* @ORM\JoinColumn(name="current_catalogue_detail", referencedColumnName="id")
*/
private $currentCatalogueDetail;

/**
* @ORM\Column(type="smallint", nullable=false, options={"unsigned" = true})
*/
protected $numDetails;

/**
* @ORM\Column(type="boolean", nullable=false)
*/
protected $finished;

/**
* @ORM\Column(type="datetime", nullable=true)
*/
protected $finish_date;

/**
* @ORM\Column(type="datetime", nullable=false)
*/
protected $creation_date;

public function __construct(ObjectManager $em, User $user)
{
/** @var Catalogue $catalogue */
$this->user = $user;
$this->finished = false;
$this->creation_date = new \DateTime('now', new \DateTimeZone('Europe/Berlin'));
$questions = $em->getRepository(Question::class)->findBy([], ['questionType' => 'ASC', 'id' => 'ASC']);
$this->numDetails = count($questions);

$this->catalogueDetails = new ArrayCollection();
$newCatalogueDetails = [];
$i = 1;
/** @var Question $question */
foreach ($questions as $question) {
$newCatalogueDetails[] = new CatalogueDetail($question, $i);
$i++;
}

$i = 0;
$cntDetails = count($newCatalogueDetails);
/** @var CatalogueDetail $newCatalogueDetail */
foreach ($newCatalogueDetails as $newCatalogueDetail) {
if ($i === 0) {
// First element, set last element as previous
$this->currentCatalogueDetail = $newCatalogueDetail;
$newCatalogueDetail->setPrevCatalogueDetail($newCatalogueDetails[$cntDetails-1]);
}
if ($i > 0) {
$newCatalogueDetail->setPrevCatalogueDetail($newCatalogueDetails[$i-1]);
}
if ($i < ($cntDetails - 1)) {
$newCatalogueDetail->setNextCatalogueDetail($newCatalogueDetails[$i+1]);
}
if ($i === ($cntDetails - 1)) {
// First element, set first element as next
$newCatalogueDetail->setNextCatalogueDetail($newCatalogueDetails[0]);
}
$this->catalogueDetails->add($newCatalogueDetail);
$newCatalogueDetail->setCatalogue($this);
$i++;
}
}

/**
* @return mixed
*/
public function getId()
{
return $this->id;
}

/**
* @return mixed
*/
public function getUser()
{
return $this->user;
}

/**
* @return PersistentCollection
*/
public function getCatalogueDetails(): Collection
{
return $this->catalogueDetails;
}

/**
* @param Collection $catalogueDetails
*/
public function setCatalogueDetails(Collection $catalogueDetails): void
{
$this->catalogueDetails = $catalogueDetails;
}

/**
* @return CatalogueDetail
*/
public function getCurrentCatalogueDetail(): CatalogueDetail
{
return $this->currentCatalogueDetail;
}

/**
* @param CatalogueDetail $currentCatalogueDetail
*/
public function setCurrentCatalogueDetail(CatalogueDetail $currentCatalogueDetail): void
{
$this->currentCatalogueDetail = $currentCatalogueDetail;
}

/**
* @return mixed
*/
public function getNumDetails()
{
return $this->numDetails;
}

/**
* @param mixed $numDetails
*/
public function setNumDetails($numDetails): void
{
$this->numDetails = $numDetails;
}

/**
* @return false
*/
public function getFinished(): bool
{
return $this->finished;
}

/**
* @throws \Exception
*/
public function setFinished(): void
{
if ($this->getNumAnswers() !== $this->numDetails) {
throw new \Exception('catalogue not finishable');
}
$this->finish_date = new \DateTime();
$this->finished = true;
}

/**
* @return mixed
*/
public function getFinishDate()
{
return $this->finish_date;
}

/**
* @return \DateTime
*/
public function getCreationDate(): \DateTime
{
return $this->creation_date;
}

public function getNumAnswers()
{
$numAnswers = 0;
/** @var CatalogueDetail $catalogueDetail */
foreach ($this->catalogueDetails as $catalogueDetail) {
$numAnswers += $catalogueDetail->getAnswer() !== null ? 1 : 0;
}
return $numAnswers;
}

public function clientMapper()
{
return [
'numAnswers' => $this->getNumAnswers(),
'numDetails' => $this->numDetails,
];
}
}

+ 0
- 214
httpdocs/src/Entity/CatalogueDetail.php Wyświetl plik

@@ -1,214 +0,0 @@
<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Entity
* @ORM\Table(name="catalogue_detail")
*/
class CatalogueDetail
{
const ANSWER_FULFILLED = 'fulfilled';
const ANSWER_PARTLY_FULFILLED = 'partly_fulfilled';
const ANSWER_WIDELY_FULFILLED = 'widely_fulfilled';
const ANSWER_NOT_FULFILLED = 'not_fulfilled';
const ANSWER_IRRELEVANT = 'irrelevant';

public static $validAnswers = array(
self::ANSWER_FULFILLED => 1, self::ANSWER_WIDELY_FULFILLED => 0.66, self::ANSWER_PARTLY_FULFILLED => 0.33, self::ANSWER_NOT_FULFILLED => 0, self::ANSWER_IRRELEVANT => 0,
);

/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
protected $id;

/**
* @ORM\ManyToOne(targetEntity="Catalogue", inversedBy="catalogueDetails")
* @ORM\JoinColumn(name="catalogue_id", referencedColumnName="id", onDelete="SET NULL")
*/
protected $catalogue;

/**
* @ORM\ManyToOne(targetEntity="CatalogueDetail")
* @ORM\JoinColumn(name="prev_catalogue_detail", referencedColumnName="id", onDelete="SET NULL")
*/
protected $prevCatalogueDetail;

/**
* @ORM\ManyToOne(targetEntity="CatalogueDetail")
* @ORM\JoinColumn(name="next_catalogue_detail", referencedColumnName="id", onDelete="SET NULL")
*/
protected $nextCatalogueDetail;

/**
* @ORM\ManyToOne(targetEntity="Question")
* @ORM\JoinColumn(name="question", referencedColumnName="id")
*/
protected $question;

/**
* @ORM\Column(name="answer", type="string", columnDefinition="enum('fulfilled', 'not_fulfilled', 'partly_fulfilled', 'widely_fulfilled', 'irrelevant')", nullable=true)
*/
protected $answer;

/**
* @ORM\Column(type="smallint", nullable=false, options={"unsigned" = true})
*/
protected $orderNo;

/**
* @ORM\Column(type="text", nullable=true)
*/
protected $note;

/**
* CatalogueDetail constructor.
* @param Question $question
* @param $orderNo
* @param CatalogueDetail|null $prevCatalogueDetail
* @param CatalogueDetail|null $nextCatalogueDetail
*/
public function __construct(Question $question, $orderNo)
{
$this->question = $question;
$this->orderNo = $orderNo;
}

/**
* @return mixed
*/
public function getId()
{
return $this->id;
}

/**
* @return mixed
*/
public function getCatalogue()
{
return $this->catalogue;
}

/**
* @param mixed $catalogue
*/
public function setCatalogue($catalogue): void
{
$this->catalogue = $catalogue;
}

/**
* @return mixed
*/
public function getPrevCatalogueDetail()
{
return $this->prevCatalogueDetail;
}

/**
* @param mixed $prevCatalogueDetail
*/
public function setPrevCatalogueDetail($prevCatalogueDetail): void
{
$this->prevCatalogueDetail = $prevCatalogueDetail;
}

/**
* @return mixed
*/
public function getNextCatalogueDetail()
{
return $this->nextCatalogueDetail;
}

/**
* @param mixed $nextCatalogueDetail
*/
public function setNextCatalogueDetail($nextCatalogueDetail): void
{
$this->nextCatalogueDetail = $nextCatalogueDetail;
}

/**
* @return Question
*/
public function getQuestion(): Question
{
return $this->question;
}

/**
* @param Question $question
*/
public function setQuestion(Question $question): void
{
$this->question = $question;
}

/**
* @return mixed
*/
public function getAnswer()
{
return $this->answer;
}

/**
* @param mixed $answer
*/
public function setAnswer($answer): void
{
if (!array_key_exists($answer, self::$validAnswers)) {
throw new \Exception('invalid answer');
}
$this->answer = $answer;
}

/**
* @return mixed
*/
public function getOrderNo()
{
return $this->orderNo;
}

/**
* @param mixed $orderNo
*/
public function setOrderNo($orderNo): void
{
$this->orderNo = $orderNo;
}

/**
* @return mixed
*/
public function getNote()
{
return $this->note;
}

/**
* @param mixed $note
*/
public function setNote($note): void
{
$this->note = $note;
}

public function clientMapper()
{
return [
'answer' => $this->answer,
'orderNo' => $this->orderNo,
'note' => $this->note
];
}
}

+ 2
- 50
httpdocs/src/Entity/DinAsset.php Wyświetl plik

@@ -37,25 +37,15 @@ class DinAsset
*/
protected $cycleMonthsMax;

/**
* @ORM\Column(type="smallint", nullable=false, options={"unsigned" = true})
*/
protected $cycleMonthsRecInspection;

/**
* @ORM\Column(type="smallint", nullable=false, options={"unsigned" = true})
*/
protected $cycleMonthsRecMaintenance;

/**
* @ORM\OneToMany(targetEntity="DinAssetTask", mappedBy="dinAsset", cascade={"persist", "remove"})
*/
private $tasks;
protected $tasks;

/**
* @ORM\OneToMany(targetEntity="DinAssetBenchmark", mappedBy="dinAsset", cascade={"persist", "remove"})
*/
private $benchmarks;
protected $benchmarks;

/**
* @return mixed
@@ -137,44 +127,6 @@ class DinAsset
$this->cycleMonthsMax = $cycleMonthsMax;
}

/**
* @return mixed
*/
public function getCycleMonthsRecInspection()
{
return $this->cycleMonthsRecInspection;
}

/**
* @param mixed $cycleMonthsRecInspection
*/
public function setCycleMonthsRecInspection($cycleMonthsRecInspection): void
{
if ($cycleMonthsRecInspection <= 0) {
throw new \Exception('invalid value');
}
$this->cycleMonthsRecInspection = $cycleMonthsRecInspection;
}

/**
* @return mixed
*/
public function getCycleMonthsRecMaintenance()
{
return $this->cycleMonthsRecMaintenance;
}

/**
* @param mixed $cycleMonthsRecMaintenance
*/
public function setCycleMonthsRecMaintenance($cycleMonthsRecMaintenance): void
{
if ($cycleMonthsRecMaintenance <= 0) {
throw new \Exception('invalid value');
}
$this->cycleMonthsRecMaintenance = $cycleMonthsRecMaintenance;
}

/**
* @return mixed
*/


+ 0
- 96
httpdocs/src/Entity/Question.php Wyświetl plik

@@ -1,96 +0,0 @@
<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Entity
* @ORM\Table(name="question")
*/
class Question
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
protected $id;

/**
* @ORM\ManyToOne(targetEntity="QuestionType")
* @ORM\JoinColumn(name="question_type", referencedColumnName="id")
*/
protected $questionType;

/**
* @ORM\Column(name="question_text", length=4096, nullable=true)
*/
protected $questionText;

/**
* @ORM\Column(type="smallint", nullable=false, options={"unsigned" = true})
*/
protected $weight;

public function __construct(QuestionType $questionType)
{
$this->questionType = $questionType;
}

/**
* @return mixed
*/
public function getId()
{
return $this->id;
}

/**
* @return mixed
*/
public function getQuestionType()
{
return $this->questionType;
}

/**
* @return mixed
*/
public function getQuestionText()
{
return $this->questionText;
}

/**
* @param mixed $questionText
*/
public function setQuestionText($questionText): void
{
$this->questionText = $questionText;
}

/**
* @return mixed
*/
public function getWeight()
{
return $this->weight;
}

/**
* @param mixed $weight
*/
public function setWeight($weight): void
{
$this->weight = $weight;
}

public function clientMapper()
{
return [
'questionType' => $this->questionType->getType(),
'questionText' => $this->questionText,
];
}
}

+ 0
- 151
httpdocs/src/Entity/QuestionType.php Wyświetl plik

@@ -1,151 +0,0 @@
<?php

namespace App\Entity;
use Symfony\Component\Config\Definition\Exception\Exception;

use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Entity
* @ORM\Table(name="question_type")
*/
class QuestionType
{
const RES_A = 'a';
const RES_B = 'b';
const RES_C = 'c';
const RES_D = 'd';
const RES_E = 'e';

// Text for results of result pdf per category id
public static $txtResultPerType = [
1 => [
self::RES_A => 'Sie haben keines der Kriterien in diesem Handlungsfeld als relevant für Ihre Organisation eingestuft!',
self::RES_B => 'Die benötigten Rahmenbedingungen (organisatorische, strategische, vertragliche bzw. finanzielle Voraussetzungen) sind nicht gegeben.',
self::RES_C => 'Die benötigten Rahmenbedingungen (organisatorische, strategische, vertragliche bzw. finanzielle Voraussetzungen) sind teilweise gegeben.',
self::RES_D => 'Die benötigten Rahmenbedingungen (organisatorische, strategische, vertragliche bzw. finanzielle Voraussetzungen) sind weitgehend gegeben.',
self::RES_E => 'Die benötigten Rahmenbedingungen (organisatorische, strategische, vertragliche bzw. finanzielle Voraussetzungen) sind gegeben.',
],
2 => [
self::RES_A => 'Sie haben keines der Kriterien in diesem Handlungsfeld als relevant für Ihre Organisation eingestuft!',
self::RES_B => 'Die notwendigen Abläufe sind nicht geregelt.',
self::RES_C => 'Die notwendigen Abläufe sind teilweise geregelt.',
self::RES_D => 'Die notwendigen Abläufe sind weitgehend geregelt.',
self::RES_E => 'Die notwendigen Abläufe sind geregelt.',
],
3 => [
self::RES_A => 'Sie haben keines der Kriterien in diesem Handlungsfeld als relevant für Ihre Organisation eingestuft!',
self::RES_B => 'Die erforderlichen personellen Ressourcen sind nicht vorhanden.',
self::RES_C => 'Die erforderlichen personellen Ressourcen sind teilweise vorhanden.',
self::RES_D => 'Die erforderlichen personellen Ressourcen sind weitgehend vorhanden.',
self::RES_E => 'Die erforderlichen personellen Ressourcen sind vorhanden.',
],
4 => [
self::RES_A => 'Sie haben keines der Kriterien in diesem Handlungsfeld als relevant für Ihre Organisation eingestuft!',
self::RES_B => 'Die erforderlichen technischen Voraussetzungen sind nicht erfüllt.',
self::RES_C => 'Die erforderlichen technischen Voraussetzungen sind teilweise erfüllt.',
self::RES_D => 'Die erforderlichen technischen Voraussetzungen sind weitgehend erfüllt.',
self::RES_E => 'Die erforderlichen technischen Voraussetzungen sind erfüllt.',
]
];

// Text for actions of result pdf per category id
public static $txtActionPerType = [
1 => [
self::RES_A => 'Überprüfen Sie bitte Ihre Antworten. Es ist sehr unwahrscheinlich, dass keines der Kriterien in diesem Handlungsfeld für Ihre Organisation relevant ist.',
self::RES_B => 'Soweit noch nicht geschehen, definieren Sie die für Ihre Organisation relevanten Anwendungsfälle und ermitteln Sie den Mehrwert sowie den Aufwand einer Einführung/Anwendung der BIM-Methodik.',
self::RES_C => 'Legen Sie anhand der ermittelten Mehrwerte und definierten Anwendungsfälle die BIM-Ziele und BIM-Strategie (ggf. auch BIM2FIELD und BIM2FM) für Ihre Organisation fest. Erstellen Sie eine Roadmap/ einen Aktionsplan zur schrittweisen Umsetzung der Strategie und Zielerreichung und sorgen Sie für eine Bereitstellung der für die Einführung der BIM-Methodik benötigten Finanzmittel. Berücksichtigen Sie BIM-spezifische Aufgaben in Ihrer Aufbauorganisation. Definieren Sie die übergeordneten (Organisations- und Asset-bezogenen) sowie projektspezifischen Informationsanforderungen und erstellen Sie BIM-spezifische vertragliche Regelungen oder Vertragsdokumente. ',
self::RES_D => 'Evaluieren Sie die Wirksamkeit durchgeführter Maßnahmen aus der Roadmap/des Aktionsplans zur Einführung der BIM-Methodik (wie die Anpassung der Aufbauorganisation, das Definieren von Informationsanforderungen, Regelungen in Verträgen, das Bereitstellen finanzieller Ressourcen). Schließen Sie identifizierte Lücken in der Roadmap und klären Sie ggf. aufgetretene Widersprüche. Sammeln und analysieren Sie Erfahrungen, indem Sie z. B. Pilotprojekte durchführen.',
self::RES_E => 'Überprüfen Sie, inwieweit Sie die mit der Anwendung der BIM-Methodik verknüpften Ziele bereits erreicht haben. Schließen Sie eventuell noch vorhandene Lücken in der Roadmap und initiieren Sie auf Basis von in durchgeführten Pilotprojekten gewonnenen lessons learned zusätzliche Verbesserungsmaßnahmen.',
],
2 => [
self::RES_A => 'Überprüfen Sie bitte Ihre Antworten. Es ist sehr unwahrscheinlich, dass keines der Kriterien in diesem Handlungsfeld für Ihre Organisation relevant ist.',
self::RES_B => 'Regeln Sie zunächst die zugehörigen elementaren Prozesse vor allem (zunächst) zur Koordination der verschiedenen Fachdisziplinen/-bereiche mit Ihren separaten IT-Systemen im Planen, Bauen und Betreiben. Legen Sie auch die Grundlagen zur Lenkung dokumentierter Informationen (Daten, Modelle und Dokumente und deren Austausch in Papierform oder als elektronische Dokumente) und der Kommunikation fest.',
self::RES_C => 'Überarbeiten Sie die vorhandenen Prozessbeschreibungen für das Planen, Bauen und Betreiben hinsichtlich der Unterstützung durch die IT-Systeme und der Lenkung dokumentierter Informationen bei einer objektbasierten Modellierung (Daten, Modelle und Dokumente in 2D und/oder 3D) sowie den Austausch zwischen den Systemen. Standardisieren Sie dazu die Datenstrukturen und -formate (Klassifizierung und Attributierung von Objekten sowie deren Beziehungen/Hierarchien zur Vererbung, Austauschformate) für Ihre Organisation. Ergänzen Sie auch noch fehlende Ablaufregelungen.',
self::RES_D => 'Überprüfen Sie die Regelungen für Prozesse des Planens, Bauens und Betreibens sowie deren Umsetzung und die Unterstützung der Workflows durch IT-Systeme. Treffen bzw. konkretisieren Sie dabei Festlegungen zur Prüfung und Koordination von Daten und Modellen, zur Ermittlung von Herstell- und Nutzungskosten, zum geforderten Informationsgehalt an Meilensteinen und beim FM-Handover, zum Umfang der zu pflegenden Bestands- und Prozessdaten sowie betriebsrelevanter Dokumente und zu Eignungskriterien für externe Partner sowie zum Frontloading durch Betreiber/Nutzer. Stellen Sie in bereits vorhandenen Insellösungen für Fachgebiete bzw. Fachbereiche eine vollständige modellbasierte Kooperation in einer 3D-Umgebung über proprietäre Schnittstellen bzw. Middleware sicher. Passen Sie die Richtlinien zur Lenkung dokumentierter Informationen (Daten, Modelle und Dokumente) an und, wenn notwendig, verfeinern Sie die Standards für Datenstrukturen und -formate (Klassifizierung und Attributierung von Objekten sowie deren Beziehungen/Hierarchien zur Vererbung, Austauschformate) für Ihre Organisation. Ergänzen Sie auch ggf. noch fehlende Ablaufregelungen.',
self::RES_E => 'Überprüfen Sie, ob die BIM-Methodik in allen definierten Anwendungsfällen wie vorgesehen (auch über 3D hinaus) angewendet wird und dieses auch in der interdisziplinären Zusammenarbeit und Lebenszyklusphasen-übergreifend erfolgt. Überwachen Sie die Erreichung der BIM-Ziele durch Festlegen und Messen von Kennzahlen (KPI).',
],
3 => [
self::RES_A => 'Überprüfen Sie bitte Ihre Antworten. Es ist sehr unwahrscheinlich, dass keines der Kriterien in diesem Handlungsfeld für Ihre Organisation relevant ist.',
self::RES_B => 'Beschreiben Sie die Rollen/Funktionen und deren grundsätzlichen Verantwortlichkeiten in den elementaren Prozessen. Ermitteln Sie die benötigten Qualifikationen interner und externer Prozessbeteiligter zur Einführung sowie Anwendung der BIM-Methodik und gleichen Sie diese mit den vorhandenen ab. Beginnen Sie mit der Planung notwendiger Qualifizierungsmaßnahmen.',
self::RES_C => 'Legen Sie zunächst die für die - projekt- sowie prozessspezifisch - wahrzunehmenden Aufgaben grundsätzlich verantwortlichen und rechenschaftspflichtigen Rollen/Funktionen fest. Delegieren Sie die Verantwortlichkeiten an bereits für die Organisation tätige Personen und statten Sie diese mit den entsprechend notwendigen Kompetenzen aus. Bemessen Sie zu den ermittelten Qualifikationen nun die erforderlichen personellen Kapazitäten zur Einführung und Anwendung der BIM-Methodik. Planen Sie Rekrutierungs- und weitere Qualifizierungsmaßnahmen und beginnen Sie mit deren Umsetzung.',
self::RES_D => 'Legen Sie nach den verantwortlichen und rechenschaftspflichtigen Rollen/Funktionen für die wahrzunehmenden Aufgaben in der Aufbauorganisation und in Projekten nun auch die zu konsultierenden und informierenden fest. Konkretisieren Sie diesbezüglich Funktions-/Stellenbeschreibungen, aber auch Leistungsbeschreibungen und Auswahlkriterien für externe Prozessbeteiligte. Sorgen Sie für eine Umsetzung der geplanten Qualifizierungs- und Rekrutierungsmaßnahmen.',
self::RES_E => 'Detaillieren Sie, soweit notwendig, die für die grundsätzlich in der Aufbauorganisation und in Projekten wahrzunehmenden Aufgaben getroffenen Festlegungen von verantwortlichen, rechenschaftspflichtigen, zu konsultierenden und informierenden Rollen/Funktionen für durchzuführende Tätigkeiten. Überprüfen Sie die Wirksamkeit durchgeführter Qualifizierungsmaßnahmen, die Eignung rekrutierten Personals sowie die Leistung externer Prozessbeteiligter.',
],
4 => [
self::RES_A => 'Überprüfen Sie bitte Ihre Antworten. Es ist sehr unwahrscheinlich, dass keines der Kriterien in diesem Handlungsfeld für Ihre Organisation relevant ist.',
self::RES_B => 'Erfassen Sie die in den Fachdisziplinen/-bereichen vorhandenen, separaten IT-Systeme und wofür Sie derzeit bei den relevanten Prozessen angewendet werden. Überprüfen Sie auch die Möglichkeiten des Datenaustauschs über Ex-/Import und vorhandene Schnittstellen sowie die Voraussetzungen für die Bereitstellung von Kollaborationsplattformen durch Ihre Organisation und die Zugriffsmöglichkeiten darauf durch externe Prozessbeteiligte. Bewerten Sie die Eignung der vorhandenen IT-Infrastruktur für eine Anwendung der BIM-Methodik und ermitteln Sie den Bedarf an zusätzlicher Hard- und Software für die - zeitnah und perspektivisch - in Eigenleistung zu erbringenden Aufgaben sowie ergänzender externer Services.',
self::RES_C => 'Beschaffen Sie schrittweise die als erforderlich ermittelte Hard- und Software zur IT-Unterstützung der verschiedenen BIM-Anwendungsfälle im Betrieb und in Projekten, entsprechend der zeitnah und perspektivisch in Eigenleistung zu erbringenden Aufgaben. Stellen Sie eine für die Kollaboration bei einer objektbasierten Modellierung geeignete gemeinsame Datenumgebung bereit und gewährleisten Sie den notwendigen Datenaustausch mittels Ex-/Import, Schnittstellen bzw. Collaboration-Tools sowie eine ordnungsgemäße Datensicherung.',
self::RES_D => 'Stellen Sie mit den bereits in Fachgebieten/-bereichen vorhandenen Insellösungen eine vollständige modellbasierte Kooperation in einer 3D-Umgebung über Schnittstellen bzw. Middleware sicher. Überprüfen Sie, ob die gemeinsame Datenumgebung den Spezifikationen entspricht und hinterfragen Sie, ob die Zugriffs- und Auswertungsmöglichkeiten und der Informationsgehalt für die internen und externen Anwender zur Wahrnehmung ihrer Aufgaben ausreichend sind, insbesondere an den verschiedenen Meilensteinen und Datenübergabepunkten. Ermitteln Sie den erforderlichen zusätzlichen Bedarf an Hard- und Software sowie externer Services, sowohl für eventuell noch nicht abgedeckte Anwendungsfälle als auch für eine vollständige netzwerkbasierte Integration und zentralisierte Datenhaltung.',
self::RES_E => 'Überführen Sie noch in Fachgebieten/-bereichen vorhandene Insellösungen in eine integrierte, netzwerkbasierte IT-Landschaft mit zentralisierter und strukturierter Datenhaltung auf Organisations-, Asset- und Projektebene. Überprüfen Sie, ob die Zugriffs- und Auswertungsmöglichkeiten und der Informationsgehalt für alle internen und externen Anwender zur Wahrnehmung ihrer Aufgaben ausreichend sind, insbesondere an den verschiedenen Meilensteinen und Datenübergabepunkten. Stellen Sie bei Datenaustausch und Zusammenarbeit möglichst von proprietären auf herstellerneutrale Schnittstellen sowie IFC/IFD-konforme Webservices und spezielle Modelserver um.',
]
];

public static $txtResultTotal = [
self::RES_A => 'Sie haben keine einzige Frage als relevant für Ihre Organisation eingestuft!',
self::RES_B => 'Die Voraussetzungen für eine Anwendung der BIM-Methodik in Ihrer Organisation sind offenbar noch nicht erfüllt, auch wenn bereits Maßnahmen dazu initiiert wurden. Der Reifegrad Ihrer Organisation ist noch als "Pre-BIM" zu bezeichnen.',
self::RES_C => 'Die Voraussetzungen für die Anwendung der BIM-Methodik sind offenbar nur in einigen Teilbereichen Ihrer Organisation erfüllt, die Aufbau- und Ablauforganisation nur hierfür definiert. Der Reifegrad Ihrer Organisation erlaubt eine "objektbasierte Modellierung".',
self::RES_D => 'Die BIM-Methodik ist in Ihrer Organisation eingeführt, die Voraussetzungen für eine gelenkte Anwendung sind weitgehend erfüllt. Der Reifegrad Ihrer Organisation entspricht dem einer "modellbasierten Kooperation" oder auch "pBIM" bzw. "little BIM".',
self::RES_E => 'Die BIM-Methodik ist anscheinend in Ihrer Organisation integriert, die Voraussetzungen für eine umfängliche Anwendung ist grundsätzlich erfüllt. Der Reifegrad Ihrer Organisation entspricht dem einer "netzwerkbasierten Integration" oder auch "iBIM" bzw. "big BIM".',
];

public static $txtActionTotal = [
self::RES_A => 'Überprüfen Sie bitte Ihre Antworten. Da kann was nicht stimmen!',
self::RES_B => 'Das Erreichen der nächst höheren Reifestufe (objektbasierte Modellierung) erfordert fundamentale und dauerhafte Änderungen oder auch „Transformationen“ in Ihrer Organisation. Diese Veränderungen erfolgen in der Regel aber nicht auf einen Schlag, sondern in Form von Schritten, die verschiedenen Handlungsfeldern zugeordnet werden können. Hinweise, welche grundlegenden Voraussetzungen für eine Einführung der BIM-Methodik zu schaffen sind, sind aus den Ergebnissen in den einzelnen Handlungsfeldern abzulesen.',
self::RES_C => 'Das Erreichen der nächst höheren Reifestufe (modellbasierte Kooperation oder auch pBIM bzw. little BIM) erfordert fundamentale und dauerhafte Änderungen oder auch „Transformationen“ in Ihrer Organisation. Diese Veränderungen erfolgen in der Regel aber nicht auf einen Schlag, sondern in Form von Schritten, die verschiedenen Handlungsfeldern zugeordnet werden können. Hinweise, welche Voraussetzungen für eine Anwendung der BIM-Methodik noch zu schaffen sind, sind aus den Ergebnissen in den einzelnen Handlungsfeldern abzulesen.',
self::RES_D => 'Das Erreichen der nächst höheren Reifestufe (vollständige Integration oder auch "iBIM" bzw. "bigBIM") erfordert noch einige fundamentale und dauerhafte Änderungen oder auch „Transformationen“ in Ihrer Organisation. Diese Veränderungen erfolgen in der Regel aber nicht auf einen Schlag, sondern in Form von Schritten, die verschiedenen Handlungsfeldern zugeordnet werden können. Hinweise auf dazu notwendige Schritte sind aus den Ergebnissen in den einzelnen Handlungsfeldern abzulesen.',
self::RES_E => 'Hinweise auf eventuell noch notwendige Schritte zu einer vollständigen Integration der BIM-Methodik in Ihrer Organisation sind aus den Ergebnissen in den einzelnen Handlungsfeldern abzulesen.',
];


/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
protected $id;

/**
* @ORM\Column(name="type", type="string", length=191, nullable=false, unique=true)
*/
protected $type;


public function __construct($type)
{
$this->type = $type;
}

/**
* @return mixed
*/
public function getId()
{
return $this->id;
}

/**
* @return mixed
*/
public function getType()
{
return $this->type;
}

public static function getResultCategoryTextIdentifier($percentage, $count)
{
if ($count === 0) {
return self::RES_A;
}
if ($percentage < 50) {
return self::RES_B;
}
if ($percentage < 67) {
return self::RES_C;
}
if ($percentage < 81) {
return self::RES_D;
}
return self::RES_E;
}
}

+ 27
- 75
httpdocs/src/Entity/User.php Wyświetl plik

@@ -17,7 +17,7 @@ use Symfony\Component\Security\Core\User\UserInterface;
*/
class User implements UserInterface
{
const MAX_CATALOGUES_PER_USER = 3;
const MAX_WORKSHEETS_PER_USER = 3;

// Costs of password encryption
const CRYPT_COST = 12;
@@ -62,14 +62,14 @@ class User implements UserInterface
protected $lastname;

/**
* @ORM\OneToMany(targetEntity="Catalogue", mappedBy="user", cascade={"persist", "remove"})
* @ORM\OneToMany(targetEntity="UserWorksheet", mappedBy="user", cascade={"persist", "remove"})
*/
protected $catalogues;
protected $worksheets;

/**
* @ORM\Column(type="smallint", nullable=false, options={"unsigned" = true})
*/
protected $maxCatalogues;
protected $maxWorksheets;

/**
* @ORM\Column(type="string", length=100, nullable=true)
@@ -144,12 +144,12 @@ class User implements UserInterface
/**
* @ORM\Column(type="datetime", nullable=false)
*/
protected $creation_date;
protected $creationDate;

/**
* @ORM\Column(type="datetime", nullable=true)
*/
protected $valid_until_date;
protected $validUntilDate;

/**
* @ORM\Column(type="boolean", options={"default":"0"})
@@ -198,14 +198,14 @@ class User implements UserInterface
$this->setPassword($password);
$this->active = true;
$this->creationUser = $editingUser;
$this->maxCatalogues = self::MAX_CATALOGUES_PER_USER;
$this->creation_date = new \DateTime('now', new \DateTimeZone('Europe/Berlin'));
$this->maxWorksheets = self::MAX_WORKSHEETS_PER_USER;
$this->creationDate = new \DateTime('now', new \DateTimeZone('Europe/Berlin'));
$this->acceptedTerms = false;
$this->acceptedLegal = false;

if ($userType->getType() === UserTypeRepository::USER_TYPE_USER) {
$this->valid_until_date = new \DateTime('now', new \DateTimeZone('Europe/Berlin'));
$this->valid_until_date->modify('+3 year');
$this->validUntilDate = new \DateTime('now', new \DateTimeZone('Europe/Berlin'));
$this->validUntilDate->modify('+3 year');
}
}

@@ -252,57 +252,33 @@ class User implements UserInterface
/**
* @return mixed
*/
public function getCatalogues()
public function getWorksheets()
{
return $this->catalogues;
return $this->worksheets;
}


public function addNewCatalogue(ObjectManager $em)
{
if (!$this->isActive()) {
throw new \Exception('user inactive');
}

if (count($this->catalogues) >= $this->getMaxCatalogues()) {
throw new \Exception('max number of catalogues reached');
}

foreach ($this->catalogues as $catalogue) {
if (!$catalogue->getFinished()) {
throw new \Exception('active catalogue exists');
}
}
$newCatalogue = new Catalogue($em, $this);
$this->catalogues[] = new Catalogue($em, $this);
return $newCatalogue;
}

public function getActiveCatalogue()
/**
* @param mixed $worksheets
*/
public function setWorksheets($worksheets): void
{
/** @var Catalogue $catalogue */
foreach ($this->catalogues as $catalogue) {
if (!$catalogue->getFinished()) {
return $catalogue;
}
}
return null;
$this->worksheets = $worksheets;
}

/**
* @return int
*/
public function getMaxCatalogues(): int
public function getMaxWorksheets(): int
{
return $this->maxCatalogues;
return $this->maxWorksheets;
}

/**
* @param int $maxCatalogues
* @param int $maxWorksheets
*/
public function setMaxCatalogues(int $maxCatalogues): void
public function setMaxWorksheets(int $maxWorksheets): void
{
$this->maxCatalogues = $maxCatalogues;
$this->maxWorksheets = $maxWorksheets;
}

/**
@@ -542,7 +518,7 @@ class User implements UserInterface
*/
public function getCreationDate()
{
return $this->creation_date;
return $this->creationDate;
}

/**
@@ -550,7 +526,7 @@ class User implements UserInterface
*/
public function getValidUntilDate(): ?\DateTime
{
return $this->valid_until_date;
return $this->validUntilDate;
}

/**
@@ -642,11 +618,11 @@ class User implements UserInterface
}

/**
* @param \DateTime $valid_until_date
* @param \DateTime $validUntilDate
*/
public function setValidUntilDate(?\DateTime $valid_until_date): void
public function setValidUntilDate(?\DateTime $validUntilDate): void
{
$this->valid_until_date = $valid_until_date;
$this->validUntilDate = $validUntilDate;
}

/**
@@ -731,28 +707,4 @@ class User implements UserInterface
$this->setEmail($em, $clientData->email);
}

/**
* Client mapper
* @param ObjectManager $em
* @param bool $fullMapping
* @return array
*/
public function clientMapper(ObjectManager $em, $fullMapping = false)
{
/** @var UserType $userType */
$userType = $em->getRepository('App:UserType')->find($this->userTypeId);

return [
'id' => $this->id,
'email' => $this->email,
'firstname' => $this->firstname,
'lastname' => $this->lastname,
'active' => $this->active,
'visible' => $this->visible,
'valid_until_date' => $this->getValidUntilDate(),
'v_translated_role' => UserType::getTranslatedRole($this->userTypeId),
'v_user_type' => $userType->clientMapper($em, $fullMapping),
];
}

}

+ 367
- 0
httpdocs/src/Entity/UserWorksheet.php Wyświetl plik

@@ -0,0 +1,367 @@
<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Entity
* @ORM\Table(name="user_worksheet")
*/
class UserWorksheet
{
/**
* @ORM\Id
* @ORM\Column(type="uuid", unique=true)
* @ORM\GeneratedValue(strategy="CUSTOM")
* @ORM\CustomIdGenerator(class="Ramsey\Uuid\Doctrine\UuidGenerator")
*/
private $id;

/**
* @ORM\ManyToOne(targetEntity="User", inversedBy="worksheets")
* @ORM\JoinColumn(name="user_id", referencedColumnName="id", onDelete="SET NULL")
*/
protected $user;

/**
* @ORM\OneToMany(targetEntity="UserWorksheetTask", mappedBy="userWorksheet", cascade={"persist", "remove"})
*/
protected $userWorkSheetTasks;

/**
* @ORM\Column(type="smallint", nullable=false, options={"unsigned" = true})
*/
protected $dinNumber;

/**
* @ORM\Column(type="string", nullable=false)
*/
protected $dinAssetName;

/**
* @ORM\Column(type="string", nullable=false)
*/
protected $failureProbability;

/**
* @ORM\Column(type="string", nullable=false)
*/
protected $failureDamage;

/**
* @ORM\Column(type="boolean", nullable=true)
*/
protected $maintenanceAdvantage;

/**
* @ORM\Column(type="boolean", nullable=true)
*/
protected $inspectionAdvantage;

/**
* @ORM\Column(type="boolean", nullable=true)
*/
protected $checkAdvantage;

/**
* @ORM\Column(type="smallint", nullable=false, options={"unsigned" = true})
*/
protected $userCycleMonths;

/**
* @ORM\Column(type="string", nullable=true)
*/
protected $bandwidth;

/**
* @ORM\Column(type="smallint", nullable=false, options={"unsigned" = true})
*/
protected $recMaintenanceCycleMonths;

/**
* @ORM\Column(type="smallint", nullable=false, options={"unsigned" = true})
*/
protected $recInspectionCycleMonths;

/**
* @ORM\Column(type="decimal", precision=10, scale=2))
*/
protected $deviationCosts;

/**
* @ORM\Column(type="decimal", precision=10, scale=2))
*/
protected $deviationPercentage;

/**
* @ORM\Column(type="datetime", nullable=false)
*/
protected $creationDate;


public function __construct(User $user)
{
$this->user = $user;
$this->creationDate = new \DateTime('now', new \DateTimeZone('Europe/Berlin'));
}

/**
* @return mixed
*/
public function getId()
{
return $this->id;
}

/**
* @return mixed
*/
public function getUser()
{
return $this->user;
}

/**
* @param mixed $user
*/
public function setUser($user): void
{
$this->user = $user;
}

/**
* @return mixed
*/
public function getDinNumber()
{
return $this->dinNumber;
}

/**
* @param mixed $dinNumber
*/
public function setDinNumber($dinNumber): void
{
$this->dinNumber = $dinNumber;
}

/**
* @return mixed
*/
public function getDinAssetName()
{
return $this->dinAssetName;
}

/**
* @param mixed $dinAssetName
*/
public function setDinAssetName($dinAssetName): void
{
$this->dinAssetName = $dinAssetName;
}

/**
* @return mixed
*/
public function getFailureProbability()
{
return $this->failureProbability;
}

/**
* @param mixed $failureProbability
*/
public function setFailureProbability($failureProbability): void
{
$this->failureProbability = $failureProbability;
}

/**
* @return mixed
*/
public function getFailureDamage()
{
return $this->failureDamage;
}

/**
* @param mixed $failureDamage
*/
public function setFailureDamage($failureDamage): void
{
$this->failureDamage = $failureDamage;
}

/**
* @return mixed
*/
public function getMaintenanceAdvantage()
{
return $this->maintenanceAdvantage;
}

/**
* @param mixed $maintenanceAdvantage
*/
public function setMaintenanceAdvantage($maintenanceAdvantage): void
{
$this->maintenanceAdvantage = $maintenanceAdvantage;
}

/**
* @return mixed
*/
public function getInspectionAdvantage()
{
return $this->inspectionAdvantage;
}

/**
* @param mixed $inspectionAdvantage
*/
public function setInspectionAdvantage($inspectionAdvantage): void
{
$this->inspectionAdvantage = $inspectionAdvantage;
}

/**
* @return mixed
*/
public function getCheckAdvantage()
{
return $this->checkAdvantage;
}

/**
* @param mixed $checkAdvantage
*/
public function setCheckAdvantage($checkAdvantage): void
{
$this->checkAdvantage = $checkAdvantage;
}

/**
* @return mixed
*/
public function getUserCycleMonths()
{
return $this->userCycleMonths;
}

/**
* @param mixed $userCycleMonths
*/
public function setUserCycleMonths($userCycleMonths): void
{
$this->userCycleMonths = $userCycleMonths;
}

/**
* @return mixed
*/
public function getBandwidth()
{
return $this->bandwidth;
}

/**
* @param mixed $bandwidth
*/
public function setBandwidth($bandwidth): void
{
$this->bandwidth = $bandwidth;
}

/**
* @return mixed
*/
public function getRecMaintenanceCycleMonths()
{
return $this->recMaintenanceCycleMonths;
}

/**
* @param mixed $recMaintenanceCycleMonths
*/
public function setRecMaintenanceCycleMonths($recMaintenanceCycleMonths): void
{
$this->recMaintenanceCycleMonths = $recMaintenanceCycleMonths;
}

/**
* @return mixed
*/
public function getRecInspectionCycleMonths()
{
return $this->recInspectionCycleMonths;
}

/**
* @param mixed $recInspectionCycleMonths
*/
public function setRecInspectionCycleMonths($recInspectionCycleMonths): void
{
$this->recInspectionCycleMonths = $recInspectionCycleMonths;
}

/**
* @return mixed
*/
public function getDeviationCosts()
{
return $this->deviationCosts;
}

/**
* @param mixed $deviationCosts
*/
public function setDeviationCosts($deviationCosts): void
{
$this->deviationCosts = $deviationCosts;
}

/**
* @return mixed
*/
public function getDeviationPercentage()
{
return $this->deviationPercentage;
}

/**
* @param mixed $deviationPercentage
*/
public function setDeviationPercentage($deviationPercentage): void
{
$this->deviationPercentage = $deviationPercentage;
}

/**
* @return \DateTime
*/
public function getCreationDate(): \DateTime
{
return $this->creationDate;
}

/**
* @return mixed
*/
public function getUserWorkSheetTasks()
{
return $this->userWorkSheetTasks;
}

/**
* @param mixed $userWorkSheetTasks
*/
public function setUserWorkSheetTasks($userWorkSheetTasks): void
{
$this->userWorkSheetTasks = $userWorkSheetTasks;
}



}

+ 239
- 0
httpdocs/src/Entity/UserWorksheetTask.php Wyświetl plik

@@ -0,0 +1,239 @@
<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Entity
* @ORM\Table(name="user_worksheet_task")
*/
class UserWorksheetTask
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
protected $id;

/**
* @ORM\ManyToOne(targetEntity="UserWorksheet", inversedBy="worksheets")
* @ORM\JoinColumn(name="worksheet_id", referencedColumnName="id", onDelete="SET NULL")
*/
protected $userWorksheet;

/**
* @ORM\Column(type="string", nullable=true)
*/
protected $delimitation;

/**
* @ORM\Column(type="string", nullable=false)
*/
protected $task;

/**
* @ORM\Column(type="boolean", nullable=true)
*/
protected $inspection;

/**
* @ORM\Column(type="boolean", nullable=true)
*/
protected $maintenance;

/**
* @ORM\Column(type="boolean", nullable=true)
*/
protected $service;

/**
* @ORM\Column(type="boolean", nullable=true)
*/
protected $expert;

/**
* @ORM\Column(type="boolean", nullable=true)
*/
protected $specialist;

/**
* @ORM\Column(type="boolean", nullable=true)
*/
protected $skilledPersonnel;

/**
* @ORM\Column(type="text", nullable=true)
*/
protected $norm;

/**
* @return mixed
*/
public function getId()
{
return $this->id;
}

/**
* @return mixed
*/
public function getUserWorksheet()
{
return $this->userWorksheet;
}

/**
* @param mixed $userWorksheet
*/
public function setUserWorksheet($userWorksheet): void
{
$this->userWorksheet = $userWorksheet;
}

/**
* @return mixed
*/
public function getDelimitation()
{
return $this->delimitation;
}

/**
* @param mixed $delimitation
*/
public function setDelimitation($delimitation): void
{
$this->delimitation = $delimitation;
}

/**
* @return mixed
*/
public function getTask()
{
return $this->task;
}

/**
* @param mixed $task
*/
public function setTask($task): void
{
$this->task = $task;
}

/**
* @return mixed
*/
public function getInspection()
{
return $this->inspection;
}

/**
* @param mixed $inspection
*/
public function setInspection($inspection): void
{
$this->inspection = $inspection;
}

/**
* @return mixed
*/
public function getMaintenance()
{
return $this->maintenance;
}

/**
* @param mixed $maintenance
*/
public function setMaintenance($maintenance): void
{
$this->maintenance = $maintenance;
}

/**
* @return mixed
*/
public function getService()
{
return $this->service;
}

/**
* @param mixed $service
*/
public function setService($service): void
{
$this->service = $service;
}

/**
* @return mixed
*/
public function getExpert()
{
return $this->expert;
}

/**
* @param mixed $expert
*/
public function setExpert($expert): void
{
$this->expert = $expert;
}

/**
* @return mixed
*/
public function getSpecialist()
{
return $this->specialist;
}

/**
* @param mixed $specialist
*/
public function setSpecialist($specialist): void
{
$this->specialist = $specialist;
}

/**
* @return mixed
*/
public function getSkilledPersonnel()
{
return $this->skilledPersonnel;
}

/**
* @param mixed $skilledPersonnel
*/
public function setSkilledPersonnel($skilledPersonnel): void
{
$this->skilledPersonnel = $skilledPersonnel;
}

/**
* @return mixed
*/
public function getNorm()
{
return $this->norm;
}

/**
* @param mixed $norm
*/
public function setNorm($norm): void
{
$this->norm = $norm;
}

}

+ 9
- 68
httpdocs/src/Repository/UserRepository.php Wyświetl plik

@@ -8,6 +8,7 @@ use App\Entity\CatalogueDetail;
use App\Entity\Question;
use App\Entity\QuestionType;
use App\Entity\User;
use App\Entity\UserWorksheet;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use Dompdf\Dompdf;
@@ -27,7 +28,7 @@ class UserRepository extends ServiceEntityRepository
$user->setFirstname($clientData->firstname);
$user->setLastname($clientData->lastname);
$user->setPhoneNo($clientData->phoneNo);
$user->setMaxCatalogues($clientData->maxCatalogues);
$user->setMaxWorksheets($clientData->maxCatalogues);
$user->setCompany($clientData->company);
$user->setDepartment($clientData->department);
$user->setOccupation($clientData->occupation);
@@ -47,15 +48,8 @@ class UserRepository extends ServiceEntityRepository

/**
* Renders user catalogue
*
* @param Environment $twig
* @param Catalogue $catalogue
* @return Dompdf
* @throws \Twig\Error\LoaderError
* @throws \Twig\Error\RuntimeError
* @throws \Twig\Error\SyntaxError
*/
public static function renderCatalogue(Environment $twig, Catalogue $catalogue)
public static function renderCatalogue(Environment $twig, UserWorksheet $worksheet)
{
// Configure Dompdf according to your needs
$pdfOptions = new Options();
@@ -66,67 +60,14 @@ class UserRepository extends ServiceEntityRepository
$dompdf = new Dompdf($pdfOptions);
$dompdf->setPaper('A4', 'portrait');

$result = [];
/** @var CatalogueDetail $catalogueDetail */
foreach($catalogue->getCatalogueDetails() as $catalogueDetail) {
/** @var Question $question */
$question = $catalogueDetail->getQuestion();
$questionType = $question->getQuestionType();
$questionTypeName = $questionType->getType();
if (!array_key_exists($questionTypeName, $result)) {
$result[$questionTypeName] = [
'count' => 0,
'maxPoints' => 0,
'points' => 0,
'countAll' => 0,
'percentage' => 0,
'id' => $questionType->getId(),
'txtResult' => '',
'txtAction' => '',
];
}
$answer = $catalogueDetail->getAnswer();
$result[$questionTypeName]['countAll']++;
if ($answer !== CatalogueDetail::ANSWER_IRRELEVANT) {
$result[$questionTypeName]['maxPoints'] += $question->getWeight();
$result[$questionTypeName]['count']++;
}
if ($answer === CatalogueDetail::ANSWER_FULFILLED || $answer === CatalogueDetail::ANSWER_PARTLY_FULFILLED || $answer === CatalogueDetail::ANSWER_WIDELY_FULFILLED) {
$result[$questionTypeName]['points'] += $question->getWeight() * CatalogueDetail::$validAnswers[$answer];
}
}

$total = [
'count' => 0,
'maxPoints' => 0,
'points' => 0,
'countAll' => 0,
'percentage' => 0,
'txtResult' => '',
'txtAction' => '',
];
foreach ($result as $qTypeName => $item) {
$percentage = $item['maxPoints'] > 0 ? ($item['points'] / $item['maxPoints'] * 100) : 0;
$result[$qTypeName]['percentage'] = $percentage;
$result[$qTypeName]['txtResult'] = QuestionType::$txtResultPerType[$item['id']][QuestionType::getResultCategoryTextIdentifier($percentage, $item['count'])];
$result[$qTypeName]['txtAction'] = QuestionType::$txtActionPerType[$item['id']][QuestionType::getResultCategoryTextIdentifier($percentage, $item['count'])];
$total['count'] += $item['count'];
$total['maxPoints'] += $item['maxPoints'];
$total['points'] += $item['points'];
$total['countAll'] += $item['countAll'];
}
$total['percentage'] = $total['maxPoints'] > 0 ? ($total['points'] / $total['maxPoints'] * 100) : 0;
$total['txtResult'] = QuestionType::$txtResultTotal[QuestionType::getResultCategoryTextIdentifier($total['percentage'], $total['count'])];
$total['txtAction'] = QuestionType::$txtActionTotal[QuestionType::getResultCategoryTextIdentifier($total['percentage'], $total['count'])];


// Retrieve the HTML generated in our twig file
$html = $twig->render('pdf/pdf.html.twig', [
'user' => $catalogue->getUser(),
'catalogue' => $catalogue,
'result' => $result,
'total' => $total
]);
$html = $twig->render('pages/worksheet.html.twig',
[
'worksheet' => $worksheet,
'isPdf' => true
]
);
// Load HTML to Dompdf
$dompdf->loadHtml($html);


+ 59
- 0
httpdocs/src/Service/CalculatorService.php Wyświetl plik

@@ -0,0 +1,59 @@
<?php


namespace App\Service;


use App\Entity\DinAsset;
use App\Entity\DinAssetBenchmark;
use App\Utils\Utils;

class CalculatorService
{
const KEY_REC_CYCLE_MAINTENANCE = 'recCycleMaintenance';
const KEY_REC_CYCLE_INSPECTION = 'recCycleInspection';
const KEY_COST_DIFF_CUR_REC_CYCLE = 'costDiffCurCycleRecCycle';
const KEY_COST_DIFF_CUR_REC_PERCENTAGE = 'costDiffCurRecPercentage';

public function calculateRisk(DinAssetBenchmark $benchmark, $params)
{
/** @var DinAsset $asset */
$asset = $benchmark->getDinAsset();
$userCycle = $params['cycle'];

$pointsFailure = Utils::$riskFailure[$params['failure']][1];
$pointsCosts = Utils::$riskCosts[$params['costs']][1];
if ((int)$params['costs'] === Utils::PERSON_DAMAGE_INDEX) {
$pointsCosts = Utils::PERSON_DAMAGE_BASE - $pointsFailure;
}
$riskPoints = $pointsFailure + $pointsCosts;
$riskFactor = Utils::$riskPoints[$riskPoints]['factor'];

$recCycleMaintenance = $asset->getCycleMonthsMax();
if ((int)($params['maintenance']) === 1 && ((int)$params['check']) === 1 ) {
$recCycleMaintenance = (int) ($asset->getCycleMonthsMax() * $riskFactor);
if ($recCycleMaintenance < $asset->getCycleMonthsMin()) {
$recCycleMaintenance = $asset->getCycleMonthsMin();
}
}
$costsCurrentPerYear = (12 / $userCycle) * $benchmark->getAverageCosts();
$costsRecPerYear = (12 / $recCycleMaintenance) * $benchmark->getAverageCosts();

$recCycleInspection = $asset->getCycleMonthsMax();
if ( ((int)$params['inspection']) === 1 ) {
$recCycleInspection = (int) ($asset->getCycleMonthsMax() * $riskFactor);
if ($recCycleInspection < $asset->getCycleMonthsMin()) {
$recCycleInspection = $asset->getCycleMonthsMin();
}
}
$costDiffCurCycleRecCycle = $costsCurrentPerYear - $costsRecPerYear;
$costDiffCurRecPercentage = 1 - ($userCycle / $recCycleMaintenance);

$res[self::KEY_REC_CYCLE_MAINTENANCE] = $recCycleMaintenance;
$res[self::KEY_REC_CYCLE_INSPECTION] = $recCycleInspection;
$res[self::KEY_COST_DIFF_CUR_REC_PERCENTAGE] = round($costDiffCurRecPercentage, 2);
$res[self::KEY_COST_DIFF_CUR_REC_CYCLE] = round($costDiffCurCycleRecCycle, 2);
return $res;
}

}

+ 21
- 0
httpdocs/symfony.lock Wyświetl plik

@@ -1,4 +1,7 @@
{
"brick/math": {
"version": "0.9.3"
},
"composer/package-versions-deprecated": {
"version": "1.11.99.1"
},
@@ -181,6 +184,24 @@
"psr/simple-cache": {
"version": "1.0.1"
},
"ramsey/collection": {
"version": "1.3.0"
},
"ramsey/uuid": {
"version": "4.2.3"
},
"ramsey/uuid-doctrine": {
"version": "2.0",
"recipe": {
"repo": "github.com/symfony/recipes-contrib",
"branch": "main",
"version": "1.3",
"ref": "471aed0fbf5620b8d7f92b7a5ebbbf6c0945c27a"
},
"files": [
"config/packages/ramsey_uuid_doctrine.yaml"
]
},
"sabberworm/php-css-parser": {
"version": "8.3.1"
},


+ 12
- 1
httpdocs/templates/pages/risk_analysis.html.twig Wyświetl plik

@@ -55,6 +55,17 @@
<option value="{{ key }}">{{ benchmarkValue }}</option>
{% endfor %}
</select>
<span class="btn" id="submit">Berechnen</span>
<span class="btn" id="calculate">Berechnen</span>
<dl>
<dt>Inspektion (empfohlener Zyklus in Monaten)</dt>
<dd id="resInspection"></dd>
<dt>Wartung (empfohlener Zyklus in Monaten)</dt>
<dd id="resMaintenance"></dd>
<dt>Kostenersparnis in Prozent</dt>
<dd id="resPercentage"></dd>
<dt>Kostenersparnis in Euro</dt>
<dd id="resEuro"></dd>
</dl>
<span class="btn" id="worksheet">Arbeitskarte erstellen</span>
</form>
{% endblock %}

+ 10
- 22
httpdocs/templates/pages/start.html.twig Wyświetl plik

@@ -4,35 +4,23 @@

{% block body %}
<h1>Übersicht</h1>
{# <p>Hier stehen Infos zum Fragenkatalog.</p>#}
<p>RealFM und der Arbeitskreis MPP wünschen Ihnen nun viel Spaß bei der Bearbeitung des Fragenkataloges sowie wichtige Erkenntnisse und wertvolle Hinweise für die BIM2FM-Stategie und für notwendige Maßnahmen zur Umsetzung.</p>
{% if noMoreCatalogues %}
<p>Sie haben die maximale Anzahl an Durchgängen erreicht.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore.</p>
{% if numWorksheetsLeft <= 0 %}
<p>Sie haben die maximale Anzahl an Durchgängen erreicht. Bitte wenden sie sich an uns, wenn sie weitere Analysen benötigen.</p>
{% else %}
<div class="container">
<a href="{{ path('risk_analysis') }}" class="btn">Neue Arbeitskarte erstellen</a>
{# <p class="alert">Leider ist Ihre Nutzungsdauer von 3 Jahren abgelaufen. Wenn Sie den Fragenkatalog noch einmal bearbeiten möchten, wenden Sie sich bitte an die Geschäftsstelle.</p>#}
</div>
<div>(noch {{ numWorksheetsLeft }} Durchgänge möglich)</div>
{% endif %}

<p>Ihre Arbeitskarten:</p>
<h2>Ihre bisher abgeschlossenen Arbeitskarten:</h2>
<ul>
<li>
<a href="#">411 - Hubwagen</a>
</li>
<li>
<a href="#">411 - Hubwagen</a>
</li>
<li>
<a href="#">411 - Hubwagen</a>
</li>
{% for worksheet in worksheets %}
<li>
<a target="blank" href="/worksheet/{{ worksheet.id }}">{{ worksheet.dinNumber }} - {{ worksheet.dinAssetName }} (erstellt am: {{ worksheet.creationDate|date("d.m.Y H:i") }})</a>
</li>
{% endfor %}
</ul>

{% if userHasFinishedCatalogue %}
<h2>"Ihr MPPScore"</h2>
<p>Hier erhalten Sie eine Zusammenfassung Ihrer Antworten zu den Fragen aus MPPTool und das Ergebnis der Auswertung als PDF-Dokument.</p>
<a href="{{ path('download') }}" class="btn">Herunterladen</a>
<p>&nbsp;</p>
{% include 'snippets/sponsors.html.twig' %}
{% endif %}
{% endblock %}

+ 79
- 0
httpdocs/templates/pages/worksheet.html.twig Wyświetl plik

@@ -0,0 +1,79 @@
{% extends 'base.html.twig' %}

{% block title %}MPP-Tool{% endblock %}

{% block body %}
<h1>Arbeitsblatt (erstellt am: {{ worksheet.creationDate|date("d.m.Y H:i") }})</h1>

<dl>
<dt>DIN</dt>
<dd>{{ worksheet.dinNumber }}</dd>
<dt>Anlage</dt>
<dd>{{ worksheet.dinAssetName }}</dd>
</dl>

<h2>Risikoanalyse</h2>
<dl>
<dt>Wie hoch ist die Ausfallwahrscheinlichkeit?</dt>
<dd>{{ worksheet.failureProbability }}</dd>
<dt>Wie hoch ist der Schaden bei Ausfall?</dt>
<dd>{{ worksheet.failureDamage }}</dd>
</dl>

<h2>Optimierungsckeck</h2>
<dl>
<dt>Wird durch die Wartung der Abnutzungsvorrat positiv beeinflusst?</dt>
<dd>{% if worksheet.maintenanceAdvantage == 1 %}Ja{% else %}nein{% endif %}</dd>
<dt>Kann durch eine Inspektion der Zustand der Anlage erkannt werden?</dt>
<dd>{% if worksheet.inspectionAdvantage == 1 %}Ja{% else %}nein{% endif %}</dd>
<dt>Genügt eine einfache Sichtkontrolle im Rahmen des regelmäßigen Rundgangs?</dt>
<dd>{% if worksheet.checkAdvantage == 1 %}Ja{% else %}nein{% endif %}</dd>
</dl>
<dl>
<dt>Aktueller Zyklus (in Monaten)</dt>
<dd>{{ worksheet.userCycleMonths }}</dd>
<dt>Bandbreite Anlage</dt>
<dd>{% if worksheet.bandwidth is not null %}{{ worksheet.bandwidth }}{% else %}-{% endif %}</dd>
</dl>

<h2>Ergebnis</h2>
<dl>
<dt>Empfehlung Wartung (in Monaten)</dt>
<dd>{{ worksheet.recMaintenanceCycleMonths }}</dd>
<dt>Empfehlung Inspektion (in Monaten)</dt>
<dd>{{ worksheet.recInspectionCycleMonths }}</dd>
<dt>Einsparpotential p.a. (%)</dt>
<dd>{{ worksheet.deviationPercentage }}</dd>
<dt>Einsparpotential p.a. (€)</dt>
<dd>{{ worksheet.deviationCosts }}</dd>
</dl>

<h2>Tätigkeiten</h2>
<dl>
{% for task in worksheet.userWorkSheetTasks %}
<dt>Abgrenzung</dt>
<dd>{% if task.delimitation is not null %}{{ task.delimitation }}{% else %}-{% endif %}</dd>
<dt>Tätigkeit</dt>
<dd>{{ task.task }}</dd>
<dt>Inspektion</dt>
<dd>{{ task.inspection }}</dd>
<dt>Wartung</dt>
<dd>{{ task.maintenance }}</dd>
<dt>Instandsetzung</dt>
<dd>{{ task.service }}</dd>
<dt>Sachverständiger</dt>
<dd>{{ task.expert }}</dd>
<dt>Sachkundige</dt>
<dd>{{ task.specialist }}</dd>
<dt>Fachkraft</dt>
<dd>{{ task.skilledPersonnel }}</dd>
<dt>Normative Grundlage</dt>
<dd>{{ task.norm }}</dd>
{% endfor %}
</dl>

{% if isPdf == false %}
<a href="{{ path('download', { uuid: worksheet.id }) }}" class="btn">Arbeitskarte als PDF herunterladen</a>
{% endif %}

{% endblock %}

Ładowanie…
Anuluj
Zapisz