From b443543ff99263b309d32c6a55cab82a7f0cb2e1 Mon Sep 17 00:00:00 2001 From: philipp lang Date: Mon, 27 Mar 2023 23:10:51 +0200 Subject: [PATCH] add spreadsheet --- .gitignore | 1 + Plugin.php | 2 + assets/eventregistration-bela.js | 18 +---- classes/Spreadsheet.php | 49 +++++++++++- components/EventForm.php | 7 +- console/EventManageCommand.php | 36 +++++++++ jobs/ProcessSubmitJob.php | 129 +++++++++++++++++++++++++++++++ 7 files changed, 218 insertions(+), 24 deletions(-) create mode 100644 .gitignore create mode 100644 console/EventManageCommand.php create mode 100644 jobs/ProcessSubmitJob.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..57872d0 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/vendor/ diff --git a/Plugin.php b/Plugin.php index daeca1f..8521753 100644 --- a/Plugin.php +++ b/Plugin.php @@ -5,6 +5,7 @@ namespace Zoomyboy\Event; use Backend; use Carbon\Carbon; use System\Classes\PluginBase; +use Zoomyboy\Event\Console\EventManageCommand; /** * event Plugin Information File. @@ -33,6 +34,7 @@ class Plugin extends PluginBase */ public function register() { + $this->registerConsoleCommand('event.event-manage', EventManageCommand::class); } /** diff --git a/assets/eventregistration-bela.js b/assets/eventregistration-bela.js index 377cdd6..967a7f2 100644 --- a/assets/eventregistration-bela.js +++ b/assets/eventregistration-bela.js @@ -19,8 +19,6 @@ export default function (toasted) { address: '', zip: '', location: '', - courses: [], - fcourses: [], food_preferences: [], activity: 'Teilnehmer*in', gender: '', @@ -34,7 +32,7 @@ export default function (toasted) { misc: '', foto: false, parent: false, - vorteam: null, + vorteam: false, }, loading: false, finished: false, @@ -55,10 +53,6 @@ export default function (toasted) { {"id": "Weiblich", "name": "Weiblich"}, {"id": "Divers", "name": "Divers"}, ], - fcourses: [ - {"id": "Ich bin Samstags beim Abendprogramm dabei", "name": "Ich bin Samstags beim Abendprogramm dabei"}, - {"id": "Ich esse sonntag Mittag mit", "name": "Ich esse sonntag Mittag mit"}, - ], groups: [ {"id": "Gallier", "name": "Gallier (Wuppertal)"}, {"id": "Gandalf", "name": "Gandalf (SG-Mangenberg)"}, @@ -103,16 +97,6 @@ export default function (toasted) { {"id": "Glutenfrei", "name": "Ich vertrage kein Gluten"}, {"id": "Laktosefrei", "name": "Ich vertrage keine Laktose"}, ], - get courses() { - return this.data.agegroup === 'Rover' ? [ - {"id": "Schritt 2", "name": "Schritt 2"}, - ] : [ - {"id": "Baustein 2a", "name": "Baustein 2a"}, - {"id": "Baustein 2c", "name": "Baustein 2c"}, - {"id": "Baustein 3c", "name": "Baustein 3c"}, - {"id": "Schritt 2", "name": "Schritt 2"}, - ]; - }, slideTo(e, index) { if (e !== null) { e.preventDefault(); diff --git a/classes/Spreadsheet.php b/classes/Spreadsheet.php index 7083c75..09ce94a 100644 --- a/classes/Spreadsheet.php +++ b/classes/Spreadsheet.php @@ -3,12 +3,42 @@ namespace Zoomyboy\Event\Classes; use PhpOffice\PhpSpreadsheet\Spreadsheet as BaseSpreadsheet; +use PhpOffice\PhpSpreadsheet\Style\Alignment as AlignmentStyle; +use PhpOffice\PhpSpreadsheet\Style\Fill as FillStyle; use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; class Spreadsheet { private array $headers; private $sheet; + private $warningStyle = [ + 'font' => [ + 'size' => 10, + 'bold' => true, + 'color' => [ + 'rgb' => 'ff0000', + ], + ], + 'alignment' => [ + 'vertical' => AlignmentStyle::VERTICAL_CENTER, + ], + ]; + private $headerStyle = [ + 'font' => [ + 'size' => 12, + 'bold' => true, + 'color' => [ + 'rgb' => 'e9fcfc', + ], + ], + 'alignment' => [ + 'vertical' => AlignmentStyle::VERTICAL_CENTER, + ], + 'fill' => [ + 'fillType' => FillStyle::FILL_SOLID, + 'color' => ['rgb' => '117878'], + ], + ]; public function __construct(string $title) { @@ -17,6 +47,7 @@ class Spreadsheet ->setTitle($title) ->setSubject($title) ->setDescription($title); + $this->spreadsheet->getDefaultStyle()->getFont()->setSize(12); $this->spreadsheet->getActiveSheet()->setTitle('unfilled'); } @@ -31,9 +62,12 @@ class Spreadsheet { $this->spreadsheet->setActiveSheetIndex(0); $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($this->spreadsheet); - $writer->save('/home/pille/s.xlsx'); + $writer->save('/home/pille/spreadsheet.xlsx'); + // $writer->save(sys_get_temp_dir().'/spreadsheet.xlsx'); $this->spreadsheet->disconnectWorksheets(); unset($this->spreadsheet); + + return sys_get_temp_dir().'/spreadsheet.xlsx'; } public function sheet(string $name, array $data): self @@ -53,8 +87,17 @@ class Spreadsheet private function fill(array $data): self { $headers = collect($this->headers)->map(fn ($header) => $header->name)->toArray(); - $this->spreadsheet->getActiveSheet()->fromArray($headers, null, 'A1'); - $this->spreadsheet->getActiveSheet()->fromArray($data, null, 'A2'); + $this->spreadsheet->getActiveSheet()->fromArray(['Achtung: Dieses Dokument wird bei neuen Teilnehmern automatisch aktualisiert. Gespeicherte Änderungen können daher jederzeit verloren gehen. Wenn du dieses Dokument bearbeiten willst, speichere es bitte an einem anderen Ort ab und editiere es dann.'], null, 'A1'); + $this->spreadsheet->getActiveSheet()->fromArray($headers, null, 'A2'); + $this->spreadsheet->getActiveSheet()->fromArray($data, null, 'A3'); + $this->spreadsheet->getActiveSheet()->getStyle('A2:Z2')->applyFromArray($this->headerStyle); + $this->spreadsheet->getActiveSheet()->getStyle('A1')->applyFromArray($this->warningStyle); + + foreach (range('A', 'Z') as $col) { + $this->spreadsheet->getActiveSheet()->getColumnDimension($col)->setAutoSize(true); + } + $this->spreadsheet->getActiveSheet()->getRowDimension(2)->setRowHeight(18); + $this->spreadsheet->getActiveSheet()->mergeCells('A1:Z1'); return $this; } diff --git a/components/EventForm.php b/components/EventForm.php index b4c0c44..ab00c8a 100644 --- a/components/EventForm.php +++ b/components/EventForm.php @@ -5,9 +5,9 @@ namespace Zoomyboy\Event\Components; use Cms\Classes\ComponentBase; use Illuminate\Http\JsonResponse; use Illuminate\Support\Facades\Lang; -use Illuminate\Support\Facades\Mail; use Input; use Winter\Storm\Support\Facades\Validator; +use Zoomyboy\Event\Jobs\ProcessSubmitJob; use Zoomyboy\Event\Models\Event; use Zoomyboy\Event\Models\Participant; @@ -70,9 +70,8 @@ class EventForm extends ComponentBase 'event_id' => $this->event->id, 'payload' => $this->event->transformInputs(Input::all()), ]); - Mail::send('confirm_'.$this->event->slug, ['data' => $participant->payload], function ($message) use ($participant) { - $message->to($participant->email, $participant->firstname.' '.$participant->lastname); - }); + + ProcessSubmitJob::dispatch($participant->id); return response()->json([], 201); } diff --git a/console/EventManageCommand.php b/console/EventManageCommand.php new file mode 100644 index 0000000..22aac52 --- /dev/null +++ b/console/EventManageCommand.php @@ -0,0 +1,36 @@ +payload['courses']) || in_array('3c', $participant->payload['courses'])) { + echo $participant->email."\n"; + } + } + } + +} diff --git a/jobs/ProcessSubmitJob.php b/jobs/ProcessSubmitJob.php new file mode 100644 index 0000000..df40a66 --- /dev/null +++ b/jobs/ProcessSubmitJob.php @@ -0,0 +1,129 @@ +participant = Participant::find($this->participantId); + $this->event = $this->participant->event; + + $this->uploadFile(); + $this->sendMail(); + } + + private function sendMail(): void + { + Mail::send('confirm_'.$this->event->slug, ['data' => $this->participant->payload], function ($message) { + $message->to($this->participant->email, $this->participant->firstname.' '.$this->participant->lastname); + }); + } + + private function uploadFile(): void + { + $filesystem = app(Filesystem::class)->client(); + + $headers = $this->getFields()->map(fn ($field) => new SpreadsheetHeader($field['label']))->toArray(); + + $orderBy = collect($this->event->loadConfig('orderBy'))->map(fn ($order) => "{$order['key']} {$order['direction']}")->implode(','); + $groupBy = $this->event->loadConfig('groupBy'); + + $participants = Participant::where('event_id', $this->event->id)->orderByRaw($orderBy)->get()->groupBy(fn ($p) => data_get($p->payload, $groupBy)); + + $s = (new Spreadsheet('Anmeldezahlen '.$this->event->title))->headers($headers); + + if ($this->event->loadConfig('groupAll')) { + $this->makeSheet($s, 'Alle', Participant::where('event_id', $this->event->id)->orderByRaw($orderBy)->get()); + } + + foreach ($participants as $group => $groupParticipants) { + $this->makeSheet($s, $group, $groupParticipants); + } + + $spreadsheetFile = $s->generate(); + + $filesystem->write($this->event->slug.'/anmeldungen.xlsx', file_get_contents($spreadsheetFile)); + } + + private function getfields() + { + return collect($this->event->loadConfig('fields')); + } + + private function makeSheet(Spreadsheet $s, $group, $groupParticipants) + { + $groupParticipants = $groupParticipants->map(function ($participant) { + $payload = $participant->payload; + $content = $this->getFields()->map(function ($field) use ($payload) { + $type = $field['type']; + $method = 'format'.ucfirst($type); + + return $this->{$method}(data_get($payload, $field['key'])); + }); + + return $content->toArray(); + })->toArray(); + + $s->sheet($group, $groupParticipants); + } + + private function formatString(?string $input = null): string + { + return $input ?: ''; + } + + private function formatDate(?string $input = null): string + { + if (!$input) { + return ''; + } + + return Carbon::parse($input)->format('d.m.Y'); + } + + private function formatEnum(?array $input = []): string + { + if (!$input) { + return ''; + } + + return collect($input)->implode(', '); + } + + private function formatBool($input = false): string + { + return true === $input ? 'Ja' : 'Nein'; + } +}