diff --git a/trunk/app/Resources/views/default/admin/imagesNew.html.twig b/trunk/app/Resources/views/default/admin/fewoImage.html.twig similarity index 67% rename from trunk/app/Resources/views/default/admin/imagesNew.html.twig rename to trunk/app/Resources/views/default/admin/fewoImage.html.twig index c526a013..adc069a6 100644 --- a/trunk/app/Resources/views/default/admin/imagesNew.html.twig +++ b/trunk/app/Resources/views/default/admin/fewoImage.html.twig @@ -4,16 +4,20 @@ {% block body %}
-

Neues Bild für "{{ lodging.name }}" anlegen

+

Bild für "{{ lodging.name }}" anlegen / bearbeiten

{{ form_errors(form) }} -
-
- {{ form_row(form.file, {label: 'Bild'}) }} + {% if is_new %} + {{ form_row(form.file, {label: 'Bild'}) }} + {% else %} +
+ {{ image.description }} +
+ {% endif %} {{ form_row(form.fileName, {label: 'Name'}) }} {{ form_row(form.description, {label: 'Beschreibung'}) }} @@ -25,7 +29,8 @@
- {{ form_rest(form) }} + + {{ form_widget(form._token) }} +
+

Mehrere Bilder für "{{ lodging.name }}" hochladen

