DB schema updated, code restructured, full exception and empty posts handling,...

DB schema updated, code restructured, full exception and empty posts handling, added download script and new route, various fixes
parent ebb0fd83
......@@ -35,6 +35,7 @@ return [
['/receive-equip', ['school'], ['get', 'post']],
['/receive-equip/submit-success', ['school'], ['get']],
['/receive-equip/report', ['school'], ['get']],
['/receive-equip/receive-doc/{fn}', ['school'], ['get']],
['/tpe_survey', ['school'], ['get', 'post']],
['/tpe_survey/total-teachers', ['school'], ['post']],
['/forum', ['guest', 'user'], ['get']],
......@@ -42,6 +43,7 @@ return [
['/in_numbers', ['guest', 'user'], ['get']],
['/export/csv/edulabs_{type}.csv', ['guest', 'user'], ['get']],
['/open-data', ['guest', 'user'], ['get']],
['/receive-equip/undo-submit/{applicationform_id}', ['school'], ['get']], // only for tests. Must be removed
],
],
],
......
<?php
/**
* gredu_labs
*
* @link https://github.com/eellak/gredu_labs for the canonical source repository
* @copyright Copyright (c) 2008-2015 Greek Free/Open Source Software Society (https://gfoss.ellak.gr/)
* @license GNU GPLv3 http://www.gnu.org/licenses/gpl-3.0-standalone.html
*/
return [
'receive_equip' => [
'file_upload_path' => __DIR__ . '/../../data/uploads', // path to save file
'file_upload_max_size' => 3145728, // Maximum number of bytes allowed(default 3MB)
'file_upload_types_permitted' => ['jpg', 'jpeg', 'pdf', 'png'], // Array of allowed extensions
],
];
......@@ -24,6 +24,7 @@ CREATE TABLE `applicationform` (
`submitted_by` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`received_ts` timestamp NULL,
`received_by` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`received_document` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT '',
PRIMARY KEY (`id`),
KEY `index_foreignkey_applicationform_school` (`school_id`),
CONSTRAINT `c_fk_applicationform_school_id` FOREIGN KEY (`school_id`) REFERENCES `school` (`id`) ON DELETE RESTRICT ON UPDATE CASCADE
......
......@@ -24,6 +24,7 @@ CREATE TABLE `applicationform` (
`submitted_by` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`received_ts` timestamp NULL,
`received_by` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`received_document` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT '',
PRIMARY KEY (`id`),
KEY `index_foreignkey_applicationform_school` (`school_id`),
CONSTRAINT `c_fk_applicationform_school_id` FOREIGN KEY (`school_id`) REFERENCES `school` (`id`) ON DELETE RESTRICT ON UPDATE CASCADE
......
......@@ -7,6 +7,9 @@
* @copyright Copyright (c) 2008-2015 Greek Free/Open Source Software Society (https://gfoss.ellak.gr/)
* @license GNU GPLv3 http://www.gnu.org/licenses/gpl-3.0-standalone.html
*/
use Slim\Http\Request;
use Slim\Http\Response;
use RedBeanPHP\R;
return function (Slim\App $app) {
$container = $app->getContainer();
......@@ -17,7 +20,6 @@ return function (Slim\App $app) {
});
$events('on', 'app.services', function ($container) {
$container[GrEduLabs\ReceiveEquip\Service\ReceiveEquipServiceInterface::class] = function ($c) {
return new GrEduLabs\ReceiveEquip\Service\ReceiveEquipService($c['logger']);
};
......@@ -43,13 +45,13 @@ return function (Slim\App $app) {
$container[GrEduLabs\ReceiveEquip\Action\ReceiveEquip::class] = function ($c) {
$settings = $c->get('settings');
return new GrEduLabs\ReceiveEquip\Action\ReceiveEquip(
$c->get('view'),
$c->get(GrEduLabs\ReceiveEquip\Service\ReceiveEquipServiceInterface::class),
$c->get(GrEduLabs\ReceiveEquip\InputFilter\ReceiveEquip::class),
$c->get('authentication_service'),
$c->get('router')->pathFor('receive_equip.submit_success'),
$c['flash'],
$c
);
};
......@@ -74,15 +76,18 @@ return function (Slim\App $app) {
$c->get(GrEduLabs\ReceiveEquip\Service\ReceiveEquipServiceInterface::class)
);
};
});
$container[GrEduLabs\ReceiveEquip\Middleware\SchoolReceiveEquip::class] = function ($c) {
return new GrEduLabs\ReceiveEquip\Middleware\SchoolReceiveEquip(
$events('on', 'app.services', function ($container) {
$container[GrEduLabs\ReceiveEquip\Middleware\HandleEmptyPosts::class] = function ($c) {
return new GrEduLabs\ReceiveEquip\Middleware\HandleEmptyPosts(
$c->get('view'),
$c->get(GrEduLabs\ReceiveEquip\Service\ReceiveEquipServiceInterface::class),
$c['flash'],
$c
);
};
});
}, -100000);
$events('on', 'app.bootstrap', function ($app, $container) {
$container['view']->getEnvironment()->getLoader()->prependPath(__DIR__ . '/templates');
......@@ -91,11 +96,46 @@ return function (Slim\App $app) {
$this->map(['get', 'post'], '', GrEduLabs\ReceiveEquip\Action\ReceiveEquip::class)
->add(GrEduLabs\Application\Middleware\AddCsrfToView::class)
->add('csrf')
->add(GrEduLabs\ReceiveEquip\Middleware\HandleEmptyPosts::class)
->setName('receive_equip');
$this->get('/submit-success', GrEduLabs\ReceiveEquip\Action\SubmitSuccess::class)
->setName('receive_equip.submit_success');
$this->get('/report', GrEduLabs\ReceiveEquip\Action\ReceiveEquipPdf::class)
->setName('receive_equip.report');
})->add(GrEduLabs\Schools\Middleware\FetchSchoolFromIdentity::class);
$app->get('/receive-equip/receive-doc/{fn}', function (Request $req, Response $res) use ($container) {
$route = $req->getAttribute('route');
$fn = $route->getArgument('fn');
/* $container["logger"]->info(sprintf('filename = %s url=%s', $fn, path_for('receive_equip.receive_doc', [
'fn' => form.values.received_document,])
)); */
$file = $container['settings']['receive_equip']['file_upload_path'] . "/" . $fn;
$response = $res->withHeader('Content-Description', 'File Transfer')
->withHeader('Content-Type', 'application/octet-stream')
->withHeader('Content-Disposition', 'attachment;filename="' . basename($file) . '"')
->withHeader('Expires', '0')
->withHeader('Cache-Control', 'must-revalidate')
->withHeader('Content-Length', filesize($file));
readfile($file);
return $response;
})->setName('receive_equip.receive_doc');
/******************* only for tests ***************************/
$app->get('/receive-equip/undo-submit/{applicationform_id}', function (Request $req, Response $res) use ($container) {
$route = $req->getAttribute('route');
$applicationform_id = $route->getArgument('applicationform_id');
$sql = 'update `applicationform` set `approved`=1, `received_ts`=null where `id`=' . $applicationform_id;
R::exec($sql);
return $res->withRedirect("/receive-equip");
})->setName('receive_equip.undosubmit');
/****************** /only for tests ***************************/
});
};
......@@ -44,13 +44,6 @@ class ReceiveEquip
*/
protected $authService;
/**
*
* @var flash messages
*/
protected $flash;
/**
*
* @var type SLIM application container
......@@ -63,23 +56,28 @@ class ReceiveEquip
*/
protected $successUrl;
/**
*
* @var array
*/
protected $formErrorMessages;
public function __construct(
Twig $view, ReceiveEquipServiceInterface $receiveEquipService, InputFilterInterface $receiveEquipInputFilter, AuthenticationServiceInterface $authService, $successUrl, $flash, $container
Twig $view, ReceiveEquipServiceInterface $receiveEquipService, InputFilterInterface $receiveEquipInputFilter, AuthenticationServiceInterface $authService, $successUrl, $container
) {
$this->view = $view;
$this->receiveEquipService = $receiveEquipService;
$this->receiveEquipInputFilter = $receiveEquipInputFilter;
$this->authService = $authService;
$this->successUrl = $successUrl;
$this->flash = $flash;
$this->container = $container;
$this->formErrorMessages = [];
}
public function __invoke(Request $req, Response $res)
{
$school = $req->getAttribute('school');
$receivedDocumentFileName = $school->id;
if ($req->isPost()) {
$reqParams = $req->getParams();
array_splice($reqParams['items'], 0, 0);
......@@ -89,74 +87,44 @@ class ReceiveEquip
'submitted_by' => $this->authService->getIdentity()->mail,
]));
$isValid = $this->receiveEquipInputFilter->isValid();
$isValidFile = true;
if ($isValid) {
$isValidFile = true;
$files = $req->getUploadedFiles();
if (empty($files['received_document'])) {
$isValidFile = false;
$this->flash->addMessage('danger', "Πρέπει να επισυνάψετε το δελτίο παραλαβής και μετά να επιλέξετε Υποβολή");
// throw new Exception('Expected a newfile');
array_push($this->formErrorMessages, "Πρέπει να επισυνάψετε το δελτίο παραλαβής και μετά να επιλέξετε Υποβολή");
$this->container["logger"]->info(sprintf('empty($files[received_document]) = true'));
} else {
$clientFile = $files['received_document'];
if ($clientFile->getError() === UPLOAD_ERR_OK) {
$this->container["logger"]->info(sprintf(
'mediatype = %s, filesize= %s',
$clientFile->getClientMediaType(), $clientFile->getSize()
));
if ((int) $clientFile->getSize() > (int) $this->container['settings']['application_form']['file_upload_max_size']) {
$isValidFile = false;
$this->flash->addMessage('danger', "Η επισύναψη - αποστολή του αρχείου απέτυχε. Το μέγεθος του αρχείου υπερβαίνει το επιτρεπτό όριο");
} else {
$clientFileName = $clientFile->getClientFilename();
$clientFileNameExt = strtolower(pathinfo($clientFileName, PATHINFO_EXTENSION));
if (in_array($clientFileNameExt, $this->container['settings']['application_form']['file_upload_extensions'])) {
$receivedDocumentFileName = $receivedDocumentFileName . "." . $clientFileNameExt;
$clientFile->moveTo($this->container['settings']['application_form']['file_upload_path'] . "/" . $receivedDocumentFileName);
} else {
$isValidFile = false;
$this->flash->addMessage('danger', "Η επισύναψη - αποστολή του αρχείου απέτυχε. Ο τύπος του αρχείου δεν είναι επιτρεπτός");
}
}
} else {
$clientFile = $files['received_document'];
$receivedDocumentFileName = $this->fileUpload($clientFile, $receivedDocumentFileName);
if ($receivedDocumentFileName === null) {
$isValidFile = false;
$this->flash->addMessage('danger', "Η επισύναψη - αποστολή του αρχείου απέτυχε");
}
}
if ($isValidFile) {
if ($isValidFile === true) {
$data = $this->receiveEquipInputFilter->getValues();
$receiveEquip = $this->receiveEquipService->submit($data, $receivedDocumentFileName);
$_SESSION['receiveEquipForm']['receiveEquip'] = $receiveEquip;
$res = $res->withRedirect($this->successUrl);
return $res;
} else {
return $res->withRedirect($req->getUri());
}
}
$this->view['form'] = [
'is_valid' => $isValid,
'values' => $this->receiveEquipInputFilter->getValues(),
'raw_values' => $this->receiveEquipInputFilter->getRawValues(),
'messages' => $this->receiveEquipInputFilter->getMessages(),
];
}
if (!$req->isPost()) {
$this->populateInvalidForm($school);
} else { // not post request
if (null !== ($receiveEquip = $this->receiveEquipService->findSchoolReceiveEquip($school->id))) {
$this->view['form'] = [
'school' => $school,
'is_valid' => true,
'exists' => true,
'values' => $receiveEquip,
];
} else {
$this->view['form'] = [
'school' => $school,
'is_valid' => true,
'exists' => false,
'values' => null,
];
......@@ -170,71 +138,115 @@ class ReceiveEquip
return $res;
}
private function fileUpload($clientFile)
private function populateInvalidForm($school) {
$receiveEquip = $this->receiveEquipService->findSchoolReceiveEquip($school->id);
$dataFromForm = $this->receiveEquipInputFilter->getValues();
if ($receiveEquip !== null) {
$items = $receiveEquip['items'];
$dataItemsFromForm = $dataFromForm['items'];
$dataItemsFromFormLength = count($dataItemsFromForm);
foreach ($items as $item) {
for ($i=0; $i<$dataItemsFromFormLength; $i++) {
if ((int) $item['id'] === (int) $dataItemsFromForm[$i]['id']) {
$dataItemsFromForm[$i]['itemcategory'] = $item['itemcategory'];
$dataItemsFromForm[$i]['qty'] = $item['qty'];
$dataItemsFromForm[$i]['lab'] = $item['lab'];
break;
}
}
}
$dataFromForm['items'] = $dataItemsFromForm;
}
$this->view['form'] = [
'school' => $school,
'exists' => true,
'is_valid' => false,
'values' => $dataFromForm,
'raw_values' => $this->receiveEquipInputFilter->getRawValues(),
'messages' => $this->receiveEquipInputFilter->getMessages(),
'formErrorMessages' => $this->formErrorMessages
];
}
private function fileUpload($clientFile, $receivedDocumentFileName)
{
switch ($error) {
$vf = true;
$this->container["logger"]->info(sprintf(
'error code= %d, mediatype = %s, filesize= %s, sizepermitted= %s',
$clientFile->getError(), $clientFile->getClientMediaType(), $clientFile->getSize(), $this->container['settings']['receive_equip']['file_upload_max_size']
));
switch ($clientFile->getError()) {
case UPLOAD_ERR_OK:
$this->container["logger"]->info(sprintf(
'mediatype = %s, filesize= %s',
$clientFile->getClientMediaType(), $clientFile->getSize()
));
if ((int) $clientFile->getSize() > (int) $this->container['settings']['application_form']['file_upload_max_size']) {
$isValidFile = false;
$this->flash->addMessage('danger', "Η επισύναψη - αποστολή του αρχείου απέτυχε. Το μέγεθος του αρχείου υπερβαίνει το επιτρεπτό όριο");
if ((int) $clientFile->getSize() > (int) $this->container['settings']['receive_equip']['file_upload_max_size']) {
$vf = false;
array_push($this->formErrorMessages, "Η επισύναψη - αποστολή του αρχείου απέτυχε. Το μέγεθος του αρχείου υπερβαίνει το επιτρεπτό όριο της εφαρμογής Edulabs");
} else {
$clientFileName = $clientFile->getClientFilename();
$clientFileNameExt = strtolower(pathinfo($clientFileName, PATHINFO_EXTENSION));
if (in_array($clientFileNameExt, $this->container['settings']['application_form']['file_upload_extensions'])) {
if (in_array($clientFileNameExt, $this->container['settings']['receive_equip']['file_upload_types_permitted'])) {
$receivedDocumentFileName = $receivedDocumentFileName . "." . $clientFileNameExt;
$clientFile->moveTo($this->container['settings']['application_form']['file_upload_path'] . "/" . $receivedDocumentFileName);
try {
$clientFile->moveTo($this->container['settings']['receive_equip']['file_upload_path'] . "/" . $receivedDocumentFileName);
}
catch (InvalidArgumentException $e) {
array_push($this->formErrorMessages, "Η επισύναψη - αποστολή του αρχείου απέτυχε. Η διαδρομή προορισμού δεν υπάρχει");
$vf = false;
}
catch (RuntimeException $e) {
array_push($this->formErrorMessages, "Η επισύναψη - αποστολή του αρχείου απέτυχε. Σφάλμα στην μετακίνηση του αρχείου");
$vf = false;
}
} else {
$isValidFile = false;
$this->flash->addMessage('danger', "Η επισύναψη - αποστολή του αρχείου απέτυχε. Ο τύπος του αρχείου δεν είναι επιτρεπτός");
$vf = false;
array_push($this->formErrorMessages, "Η επισύναψη - αποστολή του αρχείου απέτυχε. Ο τύπος του αρχείου δεν είναι επιτρεπτός");
}
}
$response = 'There is no error, the file uploaded with success.';
break;
case UPLOAD_ERR_INI_SIZE:
$isValidFile = false;
$this->flash->addMessage('danger', "Η επισύναψη - αποστολή του αρχείου απέτυχε");
$response = 'The uploaded file exceeds the upload_max_filesize directive in php.ini.';
$vf = false;
array_push($this->formErrorMessages, "Η επισύναψη - αποστολή του αρχείου απέτυχε. Το μέγεθος του αρχείου υπερβαίνει το επιτρεπτό όριο");
break;
case UPLOAD_ERR_FORM_SIZE:
$isValidFile = false;
$this->flash->addMessage('danger', "Η επισύναψη - αποστολή του αρχείου απέτυχε");
$response = 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.';
$vf = false;
array_push($this->formErrorMessages, "Η επισύναψη - αποστολή του αρχείου απέτυχε. Το μέγεθος του αρχείου υπερβαίνει το επιτρεπτό όριο της φόρμας παραλαβής");
break;
case UPLOAD_ERR_PARTIAL:
$isValidFile = false;
$this->flash->addMessage('danger', "Η επισύναψη - αποστολή του αρχείου απέτυχε");
$response = 'The uploaded file was only partially uploaded.';
$vf = false;
array_push($this->formErrorMessages, "Η επισύναψη - αποστολή του αρχείου απέτυχε. Μόνο τμήμα του αρχείου αποστάλθηκε. Προσπαθήστε πάλι");
break;
case UPLOAD_ERR_NO_FILE:
$isValidFile = false;
$this->flash->addMessage('danger', "Η επισύναψη - αποστολή του αρχείου απέτυχε");
$response = 'No file was uploaded.';
$vf = false;
array_push($this->formErrorMessages, "Η επισύναψη - αποστολή του αρχείου απέτυχε. Το αρχείο δεν βρέθηκε. Προσπαθήστε πάλι");
break;
case UPLOAD_ERR_NO_TMP_DIR:
$isValidFile = false;
$this->flash->addMessage('danger', "Η επισύναψη - αποστολή του αρχείου απέτυχε");
$response = 'Missing a temporary folder. Introduced in PHP 4.3.10 and PHP 5.0.3.';
$vf = false;
array_push($this->formErrorMessages, "Η επισύναψη - αποστολή του αρχείου απέτυχε. Δεν υπάρχει προσωρινός χώρος αποθήκευσης");
break;
case UPLOAD_ERR_CANT_WRITE:
$isValidFile = false;
$this->flash->addMessage('danger', "Η επισύναψη - αποστολή του αρχείου απέτυχε");
$response = 'Failed to write file to disk. Introduced in PHP 5.1.0.';
$vf = false;
array_push($this->formErrorMessages, "Η επισύναψη - αποστολή του αρχείου απέτυχε. Αποτυχία αποθήκευσης");
break;
case UPLOAD_ERR_EXTENSION:
$isValidFile = false;
$this->flash->addMessage('danger', "Η επισύναψη - αποστολή του αρχείου απέτυχε");
$response = 'File upload stopped by extension. Introduced in PHP 5.2.0.';
$vf = false;
array_push($this->formErrorMessages, "Η επισύναψη - αποστολή του αρχείου απέτυχε. Η αποστολή τερματίστηκε πρόωρα");
break;
default:
$isValidFile = false;
$this->flash->addMessage('danger', "Η επισύναψη - αποστολή του αρχείου απέτυχε");
$response = 'Unknown upload error';
$vf = false;
array_push($this->formErrorMessages, "Η επισύναψη - αποστολή του αρχείου απέτυχε. Απροσδιόριστο σφάλμα");
break;
}
}
if ($vf === true) {
return $receivedDocumentFileName;
}
else {
return null;
}
}
}
......@@ -15,6 +15,7 @@ use Zend\Filter;
use Zend\InputFilter\CollectionInputFilter;
use Zend\InputFilter\Input;
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\FileInput;
use Zend\Validator;
class ReceiveEquip extends InputFilter
......@@ -30,7 +31,7 @@ class ReceiveEquip extends InputFilter
->attach(new Filter\ToInt());
$id->getValidatorChain()
->attach(new Validator\NotEmpty());
$schoolId = new Input('school_id');
$schoolId->setRequired(true)
->getFilterChain()
......@@ -46,9 +47,14 @@ class ReceiveEquip extends InputFilter
'useDomainCheck' => false,
]));
/* $received_document = new FileInput('received_document');
$received_document->getValidatorChain()
->attach(new Validator\File\UploadFile()); */
$this->add($id)
->add($schoolId)
->add($submittedBy)
// ->add($received_document)
->add($itemsInputFilter, 'items');
}
}
......@@ -17,7 +17,7 @@ use Slim\Http\Response;
use Slim\Views\Twig;
class SchoolReceiveEquip
class HandleEmptyPosts
{
/**
*
......@@ -32,10 +32,18 @@ class SchoolReceiveEquip
*/
protected $receiveEquipService;
public function __construct(Twig $view, ReceiveEquipServiceInterface $receiveEquipService, $container)
/**
*
* @var flash messages
*/
protected $flash;
public function __construct(Twig $view, ReceiveEquipServiceInterface $receiveEquipService, $flash, $container)
{
$this->view = $view;
$this->receiveEquipService = $receiveEquipService;
$this->receiveEquipService = $receiveEquipService;
$this->flash = $flash;
$this->container = $container;
}
......@@ -43,28 +51,17 @@ class SchoolReceiveEquip
{
$school = $req->getAttribute('school');
$receiveEquip = $this->receiveEquipService->findSchoolReceiveEquip($school->id);
if ($receiveEquip) {
$receiveEquip['items'] = array_reduce($receiveEquip['items'], function ($aggr, $item) {
$category = $item['itemcategory_id'];
if (!isset($aggr[$category])) {
$aggr[$category] = [
'category' => $item['itemcategory'],
'count' => 0,
'countAcquired' => 0,
'available' => 'LATEST'
];
}
$aggr[$category]['count'] += $item['qty'];
$aggr[$category]['countAcquired'] += $item['qtyacquired'];
return $aggr;
}, []);
if(empty($_FILES) && empty($_POST) && isset($_SERVER['REQUEST_METHOD']) && strtolower($_SERVER['REQUEST_METHOD']) == 'post'){ //catch file overload error...
$postMax = ini_get('post_max_size'); //grab the size limits...
$this->flash->addMessage('danger', "Αποστείλατε αρχείο με μέγεθος ανώτερο του επιτρεπτού");
$this->container["logger"]->info(sprintf(
'post max size exceeded'
));
return $res->withRedirect($req->getUri());
}
else {
return $next($req, $res);
}
$this->view['receiveEquip'] = $receiveEquip;
return $next($req, $res);
}
}
......@@ -76,6 +76,7 @@ public function __construct($logger) {
$receiveEquip['items'] = array_map(function ($itemBean) {
return array_merge($itemBean->export(), [
'itemcategory' => $itemBean->itemcategory->name,
'lab' => $itemBean->lab->name,
'version' => $itemBean->itemcategory->groupflag,
]);
}, $bean->ownApplicationformitemList);
......
......@@ -2,16 +2,15 @@
{% macro itemCount(name, label, value, index, minvalue, type) %}
<div class="form-group">
<div class="col-xs-12 col-sm-12 col-md-9">
<input placeholder="{{ label|striptags }}" class="form-control input-sm" min="{{ minvalue|default(1)}}"
type="{{ type|default('number') }}" name="items[{{ index | default('<%= index %>') | raw }}][{{ name }}]" value="{{ value|default('')|raw }}">
</div>
<input placeholder="{{ label|striptags }}" class="form-control input-sm" min="{{ minvalue|default(1)}}" type="{{ type|default('number') }}" name="items[{{ index | default('<%= index %>') | raw }}][{{ name }}]" value="{{ value|default('')|raw }}">
</div>
{% endmacro %}
{% macro infoBox(boxtype, msg) %}
<div class="alert alert-{{ boxtype }} alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Κλείσιμο"><span aria-hidden="true">&times;</span></button>
<button type="button" class="close" data-dismiss="alert" aria-label="Κλείσιμο">
<span aria-hidden="true">&times;</span>
</button>
<p class="text-{{ boxtype }}">{{ msg | raw }}</p>
</div>
{% endmacro %}
......@@ -19,112 +18,134 @@
{% block content %}
{% import _self as macros %}
<div id="receive-equip">
<h1>
{% block title %}
Παραλαβή <small>νέου εξοπλισμού</small>
{% endblock %}
</h1>
<div id="receive-equip">
<h1>
{% block title %}
Παραλαβή
<small>νέου εξοπλισμού</small>
{% endblock %}
</h1>
{% for fem in form.formErrorMessages %}
{{ macros.infoBox('danger', fem) }}
{% endfor %}
<form method="post" action="" data-is-valid="{{ form.is_valid | default(true) ? '1' : '0' }}"
data-messages="{{ form.messages|default({})|json_encode }}" enctype="multipart/form-data">
<div class="form-group">
<p>
Σε αυτή την καρτέλα θα καταχωρήσετε τον αριθμό των τεμαχίων που
παραλάβατε από κάθε είδος που περιλάμβανε η αίτησή σας. Επίσης,
πρέπει να υπογράψετε, να σαρώσετε και να επισυνάψετε το σαρωμένο
δελτίο παραλαβής. Τέλος, επιλέξτε "Υποβολή" για να αποστείλετε
οριστικά τη φόρμα παραλαβής.
</p>
</div>
<div class="col-md-12" style="margin-top: 20px;">
<div class="panel panel-default">
<div class="panel-heading">
<h4>Στοιχεία εγκεκριμένης αίτησης</h4>
</div>
<div class="panel-body">
{% if form.exists %}
<div class="row">
<dl class="col-sm-12 col-md-6">
<dt>A/A εγκεκριμένης αίτησης</dt>
<dd>{{ form.values.id }}</dd>
<dt>Ημερ. υποβολής</dt>
<dd>{{ form.values.submitted|date('d/m/Y') }}<dd>
<dt>Ημερ. παραλαβής</dt>
<dd>{{ form.values.received_ts|date('d/m/Y') }}<dd>
</dl>