... | ... |
@@ -9,6 +9,7 @@ |
9 | 9 |
*/ |
10 | 10 |
|
11 | 11 |
use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungRebsorteModel; |
12 |
+use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungReservationModel; |
|
12 | 13 |
use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungSlotsModel; |
13 | 14 |
use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungStandortModel; |
14 | 15 |
|
... | ... |
@@ -21,3 +22,4 @@ $GLOBALS['BE_MOD']['content']['weinanlieferung'] = array |
21 | 22 |
$GLOBALS['TL_MODELS']['tl_vr_wa_slot'] = WeinanlieferungSlotsModel::class; |
22 | 23 |
$GLOBALS['TL_MODELS']['tl_vr_wa_standort'] = WeinanlieferungStandortModel::class; |
23 | 24 |
$GLOBALS['TL_MODELS']['tl_vr_wa_rebsorte'] = WeinanlieferungRebsorteModel::class; |
25 |
+$GLOBALS['TL_MODELS']['tl_vr_wa_reservation'] = WeinanlieferungReservationModel::class; |
24 | 26 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,63 @@ |
1 |
+<?php |
|
2 |
+ |
|
3 |
+/** |
|
4 |
+ * This file is part of contao-weinanlieferung-bundle. |
|
5 |
+ * |
|
6 |
+ * (c) vonRotenberg |
|
7 |
+ * |
|
8 |
+ * @license commercial |
|
9 |
+ */ |
|
10 |
+ |
|
11 |
+use Contao\DC_Table; |
|
12 |
+use Contao\DataContainer; |
|
13 |
+ |
|
14 |
+$GLOBALS['TL_DCA']['tl_vr_wa_reservation'] = array |
|
15 |
+( |
|
16 |
+ |
|
17 |
+ // Config |
|
18 |
+ 'config' => array |
|
19 |
+ ( |
|
20 |
+ 'sql' => array |
|
21 |
+ ( |
|
22 |
+ 'keys' => array |
|
23 |
+ ( |
|
24 |
+ 'id' => 'primary', |
|
25 |
+ 'pid' => 'index' |
|
26 |
+ ) |
|
27 |
+ ) |
|
28 |
+ ), |
|
29 |
+ |
|
30 |
+ 'fields' => array |
|
31 |
+ ( |
|
32 |
+ 'id' => array |
|
33 |
+ ( |
|
34 |
+ 'sql' => "int(10) unsigned NOT NULL auto_increment" |
|
35 |
+ ), |
|
36 |
+ 'pid' => array |
|
37 |
+ ( |
|
38 |
+ 'foreignKey' => 'tl_vr_wa_slot.time', |
|
39 |
+ 'sql' => "int(10) unsigned NOT NULL default '0'", |
|
40 |
+ 'relation' => array('type' => 'belongsTo', 'load' => 'lazy') |
|
41 |
+ ), |
|
42 |
+ 'tstamp' => array |
|
43 |
+ ( |
|
44 |
+ 'sql' => "int(10) unsigned NOT NULL default '0'" |
|
45 |
+ ), |
|
46 |
+ 'uid' => array |
|
47 |
+ ( |
|
48 |
+ 'foreignKey' => 'tl_member.username', |
|
49 |
+ 'sql' => "int(10) unsigned NOT NULL default '0'", |
|
50 |
+ 'relation' => array('type' => 'belongsTo', 'load' => 'lazy') |
|
51 |
+ ), |
|
52 |
+ 'behaelter' => array |
|
53 |
+ ( |
|
54 |
+ 'sql' => "smallint(3) unsigned NOT NULL default 0", |
|
55 |
+ ), |
|
56 |
+ 'sorten' => array |
|
57 |
+ ( |
|
58 |
+ 'foreignKey' => 'tl_vr_wa_rebsorte.title', |
|
59 |
+ 'sql' => "blob NULL", |
|
60 |
+ 'relation' => array('type' => 'hasMany', 'load' => 'lazy') |
|
61 |
+ ), |
|
62 |
+ ) |
|
63 |
+); |
... | ... |
@@ -5,16 +5,42 @@ |
5 | 5 |
<dd>{{ slot.time|date('d.m.Y H:i') }}</dd> |
6 | 6 |
|
7 | 7 |
<dt>Verfügbare Behälterkapazität</dt> |
8 |
- <dd>{{ slot.behaelter }}</dd> |
|
8 |
+ <dd>{{ slot.behaelterAvailable }}</dd> |
|
9 | 9 |
|
10 | 10 |
<dt>Verarbeitete Sorten</dt> |
11 | 11 |
<dd>{{ slot.sorte|join(', ') }}</dd> |
12 | 12 |
</dl> |
13 |
- |
|
13 |
+ <h3>Reservieren</h3> |
|
14 |
+ {% if buchen.buchbar %} |
|
15 |
+ <form hx-post="/_ajax/vr_wa/v1/slot?do=reservate"> |
|
16 |
+ <input type="hidden" name="id" value="{{ id }}"> |
|
17 |
+ <div class="dflex"> |
|
18 |
+ <div> |
|
19 |
+ <label for="res-behaelter">Liefernde Behältermenge</label> |
|
20 |
+ <select id="res-behaelter" name="behaelter" required> |
|
21 |
+ <option value="">-</option> |
|
22 |
+ {% for option in buchen.behaelter %} |
|
23 |
+ <option value="{{ option }}">{{ option }}</option> |
|
24 |
+ {% endfor %} |
|
25 |
+ </select> |
|
26 |
+ </div> |
|
27 |
+ <fieldset> |
|
28 |
+ <legend>Anliefernde Rebsorte(n)</legend> |
|
29 |
+ {% for value,label in buchen.sorten %} |
|
30 |
+ <label><input type="checkbox" name="sorten[]" value="{{ value }}"> <span class="checkable">{{ label }}</span></label><br> |
|
31 |
+ {% endfor %} |
|
32 |
+ </fieldset> |
|
33 |
+ <div> |
|
34 |
+ <button type="submit">Reservieren</button> |
|
35 |
+ </div> |
|
36 |
+ </div> |
|
37 |
+ </form> |
|
38 |
+ {% else %} |
|
39 |
+ <p class="warning">Dieser Zeit-Slot ist bereits ausgebucht</p> |
|
40 |
+ {% endif %} |
|
14 | 41 |
</div> |
15 | 42 |
</div> |
16 | 43 |
<script> |
17 |
- |
|
18 | 44 |
(function ($) { |
19 | 45 |
|
20 | 46 |
window.modals = window.modals || [] |
... | ... |
@@ -1,26 +1,57 @@ |
1 |
-<div hx-get="{{ insert_tag('env::request') }}" hx-headers='{"SR-Ajax": "CommunityFriendsModule"}' hx-trigger="updateWaList from:body" class="{{ class }} content-wrapper block"{{ cssID }}{% if style is defined and style is not empty %} style="{{ style }}"{% endif %}> |
|
1 |
+<div hx-get="{{ insert_tag('env::request') }}" hx-headers='{"VR-Ajax": "WaSlotsModule"}' hx-trigger="updateWaList from:body" class="{{ class }} content-wrapper block"{{ cssID }}{% if style is defined and style is not empty %} style="{{ style }}"{% endif %}> |
|
2 |
+ |
|
3 |
+ {% block filter %} |
|
4 |
+ <form hx-get="{{ insert_tag('env::request') }}" hx-headers='{"VR-Ajax": "WaSlotsModule"}' hx-trigger="change, submit" hx-target="closest .content-wrapper" class="filter"> |
|
5 |
+ <div class="flex"> |
|
6 |
+ <div class="full two-fifth-500 kapazitaet"> |
|
7 |
+ <select name="filter_kapazitaet"> |
|
8 |
+ <option value="">-</option> |
|
9 |
+ {% for option in filter.kapazitaet.options %} |
|
10 |
+ <option value="{{ option }}"{% if filter.kapazitaet.selected is defined and filter.kapazitaet.selected == option %} selected{% endif %}>{{ option }}</option> |
|
11 |
+ {% endfor %} |
|
12 |
+ </select> |
|
13 |
+ </div> |
|
14 |
+ <div class="full two-fifth-500 sorte"> |
|
15 |
+ <select name="filter_sorte"> |
|
16 |
+ <option value="">-</option> |
|
17 |
+ {% for key, option in filter.sorte.options %} |
|
18 |
+ <option value="{{ key }}"{% if filter.sorte.selected is defined and filter.sorte.selected == key %} selected{% endif %}>{{ option }}</option> |
|
19 |
+ {% endfor %} |
|
20 |
+ </select> |
|
21 |
+ </div> |
|
22 |
+ <div class="full fifth-500 submit"><button>Filter übernehmen</button></div> |
|
23 |
+ </div> |
|
24 |
+ </form> |
|
25 |
+ {% endblock %} |
|
2 | 26 |
|
3 | 27 |
{% block content %} |
4 |
- {% if slots is defined and slots|length %} |
|
28 |
+ {% if days is defined and days|length %} |
|
5 | 29 |
<div class="list"> |
6 |
- {% for slot in slots %} |
|
7 |
- <div class="row"> |
|
8 |
- <div class="flex align-items-center"> |
|
9 |
- <div class="full half-500 third-900 time"> |
|
10 |
- <span class="title">Tag/Uhrzeit</span> |
|
11 |
- {{ slot.time|date('d.m.Y H:i') }} |
|
12 |
- </div> |
|
13 |
- <div class="full half-500 fourth-900 behaelter"> |
|
14 |
- <span class="title">Verfügbare Behälterkapazität</span> |
|
15 |
- {{ slot.behaelter }} |
|
16 |
- </div> |
|
17 |
- <div class="full two-third-500 fourth-900 rebsorten"> |
|
18 |
- <span class="title">Verarbeitete Sorten</span> |
|
19 |
- {{ slot.sorte }} |
|
20 |
- </div> |
|
21 |
- <div class="full third-500 sixth-900 align-right action"> |
|
22 |
- <a href="javascript:;" class="button">Anzeigen</a> |
|
23 |
- </div> |
|
30 |
+ {% for day,slots in days %} |
|
31 |
+ <h3 class="toggler-dis">{{ day|date('d.m.Y') }}<span class="counter">{{ slots|length }}</span></h3> |
|
32 |
+ <div class="accordion-dis"> |
|
33 |
+ <div class="slots"> |
|
34 |
+ {% for slot in slots %} |
|
35 |
+ <div class="row{{ not slot.buchbar ? ' error' : '' }}"> |
|
36 |
+ <div class="flex align-items-center"> |
|
37 |
+ <div class="full half-500 third-900 time"> |
|
38 |
+ <span class="title">Uhrzeit</span> |
|
39 |
+ {{ slot.time|date('H:i') }} |
|
40 |
+ </div> |
|
41 |
+ <div class="full half-500 fourth-900 behaelter"> |
|
42 |
+ <span class="title">Verfügbare Behälterkapazität</span> |
|
43 |
+ {{ slot.behaelterAvailable }} |
|
44 |
+ </div> |
|
45 |
+ <div class="full two-third-500 fourth-900 rebsorten"> |
|
46 |
+ <span class="title">Verarbeitete Sorten</span> |
|
47 |
+ {{ slot.sorte|join(', ') }} |
|
48 |
+ </div> |
|
49 |
+ <div class="full third-500 sixth-900 align-right action"> |
|
50 |
+ <a hx-get="/_ajax/vr_wa/v1/slot?do=details&id={{ slot.id }}" hx-target="body" hx-swap="beforeend" href="javascript:;" class="button{{ not slot.buchbar ? ' pseudo' : '' }}">Anzeigen</a> |
|
51 |
+ </div> |
|
52 |
+ </div> |
|
53 |
+ </div> |
|
54 |
+ {% endfor %} |
|
24 | 55 |
</div> |
25 | 56 |
</div> |
26 | 57 |
{% endfor %} |
... | ... |
@@ -28,4 +59,26 @@ |
28 | 59 |
{% endif %} |
29 | 60 |
{% endblock %} |
30 | 61 |
|
62 |
+ {% block script %} |
|
63 |
+ {#<script> |
|
64 |
+ jQuery(function($) { |
|
65 |
+ $(".mod_wa_slots_list").accordion({ |
|
66 |
+ // Put custom options here |
|
67 |
+ heightStyle: 'content', |
|
68 |
+ header: '.toggler', |
|
69 |
+ collapsible: true, |
|
70 |
+ create: function(event, ui) { |
|
71 |
+ ui.header.addClass('active'); |
|
72 |
+ $('.toggler').attr('tabindex', 0); |
|
73 |
+ }, |
|
74 |
+ activate: function(event, ui) { |
|
75 |
+ ui.newHeader.addClass('active'); |
|
76 |
+ ui.oldHeader.removeClass('active'); |
|
77 |
+ $('.toggler').attr('tabindex', 0); |
|
78 |
+ } |
|
79 |
+ }); |
|
80 |
+ }); |
|
81 |
+ </script>#} |
|
82 |
+ {% endblock %} |
|
83 |
+ |
|
31 | 84 |
</div> |
... | ... |
@@ -15,11 +15,14 @@ namespace vonRotenberg\WeinanlieferungBundle\Controller\Frontend\Ajax; |
15 | 15 |
use Contao\CoreBundle\Controller\AbstractController; |
16 | 16 |
use Contao\CoreBundle\Framework\ContaoFramework; |
17 | 17 |
use Contao\CoreBundle\Security\Authentication\Token\TokenChecker; |
18 |
+use Contao\FrontendUser; |
|
19 |
+use Contao\Input; |
|
18 | 20 |
use Contao\System; |
19 | 21 |
use Symfony\Component\HttpFoundation\Request; |
20 | 22 |
use Symfony\Component\HttpFoundation\Response; |
21 | 23 |
use Symfony\Component\Routing\Annotation\Route; |
22 | 24 |
use Symfony\Contracts\Translation\TranslatorInterface; |
25 |
+use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungReservationModel; |
|
23 | 26 |
use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungSlotsModel; |
24 | 27 |
|
25 | 28 |
/** |
... | ... |
@@ -57,6 +60,9 @@ class SlotAjaxController extends AbstractController |
57 | 60 |
case 'details': |
58 | 61 |
return $this->renderDetails(); |
59 | 62 |
break; |
63 |
+ |
|
64 |
+ case 'reservate': |
|
65 |
+ return $this->reservate(); |
|
60 | 66 |
} |
61 | 67 |
|
62 | 68 |
return new Response('',500); |
... | ... |
@@ -78,20 +84,59 @@ class SlotAjaxController extends AbstractController |
78 | 84 |
$arrSorten = []; |
79 | 85 |
if (($Sorten = $Slot->getRelated('sorte')) !== null) |
80 | 86 |
{ |
81 |
- $arrSorten = $Sorten->fetchEach('title'); |
|
87 |
+ $arrSorten = array_combine($Sorten->fetchEach('id'),$Sorten->fetchEach('title')); |
|
82 | 88 |
} |
83 | 89 |
|
90 |
+ $intAvailableBehaelter = $Slot->getAvailableBehaelter(); |
|
91 |
+ |
|
84 | 92 |
$arrData = [ |
85 | 93 |
'id' => $Slot->id, |
86 | 94 |
'slot' => array_merge($Slot->row(),[ |
87 |
- 'sorte' => $arrSorten |
|
95 |
+ 'sorte' => $arrSorten, |
|
96 |
+ 'behaelterAvailable' => $intAvailableBehaelter |
|
88 | 97 |
]), |
89 |
- 'standort' => $Slot->getRelated('pid') |
|
98 |
+ 'standort' => $Slot->getRelated('pid'), |
|
99 |
+ 'buchen' => [ |
|
100 |
+ 'buchbar' => (boolean) $intAvailableBehaelter, |
|
101 |
+ 'behaelter' => range(min($intAvailableBehaelter,1),$intAvailableBehaelter), |
|
102 |
+ 'sorten' => $arrSorten |
|
103 |
+ ] |
|
90 | 104 |
]; |
91 | 105 |
|
92 | 106 |
return $this->render('@Contao/modal_slot_details.html.twig',$arrData); |
93 | 107 |
} |
94 | 108 |
|
109 |
+ protected function reservate() |
|
110 |
+ { |
|
111 |
+ if (empty($_REQUEST['id']) || empty(Input::post('behaelter')) || empty(Input::post('sorten'))) |
|
112 |
+ { |
|
113 |
+ return new Response('Missing parameter',500); |
|
114 |
+ } |
|
115 |
+ |
|
116 |
+ $arrSorten = []; |
|
117 |
+ if (!is_array(Input::post('sorten'))) |
|
118 |
+ { |
|
119 |
+ $arrSorten[] = Input::post('sorten'); |
|
120 |
+ } else { |
|
121 |
+ $arrSorten = implode(',', Input::post('sorten')); |
|
122 |
+ } |
|
123 |
+ |
|
124 |
+ $Reservation = new WeinanlieferungReservationModel(); |
|
125 |
+ |
|
126 |
+ $Reservation->setRow([ |
|
127 |
+ 'pid' => $_REQUEST['id'], |
|
128 |
+ 'tstamp' => time(), |
|
129 |
+ 'uid' => FrontendUser::getInstance()->id, |
|
130 |
+ 'behaelter' => Input::post('behaelter'), |
|
131 |
+ 'sorten' => $arrSorten |
|
132 |
+ ]); |
|
133 |
+ |
|
134 |
+ |
|
135 |
+ $Reservation->save(); |
|
136 |
+ |
|
137 |
+ return new Response('<p>Reservierung erfolgreich</p>'); |
|
138 |
+ } |
|
139 |
+ |
|
95 | 140 |
protected function renderUnauthorized() |
96 | 141 |
{ |
97 | 142 |
return $this->render('@Contao/modal_unauthorized.html.twig'); |
... | ... |
@@ -12,13 +12,18 @@ declare(strict_types=1); |
12 | 12 |
|
13 | 13 |
namespace vonRotenberg\WeinanlieferungBundle\Controller\Frontend\Module; |
14 | 14 |
|
15 |
+use Contao\Controller; |
|
15 | 16 |
use Contao\CoreBundle\Controller\FrontendModule\AbstractFrontendModuleController; |
17 |
+use Contao\CoreBundle\Exception\ResponseException; |
|
18 |
+use Contao\CoreBundle\InsertTag\InsertTagParser; |
|
16 | 19 |
use Contao\CoreBundle\ServiceAnnotation\FrontendModule; |
20 |
+use Contao\Date; |
|
17 | 21 |
use Contao\ModuleModel; |
18 | 22 |
use Contao\StringUtil; |
19 | 23 |
use Contao\Template; |
20 | 24 |
use Symfony\Component\HttpFoundation\Request; |
21 | 25 |
use Symfony\Component\HttpFoundation\Response; |
26 |
+use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungRebsorteModel; |
|
22 | 27 |
use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungSlotsModel; |
23 | 28 |
|
24 | 29 |
/** |
... | ... |
@@ -28,22 +33,71 @@ class WeinanlieferungSlotsListModuleController extends AbstractFrontendModuleCon |
28 | 33 |
{ |
29 | 34 |
public const TYPE = 'wa_slots_list'; |
30 | 35 |
|
36 |
+ private $insertTagParser; |
|
37 |
+ |
|
38 |
+ public function __construct(InsertTagParser $insertTagParser) |
|
39 |
+ { |
|
40 |
+ $this->insertTagParser = $insertTagParser; |
|
41 |
+ } |
|
42 |
+ |
|
43 |
+ |
|
31 | 44 |
protected function getResponse(Template $template, ModuleModel $model, Request $request): ?Response |
32 | 45 |
{ |
33 | 46 |
$standortIds = StringUtil::deserialize($model->vr_wa_standortId); |
34 |
- |
|
35 | 47 |
$arrData = $template->getData(); |
48 |
+ $arrOptions = []; |
|
36 | 49 |
|
37 |
- if (($slots = WeinanlieferungSlotsModel::findMultiplePublishedByPids($standortIds)) !== null) |
|
50 |
+ // Add filter values |
|
51 |
+ if (!empty($_GET['filter_kapazitaet'])) |
|
52 |
+ { |
|
53 |
+ $arrData['filter']['kapazitaet']['selected'] = $_GET['filter_kapazitaet']; |
|
54 |
+ $arrOptions['column'][] = 'behaelter = ?'; |
|
55 |
+ $arrOptions['value'][] = $_GET['filter_kapazitaet']; |
|
56 |
+ } |
|
57 |
+ if (!empty($_GET['filter_sorte'])) |
|
38 | 58 |
{ |
59 |
+ $arrData['filter']['sorte']['selected'] = $_GET['filter_sorte']; |
|
60 |
+ $arrOptions['column'][] = 'FIND_IN_SET(?,sorte)'; |
|
61 |
+ $arrOptions['value'][] = $_GET['filter_sorte']; |
|
62 |
+ } |
|
63 |
+ $arrData['filter']['kapazitaet']['options'] = range(1,30); |
|
64 |
+ |
|
65 |
+ if (($Sorten = WeinanlieferungRebsorteModel::findAll(['order'=>'title ASC'])) !== null) |
|
66 |
+ { |
|
67 |
+ $arrData['filter']['sorte']['options'] = array_combine($Sorten->fetchEach('id'),$Sorten->fetchEach('title')); |
|
68 |
+ } |
|
69 |
+ |
|
70 |
+ // Get available slots |
|
71 |
+ if (($slots = WeinanlieferungSlotsModel::findMultiplePublishedByPids($standortIds,$arrOptions)) !== null) |
|
72 |
+ { |
|
73 |
+ /** @var WeinanlieferungSlotsModel $slot */ |
|
39 | 74 |
foreach ($slots as $slot) |
40 | 75 |
{ |
41 |
- $arrData['slots'][] = $slot->row(); |
|
76 |
+ $day = new Date($slot->date); |
|
77 |
+ $arrSorten = []; |
|
78 |
+ $intAvailableBehaelter = $slot->getAvailableBehaelter(); |
|
79 |
+ |
|
80 |
+ if (($Sorten = $slot->getRelated('sorte')) !== null) |
|
81 |
+ { |
|
82 |
+ $arrSorten = $Sorten->fetchEach('title'); |
|
83 |
+ } |
|
84 |
+ |
|
85 |
+ $arrData['days'][$day->dayBegin][] = array_merge($slot->row(),[ |
|
86 |
+ 'sorte' => $arrSorten, |
|
87 |
+ 'behaelterAvailable' => $intAvailableBehaelter, |
|
88 |
+ 'buchbar' => (boolean) $intAvailableBehaelter |
|
89 |
+ ]); |
|
42 | 90 |
} |
43 | 91 |
} |
44 | 92 |
|
45 | 93 |
$template->setData($arrData); |
46 | 94 |
|
95 |
+ // Handle ajax |
|
96 |
+ if ($request->headers->get('VR-Ajax') == 'WaSlotsModule') |
|
97 |
+ { |
|
98 |
+ throw new ResponseException(new Response($this->insertTagParser->replace($template->parse()))); |
|
99 |
+ } |
|
100 |
+ |
|
47 | 101 |
return $template->getResponse(); |
48 | 102 |
} |
49 | 103 |
|
50 | 104 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,24 @@ |
1 |
+<?php |
|
2 |
+ |
|
3 |
+declare(strict_types=1); |
|
4 |
+ |
|
5 |
+/* |
|
6 |
+ * This file is part of contao-weinanlieferung-bundle. |
|
7 |
+ * |
|
8 |
+ * (c) vonRotenberg |
|
9 |
+ * |
|
10 |
+ * @license commercial |
|
11 |
+ */ |
|
12 |
+ |
|
13 |
+namespace vonRotenberg\WeinanlieferungBundle\Model; |
|
14 |
+ |
|
15 |
+use Contao\Model; |
|
16 |
+ |
|
17 |
+class WeinanlieferungReservationModel extends Model |
|
18 |
+{ |
|
19 |
+ /** |
|
20 |
+ * Table name |
|
21 |
+ * @var string |
|
22 |
+ */ |
|
23 |
+ protected static $strTable = 'tl_vr_wa_reservation'; |
|
24 |
+} |
... | ... |
@@ -12,9 +12,11 @@ declare(strict_types=1); |
12 | 12 |
|
13 | 13 |
namespace vonRotenberg\WeinanlieferungBundle\Model; |
14 | 14 |
|
15 |
+use Contao\Controller; |
|
15 | 16 |
use Contao\Database; |
16 | 17 |
use Contao\Model; |
17 | 18 |
use Contao\Model\Registry; |
19 |
+use Doctrine\DBAL\Connection; |
|
18 | 20 |
|
19 | 21 |
class WeinanlieferungSlotsModel extends Model |
20 | 22 |
{ |
... | ... |
@@ -40,7 +42,7 @@ class WeinanlieferungSlotsModel extends Model |
40 | 42 |
$arrOptions['order'] = "$t.time ASC"; |
41 | 43 |
} |
42 | 44 |
|
43 |
- return static::findBy($arrColumns, $intId, $arrOptions); |
|
45 |
+ return static::findOneBy($arrColumns, $intId, $arrOptions); |
|
44 | 46 |
} |
45 | 47 |
|
46 | 48 |
public static function findPublishedByPid($intPid, array $arrOptions=array()) |
... | ... |
@@ -94,4 +96,22 @@ class WeinanlieferungSlotsModel extends Model |
94 | 96 |
|
95 | 97 |
return static::findBy($arrColumns,null,$arrOptions); |
96 | 98 |
} |
99 |
+ |
|
100 |
+ public function getAvailableBehaelter() |
|
101 |
+ { |
|
102 |
+ /** @var Connection $db */ |
|
103 |
+ $db = Controller::getContainer()->get('database_connection'); |
|
104 |
+ |
|
105 |
+ $ReservedBehaelter = $db->prepare("SELECT SUM(behaelter) FROM tl_vr_wa_reservation WHERE pid = ?") |
|
106 |
+ ->executeQuery([$this->id]); |
|
107 |
+ |
|
108 |
+ $intReserved = $ReservedBehaelter->fetchOne(); |
|
109 |
+ |
|
110 |
+ if ($intReserved === null) |
|
111 |
+ { |
|
112 |
+ $intReserved = 0; |
|
113 |
+ } |
|
114 |
+ |
|
115 |
+ return (int) $this->behaelter - $intReserved; |
|
116 |
+ } |
|
97 | 117 |
} |