<?php namespace vonRotenberg\WeinanlieferungBundle\EventListener; use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; use Contao\CoreBundle\Monolog\ContaoContext; use Contao\MemberModel; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Filesystem\Filesystem; use vonRotenberg\WeinanlieferungBundle\Event\CheckInCompletedEvent; use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungLageModel; use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungLeseartModel; use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungRebsorteModel; /** * Listener for the CheckInCompletedEvent. * Generates a CSV export file for each checked-in booking. */ class CheckInCompletedListener implements EventSubscriberInterface { /** * @var LoggerInterface */ private $logger; /** * @var string */ private $projectDir; /** * Constructor. * * @param LoggerInterface $logger * @param string $projectDir */ public function __construct(LoggerInterface $logger, string $projectDir) { $this->logger = $logger; $this->projectDir = $projectDir; } /** * Returns an array of event names this subscriber wants to listen to. * * @return array The event names to listen to */ public static function getSubscribedEvents() { return [ CheckInCompletedEvent::NAME => 'onCheckInCompleted', ]; } /** * Handle the check-in completed event. * * @param CheckInCompletedEvent $event */ public function onCheckInCompleted(CheckInCompletedEvent $event) { // Get the reservation data from the event $reservationData = $event->getReservationData(); $reservationModel = $event->getReservationModel(); // Log the event for testing purposes $this->logger->log( LogLevel::INFO, sprintf('Check-in completed for reservation ID: %s', $reservationData['id']), ['contao' => new ContaoContext(__METHOD__, 'CHECK_IN')] ); // Generate and save the CSV export $this->generateCsvExport($reservationData, $reservationModel); } /** * Generate and save the CSV export file. * * @param array $reservationData * @param object $reservationModel */ private function generateCsvExport(array $reservationData, $reservationModel) { // Create export directory if it doesn't exist $exportDir = $this->projectDir . '/export/check_in'; $filesystem = new Filesystem(); if (!$filesystem->exists($exportDir)) { $filesystem->mkdir($exportDir, 0755); } // Get member data $memberId = $reservationData['uid']; $memberModel = MemberModel::findById($memberId); if (null === $memberModel) { $this->logger->log( LogLevel::ERROR, sprintf('Could not find member with ID: %s', $memberId), ['contao' => new ContaoContext(__METHOD__, 'CHECK_IN_CSV_EXPORT')] ); return; } // Get behaelter numbers $behaelterNumbers = json_decode($reservationData['behaelter_numbers'], true); if (!is_array($behaelterNumbers) || empty($behaelterNumbers)) { $this->logger->log( LogLevel::ERROR, sprintf('No behaelter numbers found for reservation ID: %s', $reservationData['id']), ['contao' => new ContaoContext(__METHOD__, 'CHECK_IN_CSV_EXPORT')] ); return; } // Format check-in date $checkInDate = date('d.m.Y', $reservationData['checked_in_on']); // Get sorten (grape varieties and harvest types) $sortenData = []; $sortenLeseartPairs = explode(';', $reservationData['sorten']); foreach ($sortenLeseartPairs as $pair) { if (empty($pair)) { continue; } list($sorteId, $leseartId) = explode(',', $pair); $rebsorteModel = WeinanlieferungRebsorteModel::findById($sorteId); $leseartModel = WeinanlieferungLeseartModel::findById($leseartId); if (null !== $rebsorteModel && null !== $leseartModel) { $sortenData[] = [ 'rebsorte_id' => $rebsorteModel->ident_string, 'rebsorte_title' => $rebsorteModel->title, 'leseart_id' => $leseartModel->ident_string, 'leseart_title' => $leseartModel->title ]; } } // Get lagen (locations) $lagenData = []; $lagenIds = explode(',', $reservationData['lage']); foreach ($lagenIds as $lageId) { if (empty($lageId)) { continue; } $lageModel = WeinanlieferungLageModel::findById($lageId); if (null !== $lageModel) { $lagenData[] = [ 'lage_id' => $lageModel->ident_string, 'lage_title' => $lageModel->title ]; } } // Get ernteart (harvest method) $ernteartValues = explode(',', $reservationData['ernteart']); $ernteartMapping = [ 'handlese' => 'H', 'vollernter' => 'V' ]; // Prepare CSV data $csvData = []; // For each behaelter, create a line in the CSV foreach ($behaelterNumbers as $behaelterNumber) { // Skip special value 9999 if needed if ($behaelterNumber === '9999') { continue; } // Use the first sorte, leseart, and lage if available $rebsorteId = !empty($sortenData) ? $sortenData[0]['rebsorte_id'] : ''; $rebsorteTitle = !empty($sortenData) ? $sortenData[0]['rebsorte_title'] : ''; $leseartId = !empty($sortenData) ? $sortenData[0]['leseart_id'] : ''; $leseartTitle = !empty($sortenData) ? $sortenData[0]['leseart_title'] : ''; $lageId = !empty($lagenData) ? $lagenData[0]['lage_id'] : ''; $lageTitle = !empty($lagenData) ? $lagenData[0]['lage_title'] : ''; // Map ernteart values to H/V $ernteart = ''; foreach ($ernteartValues as $value) { if (isset($ernteartMapping[$value])) { $ernteart = $ernteartMapping[$value]; break; } } // Create CSV line $csvData[] = [ $memberModel->memberno, // member id $memberModel->firstname . ' ' . $memberModel->lastname, // member first and lastname $rebsorteId, // rebsorte identifikator $rebsorteTitle, // rebsorte title $lageId, // lage identifikator $lageTitle, // lage title $leseartId, // leseart identifikator $leseartTitle, // leseart title $ernteart, // ernteart (H for handlese, V for vollernter) $behaelterNumber, // behaelter number $checkInDate, // check-in date $reservationData['behaelter'] // behaelter amount for the whole checked-in booking ]; } // Generate CSV file $filename = $reservationData['id'] . '_' . $memberModel->memberno . '.csv'; $filepath = $exportDir . '/' . $filename; $file = fopen($filepath, 'w'); foreach ($csvData as $line) { fputcsv($file, $line, ';'); } fclose($file); $this->logger->log( LogLevel::INFO, sprintf('CSV export created for reservation ID: %s at %s', $reservationData['id'], $filepath), ['contao' => new ContaoContext(__METHOD__, 'CHECK_IN_CSV_EXPORT')] ); } }