+ +
+ + {{ form_errors(form) }} + +
+ {{ form(form) }} +
+ +
+ +
+
+
+ +
+ Zurück + +
+
+{% endblock body %} \ No newline at end of file diff --git a/trunk/app/Resources/views/default/admin/lodgingsEdit.html.twig b/trunk/app/Resources/views/default/admin/lodgingsEdit.html.twig index d2d717a6..0b051e76 100644 --- a/trunk/app/Resources/views/default/admin/lodgingsEdit.html.twig +++ b/trunk/app/Resources/views/default/admin/lodgingsEdit.html.twig @@ -24,7 +24,6 @@ {{ form_row(form.city, {'label': 'Ort'}) }} {{ form_row(form.maximumPersons, {'label': 'Maximale Personenanzahl'}) }} {{ form_row(form.deposit, {'label': 'Kaution'}) }} - {{ form_row(form.onlyWeekday, {'label': 'Exklusiver Wochentag'}) }} {#
@@ -52,13 +51,17 @@ {% for image in lodging.images %} - {{ image.description }} + {{ image.description }} {{ image.fileName }} {{ image.description }} + + Bearbeiten + Löschen @@ -71,12 +74,12 @@

Keine Bilder vorhanden

{% endif %} - + Hinzufügen + + Mehrere Bilder hochladen +

diff --git a/trunk/app/Resources/views/default/admin/lodgingsEditCalendar.html.twig b/trunk/app/Resources/views/default/admin/lodgingsEditCalendar.html.twig index d9a56281..8362c1ac 100644 --- a/trunk/app/Resources/views/default/admin/lodgingsEditCalendar.html.twig +++ b/trunk/app/Resources/views/default/admin/lodgingsEditCalendar.html.twig @@ -1,9 +1,9 @@ -{% for monthIndex in 0..11 %} +{% for calendar_month in calendar %} @@ -21,7 +21,7 @@ {% for dayIndex in 0..6 %} {# @var dayState \AppBundle\Util\CalendarDayState #} - {% set dayState = calendar[monthIndex]['data'][(weekIndex * 7) + dayIndex] %} + {% set dayState = calendar_month['data'][(weekIndex * 7) + dayIndex] %} {% set is_past_date = dayState.date is not empty and date(dayState.date) < date('now') %} @@ -47,7 +47,7 @@ {{ dayState.day }} {% elseif dayState.isBookable and not is_past_date %} - + {{ dayState.day }} {% elseif dayState.day == 0 %} diff --git a/trunk/app/Resources/views/default/admin/lodgingsNew.html.twig b/trunk/app/Resources/views/default/admin/lodgingsNew.html.twig index 988a6400..b6ab752a 100644 --- a/trunk/app/Resources/views/default/admin/lodgingsNew.html.twig +++ b/trunk/app/Resources/views/default/admin/lodgingsNew.html.twig @@ -24,7 +24,6 @@ {{ form_row(form.city, {label: 'Ort'}) }} {{ form_row(form.maximumPersons, {label: 'Maximale Personenanzahl'}) }} {{ form_row(form.deposit, {label: 'Kaution'}) }} - {{ form_row(form.onlyWeekday, {label: 'Exklusiver Wochentag'}) }} {#
diff --git a/trunk/app/Resources/views/default/admin/seasonsEdit.html.twig b/trunk/app/Resources/views/default/admin/seasonsEdit.html.twig index 902185f0..fd1c0e5a 100644 --- a/trunk/app/Resources/views/default/admin/seasonsEdit.html.twig +++ b/trunk/app/Resources/views/default/admin/seasonsEdit.html.twig @@ -18,8 +18,7 @@ {{ form_row(form.toDate, {label: 'Bis'}) }} {{ form_row(form.minimumStay, {label: 'Mindestbelegung in Tagen'}) }} {{ form_row(form.description, {label: 'Beschreibung'}) }} - - + {{ form_row(form.onlyWeekday, {label: 'Exklusiver Wochentag'}) }}
- {{ calendar[monthIndex]['monthName'] }} {{ calendar[monthIndex]['year'] }} + {{ calendar_month['monthName'] }} {{ calendar_month['year'] }}
@@ -23,7 +23,7 @@ {% for dayIndex in 0..6 %} {# @var dayState \AppBundle\Util\CalendarDayState #} - {% set dayState = calendar[monthIndex]['data'][(weekIndex * 7) + dayIndex] %} + {% set dayState = calendar_month['data'][(weekIndex * 7) + dayIndex] %} {% set is_past_date = dayState.date is not empty and date(dayState.date) < date('now') %} @@ -43,7 +43,7 @@ @@ -132,6 +132,10 @@ {{ form_field_pho(form.city, 'Ort') }} +
+ {{ form_field_pho(form.nation, 'Land') }} +
+
{{ form_field_pho(form.phone, 'Telefon tagsüber') }}
diff --git a/trunk/src/AppBundle/Controller/AdminController.php b/trunk/src/AppBundle/Controller/AdminController.php index 60141336..f294e7d8 100644 --- a/trunk/src/AppBundle/Controller/AdminController.php +++ b/trunk/src/AppBundle/Controller/AdminController.php @@ -24,10 +24,13 @@ use AppBundle\Service\FileManager; use AppBundle\Util; use Doctrine\Bundle\DoctrineCacheBundle\Tests\Functional\FileSystemCacheTest; use Doctrine\ORM\EntityManager; +use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\Filesystem\Filesystem; +use Symfony\Component\Form\Extension\Core\Type\FileType; use Symfony\Component\HttpFoundation\File; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Security\Http\Authentication\AuthenticationUtils; @@ -159,17 +162,17 @@ class AdminController extends Controller $lodging = null; - $calendarUtil = $this->container->get('app.lodging_calendar_util'); + $calendarService = $this->container->get('app.lodging_calendar_util'); $lodging = $fewoLodgingRepo->find($lodgingId); - $reservations = $calendarUtil->getReservations($lodging); + $reservations = $calendarService->getReservations($lodging); - $paddedCalendar = $calendarUtil->getCalendarWithPadding(); - $calendar = $calendarUtil->getCalendar(); + $paddedCalendar = $calendarService->getCalendarWithPadding($calendarService->getMinCalendarEntriesByLodging($lodging)); + $calendar = $calendarService->getCalendar($lodging); if (count($lodging->getPrices()->toArray()) != 0) { - $calendar = $calendarUtil->getCalendarWithReservations($lodging); - $calendar = $calendarUtil->mergeWithPaddedCalendar($calendar, $paddedCalendar); + $calendar = $calendarService->createCalendarAndFillDayStates($lodging); + $calendar = $calendarService->mergeWithPaddedCalendar($calendar, $paddedCalendar); } else { $calendar = $paddedCalendar; } @@ -230,16 +233,13 @@ class AdminController extends Controller $lodging = $fewoLodgingRepo->find($lodgingId); - $calendarUtil = $this->container->get('app.lodging_calendar_util'); + $calendarService = $this->container->get('app.lodging_calendar_util'); - $reservations = $calendarUtil->getReservations($lodging); - - $paddedCalendar = $calendarUtil->getCalendarWithPadding(); - $calendar = $calendarUtil->getCalendar(); + $paddedCalendar = $calendarService->getCalendarWithPadding($calendarService->getMinCalendarEntriesByLodging($lodging)); if (count($lodging->getPrices()->toArray()) != 0) { - $calendar = $calendarUtil->getCalendarWithReservations($lodging); - $calendar = $calendarUtil->mergeWithPaddedCalendar($calendar, $paddedCalendar); + $calendar = $calendarService->createCalendarAndFillDayStates($lodging); + $calendar = $calendarService->mergeWithPaddedCalendar($calendar, $paddedCalendar); } else { $calendar = $paddedCalendar; } @@ -771,51 +771,133 @@ class AdminController extends Controller return $this->redirect('/admin/fewo/seasons'); } + /** + * @Route("/admin/fewo/lodgings/{lodgingId}/images/multi-upload", requirements={"lodgingId": "\d+"}) + */ + public function adminFewoImageMultiUploadAction(Request $request, $lodgingId) + { + $em = $this->getEntityManager(); + $lodging = $em->getRepository('AppBundle:FewoLodging')->find($lodgingId); + if (!$lodging) + { + throw new HttpException(404, 'Unbekannte lodging-ID: '. $lodgingId); + } + + $form = $this->createForm(FileType::class, null, [ + 'multiple' => true + ]); + if ($request->getMethod() == 'POST') + { + $form->handleRequest($request); + if ($form->isValid()) + { + $uploader = $this->container->get('app.image_uploader'); + foreach ($form->getData() as $uploadedFile) + { + $image = new FewoLodgingImage(); + $image->setFile($uploadedFile); + $image->setLodging($lodging); + $image->setFileName(''); + $image->setDescription(''); + $em->persist($image); + $em->flush(); + } + return $this->redirect('/admin/fewo/lodgings/'. $lodging->getId()); + } + } + + return $this->render('default/admin/fewoImageMultiUpload.html.twig', [ + 'form' => $form->createView(), + 'lodging' => $lodging, + ]); + } + /** * @Route("/admin/fewo/lodgings/{lodgingId}/images/new", requirements={"lodgingId": "\d+"}) */ public function adminFewoNewImageAction(Request $request, $lodgingId) + { + $lodging = $this->getEntityManager()->getRepository('AppBundle:FewoLodging')->find($lodgingId); + if (!$lodging) + { + throw new HttpException(404, 'Unbekannte lodging-ID: '. $lodgingId); + } + return $this->processImageForm($request, null, $lodging); + } + + /** + * @Route("/admin/fewo/lodgings/{lodgingId}/images/{imageId}", requirements={"lodgingId": "\d+", "imageId": "\d+"}) + */ + public function adminFewoEditImageAction(Request $request, $lodgingId, $imageId) + { + /** @var FewoLodgingImage $image */ + $image = $this->getEntityManager()->getRepository('AppBundle:FewoLodgingImage')->find($imageId); + if (!$image || $image->getLodging()->getId() != $lodgingId) + { + throw new HttpException(404, 'Unbekannte FewoLodgingImage-ID oder lodging-ID passt nicht: '. + $imageId .' / '. $lodgingId); + } + return $this->processImageForm($request, $image); + } + + /** + * @param Request $request + * @param FewoLodgingImage $image + * @param FewoLodging|null $lodging + * + * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response + */ + public function processImageForm(Request $request, $image, $lodging = null) { $em = $this->getEntityManager(); - $fewoLodgingRepo = $em->getRepository('AppBundle:FewoLodging'); - $lodging = $fewoLodgingRepo->find($lodgingId); + if ($image == null) + { + $isNew = true; + } + else + { + $isNew = false; + $lodging = $image->getLodging(); + $imageFileName = $image->getFile(); + } - $image = null; - if ($request->getMethod() != 'POST') + if ($request->getMethod() != 'POST' && $image == null) { $image = new FewoLodgingImage(); } - $form = $this->createForm(FewoLodgingImageType::class, $image, [ - - ]); + $form = $this->createForm(FewoLodgingImageType::class, $image); if ($request->getMethod() == 'POST') { $form->handleRequest($request); - $image = $form->getData(); } if ($request->getMethod() == 'POST' && $form->isValid()) { - - if($lodging == null) + $image = $form->getData(); + if ($isNew) { - return $this->redirect('/admin/fewo/lodgings'); + $image->setLodging($lodging); + } + else + { + $image->setFile($imageFileName); } - - $image->setLodging($lodging); $em->persist($image); $em->flush(); - return $this->redirect('/admin/fewo/lodgings/'.$lodgingId); + return $this->redirect('/admin/fewo/lodgings/'. ($lodging->getId())); } - return $this->render('default/admin/imagesNew.html.twig', [ + return $this->render('default/admin/fewoImage.html.twig', [ 'form' => $form->createView(), 'lodging' => $lodging, + 'is_new' => $isNew, + 'image_file_name' => $isNew ? null : $imageFileName, + 'image' => $image, ]); } diff --git a/trunk/src/AppBundle/Controller/BookingController.php b/trunk/src/AppBundle/Controller/BookingController.php index 0fda1ac8..4c5a8331 100644 --- a/trunk/src/AppBundle/Controller/BookingController.php +++ b/trunk/src/AppBundle/Controller/BookingController.php @@ -93,7 +93,14 @@ class BookingController extends Controller $em->flush(); $crmBookingUrl = $this->get('app.booking_exporter')->process($bookingRequest, $travelDate, $bookingPriceInfo); - $crmBookingUrl = preg_replace('/\\/api/', '', $crmBookingUrl) .'/edit'; + if (!$crmBookingUrl) + { + $crmBookingUrl = '[CRM-EXPORT FEHLGESCHLAGEN]'; + } + else + { + $crmBookingUrl = preg_replace('/\\/api/', '', $crmBookingUrl).'/edit'; + } $this->get('mailer')->send(\Swift_Message::newInstance() ->setSubject('Ihr Buchungsauftrag bei STERN TOURS') diff --git a/trunk/src/AppBundle/Controller/CmsController.php b/trunk/src/AppBundle/Controller/CmsController.php index 2a26c3fd..f689894f 100644 --- a/trunk/src/AppBundle/Controller/CmsController.php +++ b/trunk/src/AppBundle/Controller/CmsController.php @@ -49,11 +49,16 @@ class CmsController extends Controller public function overviewAction(Page $page) { - return $this->render('default/pages/cms/overview.html.twig', [ + $settings = $page->getCmsSettings(); + if (!is_array($settings)) + { + $settings = []; + } + + return $this->render('default/pages/cms/overview.html.twig', array_merge($settings, [ 'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR, 'page' => $page, - // TODO - ]); + ])); } public function travelProgramOverviewAction(Page $page) @@ -126,17 +131,14 @@ class CmsController extends Controller public function fewoLodgingAction(Page $page) { - //$calendarUtil = new Util\LodgingCalendarUtil(); - $calendarUtil = $this->container->get('app.lodging_calendar_util'); - //$fewoLodgingRepo = $this->getEntityManager()->getRepository('AppBundle:FewoLodging'); + $calendarService = $this->container->get('app.lodging_calendar_util'); $lodging = $page->getFewoLodging(); - $paddedCalendar = $calendarUtil->getCalendarWithPadding(); - $calendar = $calendarUtil->getCalendar(); + $paddedCalendar = $calendarService->getCalendarWithPadding($calendarService->getMinCalendarEntriesByLodging($lodging)); if (count($lodging->getPrices()->toArray()) != 0) { - $calendar = $calendarUtil->getCalendarWithReservations($lodging); - $calendar = $calendarUtil->mergeWithPaddedCalendar($calendar, $paddedCalendar); + $calendar = $calendarService->createCalendarAndFillDayStates($lodging); + $calendar = $calendarService->mergeWithPaddedCalendar($calendar, $paddedCalendar); } else { $calendar = $paddedCalendar; } diff --git a/trunk/src/AppBundle/Controller/FewoBookingController.php b/trunk/src/AppBundle/Controller/FewoBookingController.php index d609dd0f..24f016a1 100644 --- a/trunk/src/AppBundle/Controller/FewoBookingController.php +++ b/trunk/src/AppBundle/Controller/FewoBookingController.php @@ -43,9 +43,7 @@ class FewoBookingController extends Controller */ public function indexAction(Page $fewoTravelProgramPage, $action, Request $request) { - - //$calendarUtils = new Util\LodgingCalendarUtil(); - $calendarUtil = $this->container->get('app.lodging_calendar_util'); + $calendarService = $this->container->get('app.lodging_calendar_util'); $em = $this->getEntityManager(); //$fewoLodgingRepo = $em->getRepository('AppBundle:FewoLodging'); $fewoPriceRepo = $em->getRepository('AppBundle:FewoPrice'); @@ -66,7 +64,7 @@ class FewoBookingController extends Controller $season = $price->getSeason(); $minimumStay = $season->getMinimumStay(); - $fromDate = $calendarUtil->convertDate($fromDate); + $fromDate = $calendarService->convertDate($fromDate); $fromDateTime = new \DateTime($fromDate); $toDate = ''; @@ -82,16 +80,59 @@ class FewoBookingController extends Controller $fewoBookingRequest->setLodging($lodging); $fewoBookingRequest->setPrice($price); + $allowedToDateStrs = []; + if (!$lodging->getPrices()->isEmpty()) + { + $nightsSinceFromDate = 0; + $calendar = $calendarService->createCalendarAndFillDayStates($lodging); + $areAllowedToDatesCollected = false; + foreach ($calendar as $calendarMonth) + { + if ($calendarMonth['year'] < $fromDateTime->format('Y') || + $calendarMonth['monthNumber'] < $fromDateTime->format('n')) + { + continue; + } + /** @var Util\CalendarDayState[] $dayStates */ + $dayStates = $calendarMonth['data']; + $i = 0; + if ($calendarMonth['year'] == $fromDateTime->format('Y') && + $calendarMonth['monthNumber'] == $fromDateTime->format('n')) + { + $i = intval($fromDateTime->format('j')) - 1; + } + for (; $i < count($dayStates); ++$i) + { + if ($nightsSinceFromDate >= $season->getMinimumStay()) + { + $dayState = $dayStates[$i]; + if ($dayState->getIsInSeason() && (!$dayState->getIsReserved() || + ($dayState->getIsReservationBegin() && !$dayState->getIsReservationEnd()))) + { + $allowedToDateStrs[] = $dayState->getDate()->format('Y-m-d'); + } + else + { + $areAllowedToDatesCollected = true; + break; + } + } + ++$nightsSinceFromDate; + } + if ($areAllowedToDatesCollected) + { + break; + } + } + if (!empty($allowedToDateStrs)) + { + $toDate = $allowedToDateStrs[0]; + } + } + if ($request->getMethod() != 'POST') { - $dateAppendix = " + ".($minimumStay - 1)." day"; - if($minimumStay > 1) - { - $dateAppendix= $dateAppendix."s"; - } - - $toDate = date('d.m.Y', strtotime($fromDate.$dateAppendix)); $fewoBookingRequest->setFromDate($fromDate); $fewoBookingRequest->setToDate($toDate); $fewoBookingRequest->setNumberDays($minimumStay); @@ -144,7 +185,14 @@ class FewoBookingController extends Controller $em->flush(); $crmBookingUrl = $this->get('app.fewo_booking_exporter')->process($fewoBookingRequest, $lodging, $price);//, $travelDate, $bookingPriceInfo); - $crmBookingUrl = preg_replace('/\\/api/', '', $crmBookingUrl) . '/edit'; + if (!$crmBookingUrl) + { + $crmBookingUrl = '[CRM-EXPORT FEHLGESCHLAGEN]'; + } + else + { + $crmBookingUrl = preg_replace('/\\/api/', '', $crmBookingUrl) . '/edit'; + } $this->get('mailer')->send(\Swift_Message::newInstance() ->setSubject('Ihr FeWo-Buchungsauftrag bei STERN TOURS') @@ -208,9 +256,9 @@ class FewoBookingController extends Controller 'fewo_price' => $price, 'total_price' => $totalPrice, 'total_price_per_night' => $perDayTotalPrice, + 'allowed_to_dates' => implode(';', $allowedToDateStrs), 'page' => $fewoTravelProgramPage, 'show_search_sidebar_widget' => false, - ]); } diff --git a/trunk/src/AppBundle/Entity/FewoLodging.php b/trunk/src/AppBundle/Entity/FewoLodging.php index 360858e5..f015ed4d 100644 --- a/trunk/src/AppBundle/Entity/FewoLodging.php +++ b/trunk/src/AppBundle/Entity/FewoLodging.php @@ -125,13 +125,6 @@ class FewoLodging //------------------------------------------------------------------------------------------------------------------ // Kalender - /** - * @var integer - * - * @ORM\Column(name="only_weekday", type="integer", nullable=true) - */ - private $onlyWeekday; - /** * @var \AppBundle\Entity\FewoReservation * @@ -411,30 +404,6 @@ class FewoLodging return $this->deposit; } - /** - * Set onlyWeekday - * - * @param integer $onlyWeekday - * - * @return FewoLodging - */ - public function setOnlyWeekday($onlyWeekday) - { - $this->onlyWeekday = $onlyWeekday; - - return $this; - } - - /** - * Get onlyWeekday - * - * @return integer - */ - public function getOnlyWeekday() - { - return $this->onlyWeekday; - } - /** * Set calendarVisible * diff --git a/trunk/src/AppBundle/Entity/FewoLodgingRepository.php b/trunk/src/AppBundle/Entity/FewoLodgingRepository.php index 748a9ea3..d9f455a2 100644 --- a/trunk/src/AppBundle/Entity/FewoLodgingRepository.php +++ b/trunk/src/AppBundle/Entity/FewoLodgingRepository.php @@ -1,6 +1,7 @@ getEntityManager()->createQueryBuilder(); + $qb->select('s'); + $qb->from('AppBundle:FewoSeason', 's'); + $qb->innerJoin('s.prices', 'p'); + $qb->where($qb->expr()->eq('p.lodging', $lodging->getId())); + $qb->addOrderBy('s.toDate', 'DESC'); + $qb->setMaxResults(1); + return $qb->getQuery()->getOneOrNullResult(); } } diff --git a/trunk/src/AppBundle/Entity/FewoSeason.php b/trunk/src/AppBundle/Entity/FewoSeason.php index 4dbd86d1..bee0fabe 100644 --- a/trunk/src/AppBundle/Entity/FewoSeason.php +++ b/trunk/src/AppBundle/Entity/FewoSeason.php @@ -65,6 +65,14 @@ class FewoSeason * @ORM\Column(name="description", type="text", nullable=true) */ private $description; + + /** + * @var integer + * + * @ORM\Column(name="only_weekday", type="integer", nullable=true) + */ + private $onlyWeekday; + /** * Constructor */ @@ -242,4 +250,28 @@ class FewoSeason return $this->name; } + + /** + * Set onlyWeekday + * + * @param integer $onlyWeekday + * + * @return FewoSeason + */ + public function setOnlyWeekday($onlyWeekday) + { + $this->onlyWeekday = $onlyWeekday; + + return $this; + } + + /** + * Get onlyWeekday + * + * @return integer + */ + public function getOnlyWeekday() + { + return $this->onlyWeekday; + } } diff --git a/trunk/src/AppBundle/Entity/Page.php b/trunk/src/AppBundle/Entity/Page.php index b03e5f2c..395d8b66 100644 --- a/trunk/src/AppBundle/Entity/Page.php +++ b/trunk/src/AppBundle/Entity/Page.php @@ -1255,13 +1255,13 @@ class Page /** * Set cmsSettings * - * @param string $cmsSettings + * @param mixed $cmsSettings * * @return Page */ public function setCmsSettings($cmsSettings) { - $this->cmsSettings = $cmsSettings; + $this->cmsSettings = is_array($cmsSettings) ? json_encode($cmsSettings) : $cmsSettings; return $this; } @@ -1269,10 +1269,15 @@ class Page /** * Get cmsSettings * - * @return string + * @return mixed */ public function getCmsSettings() { - return $this->cmsSettings; + $ret = json_decode($this->cmsSettings, true); + if (empty($ret) || !is_array($ret)) + { + return $this->cmsSettings; + } + return $ret; } } diff --git a/trunk/src/AppBundle/Entity/Traveler.php b/trunk/src/AppBundle/Entity/Traveler.php index 76f099fb..1b6f26ac 100644 --- a/trunk/src/AppBundle/Entity/Traveler.php +++ b/trunk/src/AppBundle/Entity/Traveler.php @@ -32,6 +32,7 @@ class Traveler /** * @Assert\NotBlank() + * @Assert\Date() */ private $birthDate; diff --git a/trunk/src/AppBundle/Export/FewoBookingSternToursCrmExporter.php b/trunk/src/AppBundle/Export/FewoBookingSternToursCrmExporter.php index de65a327..59ced106 100644 --- a/trunk/src/AppBundle/Export/FewoBookingSternToursCrmExporter.php +++ b/trunk/src/AppBundle/Export/FewoBookingSternToursCrmExporter.php @@ -50,17 +50,17 @@ class FewoBookingSternToursCrmExporter extends SternToursCrmExporter $resp = $this->httpPost('lead', ['lead' => [ 'customerForm' => [ 'salutation_id' => $fewoBookingRequest->getSalutation(), - 'name' => $fewoBookingRequest->getLastName(), + 'name' => $fewoBookingRequest->getLastName(), // required 'firstname' => $fewoBookingRequest->getFirstName(), 'street' => $fewoBookingRequest->getStreetAddress(), 'zip' => $fewoBookingRequest->getZipCode(), 'city' => $fewoBookingRequest->getCity(), - 'country_id' => $fewoBookingRequest->getNation(), + 'country_id' => $fewoBookingRequest->getNation(), // required 'phone' => $fewoBookingRequest->getPhone(), 'fax' => $fewoBookingRequest->getFax(), 'email' => $fewoBookingRequest->getEmail() ], - 'request_date' => (new \DateTime())->format('Y-m-d'), + 'request_date' => (new \DateTime())->format('Y-m-d'), // required 'sf_guard_user_id' => self::API_USER_ID, 'status_id' => 7, // 'gebucht' 'travelperiod_start' => $fewoBookingRequest->getFromDate()->format('Y-m-d'), @@ -73,6 +73,9 @@ class FewoBookingSternToursCrmExporter extends SternToursCrmExporter 'remarks' => $fewoBookingRequest->getNotes() ]]); + //Util::varDump($resp); + //die(); + if ($resp['success']) { $ret = $this->httpGet($resp['location']); @@ -98,10 +101,10 @@ class FewoBookingSternToursCrmExporter extends SternToursCrmExporter 'branch_id' => 4, 'website_id' => self::WEBSITE_ID, 'title' => $lodging->getName(), - 'start_date' => $fewoBookingRequest->getFromDate()->format('Y-m-d'), - 'end_date' => $fewoBookingRequest->getToDate()->format('Y-m-d'), + 'start_date' => $fewoBookingRequest->getFromDate()->format('Y-m-d'), // required + 'end_date' => $fewoBookingRequest->getToDate()->format('Y-m-d'), // required 'pax' => $fewoBookingRequest->getTravelerCount(), - 'travel_number' => $lodging->getName()." - ".$price->getSeason()->getName(), + 'travel_number' => substr($lodging->getName()." - ".$price->getSeason()->getName(), 0, 30), 'price' => $fewoBookingRequest->getTotalPrice(), 'participant_salutation_id' => $fewoBookingRequest->getSalutation(), diff --git a/trunk/src/AppBundle/Form/FewoBookingRequestType.php b/trunk/src/AppBundle/Form/FewoBookingRequestType.php index 13ba9859..791d288d 100644 --- a/trunk/src/AppBundle/Form/FewoBookingRequestType.php +++ b/trunk/src/AppBundle/Form/FewoBookingRequestType.php @@ -105,6 +105,13 @@ class FewoBookingRequestType extends AbstractType ]) ->add('firstName') ->add('lastName') + ->add('nation', ChoiceType::class, [ + 'choices' => self::$NATION_CHOICES, + 'constraints' => [ + new NotNull(), + new Choice(['choices' => self::$NATION_CHOICES]) + ] + ]) ->add('streetAddress') ->add('zipCode') ->add('city') diff --git a/trunk/src/AppBundle/Form/FewoLodgingImageType.php b/trunk/src/AppBundle/Form/FewoLodgingImageType.php index 6d7afff1..be510573 100644 --- a/trunk/src/AppBundle/Form/FewoLodgingImageType.php +++ b/trunk/src/AppBundle/Form/FewoLodgingImageType.php @@ -16,7 +16,7 @@ class FewoLodgingImageType extends AbstractType { $builder ->add('file', FileType::class, [ - + 'data_class' => null ]) ->add('fileName') ->add('description') diff --git a/trunk/src/AppBundle/Form/FewoLodgingType.php b/trunk/src/AppBundle/Form/FewoLodgingType.php index 165b4b97..f36335a3 100644 --- a/trunk/src/AppBundle/Form/FewoLodgingType.php +++ b/trunk/src/AppBundle/Form/FewoLodgingType.php @@ -21,18 +21,6 @@ use AppBundle\Entity\FewoSeason; class FewoLodgingType extends AbstractType { - public static $WEEKDAY_CHOICES = [ - 'keiner' => 0, - 'Montag' => 1, - 'Dienstag' => 2, - 'Mittwoch' => 3, - 'Donnerstag' => 4, - 'Freitag' => 5, - 'Samstag' => 6, - 'Sonntag' => 7 - ]; - - /** * {@inheritdoc} @@ -65,12 +53,6 @@ class FewoLodgingType extends AbstractType ->add('deposit', null, [ 'required' => true, ]) - ->add('onlyWeekday', ChoiceType::class, [ - 'choices' => self::$WEEKDAY_CHOICES, - 'constraints' => [ - new Choice(['choices' => self::$WEEKDAY_CHOICES]) - ] - ]) //->add('calendarVisible') ->add('type', EntityType::class, [ 'placeholder' => '(Bitte wählen) *', diff --git a/trunk/src/AppBundle/Form/FewoSeasonType.php b/trunk/src/AppBundle/Form/FewoSeasonType.php index 4cfe2147..17d110e5 100644 --- a/trunk/src/AppBundle/Form/FewoSeasonType.php +++ b/trunk/src/AppBundle/Form/FewoSeasonType.php @@ -21,6 +21,17 @@ use Symfony\Component\Validator\Constraints\NotNull; class FewoSeasonType extends AbstractType { + public static $WEEKDAY_CHOICES = [ + 'beliebig' => NULL, + 'Sonntag' => 0, + 'Montag' => 1, + 'Dienstag' => 2, + 'Mittwoch' => 3, + 'Donnerstag' => 4, + 'Freitag' => 5, + 'Samstag' => 6, + ]; + /** * {@inheritdoc} */ @@ -38,6 +49,12 @@ class FewoSeasonType extends AbstractType ]) ->add('description') + ->add('onlyWeekday', ChoiceType::class, [ + 'choices' => self::$WEEKDAY_CHOICES, + 'constraints' => [ + new Choice(['choices' => self::$WEEKDAY_CHOICES]) + ] + ]) ; } diff --git a/trunk/src/AppBundle/Resources/public/js/custom.js b/trunk/src/AppBundle/Resources/public/js/custom.js index 935526ae..92daa0e0 100644 --- a/trunk/src/AppBundle/Resources/public/js/custom.js +++ b/trunk/src/AppBundle/Resources/public/js/custom.js @@ -514,7 +514,24 @@ jQuery(document).ready(function($) { dayNames: ['Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag'], dayNamesShort: ['So','Mo','Di','Mi','Do','Fr','Sa'], dayNamesMin: ['So','Mo','Di','Mi','Do','Fr','Sa'], - firstDay: 1 + firstDay: 1, + beforeShowDay: function(date) { + var allowedDateStrListStr = $(this).attr('data-allowed-dates'); + if (allowedDateStrListStr) + { + var allowedDatesStrList = allowedDateStrListStr.split(';'); + for (var i = 0; i < allowedDatesStrList.length; ++i) + { + var allowedDate = new Date(allowedDatesStrList[i]); + if (allowedDate.getDate() === date.getDate() && allowedDate.getMonth() === date.getMonth() && + allowedDate.getYear() === date.getYear()) + { + return [true, '', '']; + } + } + return [false, '', ''] + } + } }); function initAutoEndDate(startTxt$, endTxt$) diff --git a/trunk/src/AppBundle/Service/FileManager.php b/trunk/src/AppBundle/Service/FileManager.php index 6d8916be..59a6ba3b 100644 --- a/trunk/src/AppBundle/Service/FileManager.php +++ b/trunk/src/AppBundle/Service/FileManager.php @@ -14,11 +14,56 @@ class FileManager $this->targetDir = $targetDir; } + const MAX_DEST_WIDTH = 848; + const MAX_DEST_HEIGHT = 280; + public function upload(UploadedFile $file) { - $fileName = md5(uniqid()).'.'.$file->guessExtension(); + $baseFileName = md5(uniqid()); + $fileName = $baseFileName.'.'.$file->guessExtension(); $file->move($this->getTargetDir(), $fileName); + $path = $this->getTargetDir() .'/'. $fileName; + $imgInfo = getimagesize($path); + if ($imgInfo !== false) + { + $srcWidth = $imgInfo[0]; + $srcHeight = $imgInfo[1]; + switch ($imgInfo[2]) { + case IMAGETYPE_GIF : $src = imagecreatefromgif($path); break; + case IMAGETYPE_JPEG : $src = imagecreatefromjpeg($path); break; + case IMAGETYPE_PNG : $src = imagecreatefrompng($path); break; + // default: // #TODO Warning + } + if (isset($src)) + { + $tmp = imagecreatetruecolor(848, 280); + $destWidth = self::MAX_DEST_HEIGHT * $srcWidth / $srcHeight; + if ($destWidth < self::MAX_DEST_WIDTH) + { + $destWidth = self::MAX_DEST_WIDTH; + $destHeight = $destWidth * $srcHeight / $srcWidth; + $destX = 0; + $destY = ($destHeight - self::MAX_DEST_HEIGHT) / 2; + } + else + { + $destHeight = self::MAX_DEST_HEIGHT; + $destX = ($destWidth - self::MAX_DEST_WIDTH) / 2; + $destY = 0; + } + imagecopyresampled($tmp, $src, 0, 0, $destX, $destY, + $destWidth, $destHeight, $srcWidth, $srcHeight); + $newFileName = md5(uniqid()) .'.jpg'; + if (imagejpeg($tmp, $this->getTargetDir() .'/'. $newFileName, 80)) + { + $filesystem = new Filesystem(); + $filesystem->remove($this->getTargetDir() .'/'. $fileName); + return $newFileName; + } + // else #TODO warn + } + } return $fileName; } diff --git a/trunk/src/AppBundle/Service/LodgingCalendarService.php b/trunk/src/AppBundle/Service/LodgingCalendarService.php index 0b7e7d16..c86227a2 100644 --- a/trunk/src/AppBundle/Service/LodgingCalendarService.php +++ b/trunk/src/AppBundle/Service/LodgingCalendarService.php @@ -26,7 +26,7 @@ class LodgingCalendarService return $month == 2 ? ($year % 4 ? 28 : ($year % 100 ? 29 : ($year % 400 ? 28 : 29))) : (($month - 1) % 7 % 2 ? 30 : 31); } - public function getCalendarWithPadding() + public function getCalendarWithPadding($months) { $calendar = null; $currentMonth = date('n'); @@ -35,7 +35,7 @@ class LodgingCalendarService setlocale(LC_TIME, "german"); - for($m = $currentMonth; $m < ($currentMonth + 12); $m++) + for($m = $currentMonth; $m < ($currentMonth + $months); $m++) { if($m < 13) { @@ -117,9 +117,9 @@ class LodgingCalendarService } - public function getCalendar() + public function getCalendar($lodging) { - + $months = $this->getMinCalendarEntriesByLodging($lodging); $calendar = null; $currentMonth = date('n'); $currentYear = date('Y'); @@ -127,7 +127,7 @@ class LodgingCalendarService setlocale(LC_TIME, "german"); - for($m = $currentMonth; $m < ($currentMonth + 12); $m++) + for($m = $currentMonth; $m < ($currentMonth + $months); $m++) { if($m < 13) { @@ -180,6 +180,22 @@ class LodgingCalendarService return $calendar; } + /** + * Retrieve needed number of months to generate a calendar which includes all available seasons + * + * @param FewoLodging $lodging + * @return int + */ + public function getMinCalendarEntriesByLodging($lodging) + { + $latestSeason = $this->em->getRepository('AppBundle:FewoLodging')->findLatestSeasonEndForLodging($lodging); + $curMonthDate = new \DateTime(); + $curMonthDate->setDate($curMonthDate->format('Y'), $curMonthDate->format('n'), 1); + $seasonMonthDate = new \DateTime($latestSeason->getToDate()->format('Y-m-d')); + $seasonMonthDate->setDate($seasonMonthDate->format('Y'), $seasonMonthDate->format('n'), 1); + return 2 + intval($seasonMonthDate->diff($curMonthDate)->format('%m')); + } + /** * @param FewoLodging $lodging @@ -426,7 +442,7 @@ class LodgingCalendarService private function mergeCalendars($calendar, $extensionCalendar, $withFromTo = false) { - for($i = 0; $i < 12; $i++) + for($i = 0; $i < count($calendar); $i++) { /** @var CalendarDayState[] $calendarData */ $calendarData = $calendar[$i]['data']; @@ -584,10 +600,8 @@ class LodgingCalendarService */ private function filterReservableDays(FewoLodging $lodging, $calendar) { + /** @var CalendarDayState[] $potentiallyReservableDays */ $potentiallyReservableDays = []; - $priceId = 0; - /** @var FewoPrice $lastReservablePrice */ - $lastReservablePrice = null; for ($currMonthIndex = 0; $currMonthIndex < count($calendar); $currMonthIndex++) { @@ -599,140 +613,81 @@ class LodgingCalendarService { $currDay = $data[$currDayIndex]; - if ($currDay->getPrice() !== $lastReservablePrice && !$currDay->getIsInSeason()) + // We passed the season end? => All days in the stack are not reservable, as their minimum stay + // requirement would mean their reservation end is outside a season + if (!$currDay->getIsInSeason()) { - $actuallyReservableDays = $this->processPotentiallyReservableDays($potentiallyReservableDays, - $lastReservablePrice->getSeason()->getMinimumStay()); - $this->processRest($actuallyReservableDays, $lastReservablePrice, $calendar); - $potentiallyReservableDays = []; - } - if ($currDay->getIsInSeason() && (!$currDay->getIsReserved() || $currDay->getIsReservationBegin() || - $currDay->getIsReservationEnd())) - { - $currentDayDate = date("d.m.Y", strtotime($currMonth['year']."-". - $currMonth['monthNumber']."-".$currDay->getDay())); - $potentiallyReservableDays[] = $currentDayDate; + while (!empty($potentiallyReservableDays)) + { + $potentiallyReservableDay = array_pop($potentiallyReservableDays); + $potentiallyReservableDay->setIsBookable(false); + } + $currDay->setIsBookable(false); + continue; } - $lastReservablePrice = $currDay->getIsInSeason() ? $currDay->getPrice() : null; - } - } - if ($lastReservablePrice !== null) - { - $actuallyReservableDays = $this->processPotentiallyReservableDays($potentiallyReservableDays, - $lastReservablePrice->getSeason()->getMinimumStay()); - $this->processRest($actuallyReservableDays, $lastReservablePrice, $calendar); - } - return $calendar; - } + $currSeason = $currDay->getPrice()->getSeason(); - - - private function processPotentiallyReservableDays($potentiallyReservableDays, $minimumStay) - { - $coherentDays = []; - $actuallyReservableDays = []; - //$coherentDays[] = $potentiallyReservableDays[0]; - for($i = 1; $i < count($potentiallyReservableDays); $i++) - { - - if($this->isNextDay($potentiallyReservableDays[$i - 1], $potentiallyReservableDays[$i])) - { - if(count($coherentDays) == 0) + // Process the stack of reservable days and set reservable=true, if their minimum stay requirement could + // be fulfilled. Set reservable=false if there is no chance for the stack entry to be reservable. + // Remove potentially reservable days from the stack for which a final decision has been made. + if (!$currDay->getIsReserved() || $currDay->getIsReservationBegin()) { - $coherentDays[] = $potentiallyReservableDays[$i - 1]; + foreach ($potentiallyReservableDays as $k => $potentiallyReservableDay) + { + $nights = intval($potentiallyReservableDay->getDate()->diff($currDay->getDate())->format('%a')); + if ($nights >= $currSeason->getMinimumStay()) + { + $potentiallyReservableDay->setIsBookable(true); + unset($potentiallyReservableDays[$k]); + } + elseif ($currDay->getIsReservationBegin()) + { + // Reservation begin => We are absolutely sure that this day is not reservable + $potentiallyReservableDay->setIsBookable(false); + unset($potentiallyReservableDays[$k]); + } + } } - $coherentDays[] = $potentiallyReservableDays[$i]; - } - else - { - if(count($coherentDays) < $minimumStay) + + // Add the current calendar day to stack, as we need to analyse the following days in order to be able + // to decide if the day is reservable or not. + if ((!$currDay->getIsReserved() || $currDay->getIsReservationEnd()) && + ($currSeason->getOnlyWeekday() == null || $currSeason->getOnlyWeekday() == $currDay->getDate()->format('w'))) { - $coherentDays = []; - $coherentDays[] = $potentiallyReservableDays[$i]; + $potentiallyReservableDays[] = $currDay; } else { - $coherentDaysCount = count($coherentDays); - - $offset = $coherentDaysCount - ($minimumStay - 1); - - $coherentDays = array_splice($coherentDays, 0, $offset); - for($j = 0; $j < count($coherentDays); $j++) - { - $actuallyReservableDays[] = $coherentDays[$j]; - } - $coherentDays = []; + $currDay->setIsBookable(false); } } } - if(count($coherentDays) > 0) + // Remaining entries in the stack are definitely not reservable. Otherwise they would have been processed before. + foreach ($potentiallyReservableDays as $potentiallyReservableDay) { - $coherentDaysCount = count($coherentDays); - - $offset = $coherentDaysCount - ($minimumStay - 1); - - $coherentDays = array_splice($coherentDays, 0, $offset); - for($j = 0; $j < count($coherentDays); $j++) - { - $actuallyReservableDays[] = $coherentDays[$j]; - } + $potentiallyReservableDay->setIsBookable(false); } - return $actuallyReservableDays; + return $calendar; } - - private function processRest($actuallyReservableDays, FewoPrice $price, &$cleanCalendar) - { - for($currMonthIndex = 0; $currMonthIndex < count($cleanCalendar); $currMonthIndex++) - { - $currMonth = $cleanCalendar[$currMonthIndex]; - /** @var CalendarDayState[] $data */ - $data = $currMonth['data']; - - for($currDayIndex = 0; $currDayIndex < count($data); $currDayIndex++) - { - $currDay = $data[$currDayIndex]; - - $currentDate = date("d.m.Y", strtotime($currMonth['year']."-".$currMonth['monthNumber']."-".$currDay->getDay())); - - if (in_array($currentDate, $actuallyReservableDays)) - { - //$data[$currDayIndex]->setIsInSeason(true); - //$data[$currDayIndex]->setIsReserved(false); // todo ? - $data[$currDayIndex]->setIsBookable(true); - //$data[$currDayIndex]->setIsReservationBegin(false); - //$data[$currDayIndex]->setIsReservationEnd(false); // todo ? - //$data[$currDayIndex]->setPrice($price); - - $currMonth['marked'] = 1; - } - } - $currMonth['data'] = $data; - $cleanCalendar[$currMonthIndex] = $currMonth; - } - } - - - /** * @param FewoLodging $lodging * @param $calendar * @return mixed + * + * createCalendarAndFillDayStates */ - public function getCalendarWithReservations(FewoLodging $lodging) + public function createCalendarAndFillDayStates(FewoLodging $lodging) { - $today = new \DateTime(); - $pricesCalendar = $this->getCalendar(); - $reservationsCalendar = $this->getCalendar(); + $pricesCalendar = $this->getCalendar($lodging); + $reservationsCalendar = $this->getCalendar($lodging); $reservations = $lodging->getReservations(); $prices = $lodging->getPrices(); - $lodgingId = $lodging->getId(); - foreach ($prices as $price) { /** @var FewoSeason $season */
- {{ calendar[monthIndex]['monthName'] }} {{ calendar[monthIndex]['year'] }} + {{ calendar_month['monthName'] }} {{ calendar_month['year'] }}
{% if dayState.isBookable and not is_past_date %} - diff --git a/trunk/app/Resources/views/default/pages/fewoBooking.html.twig b/trunk/app/Resources/views/default/pages/fewoBooking.html.twig index 7841cb04..ee0158e3 100644 --- a/trunk/app/Resources/views/default/pages/fewoBooking.html.twig +++ b/trunk/app/Resources/views/default/pages/fewoBooking.html.twig @@ -63,7 +63,7 @@
{{ form_label(form.toDate, 'Reiseende') }} - {{ form_widget(form.toDate) }} + {{ form_widget(form.toDate, {attr: {'data-allowed-dates': allowed_to_dates}}) }} {{ form_errors(form.toDate) }}