Question export

This commit is contained in:
Jérémy Munsch 2021-09-14 10:58:00 +02:00
parent 0a7d61011f
commit 41909ff8e0
6 changed files with 177 additions and 5 deletions

View file

@ -3,10 +3,17 @@
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Http\Requests\QuestionExport;
use App\Models\Brand;
use App\Models\Question;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
use League\Csv\Writer;
use Symfony\Component\HttpFoundation\StreamedResponse;
class QuestionController extends Controller
{
@ -36,4 +43,83 @@ class QuestionController extends Controller
}
return $query;
}
public function export()
{
$brands = Brand::all();
return view('question.export', compact('brands'));
}
public function exportSubmit(QuestionExport $request)
{
$results = [];
$brand = Brand::findOrFail($request->brand);
$questions = $brand->questions->load('answers');
foreach ($questions as $question) {
$answersCounts = DB::query()
->selectRaw('count(*) as total, answer_id')
->from('customer_answer')
->whereIn('answer_id', $question->answers->pluck('id'))
->groupBy('answer_id')
->get()->keyBy('answer_id');
$results[$question->id] = [
'question' => $question->question,
'answers' => []
];
foreach ($question->answers as $answer) {
$results[$question->id]['answers'][] =
[
"$answer->answer ",
$answersCounts[$answer->id]->total ?? 0
];
}
}
$pagination = 2000;
$w = Writer::createFromString('');
$w->setDelimiter(';');
$w->setEnclosure('"');
$w->setOutputBOM(Writer::BOM_UTF8);
//We send the CSV using Symfony StreamedResponse
$response = new StreamedResponse();
$response->headers->set('Content-Encoding', 'none');
$response->headers->set('Content-Type', 'text/csv; charset=UTF-8');
$response->headers->set('Description', 'File Transfer');
$response->headers->set(
'Content-Disposition',
sprintf(
'attachment; filename="Export pour newsletter %s %s.csv"',
Carbon::now()->format('d-m-Y_H-i'),
Str::slug($brand->name)
)
);
foreach ($results as $result) {
$w->insertOne([
'question' => $result['question'],
]);
foreach ($result['answers'] as $answer) {
$w->insertOne($answer);
}
$w->insertOne([]);
}
//we create a callable to output the CSV in chunk
//with Symfony StreamResponse you can flush the body content if necessary
//see Symfony documentation for more information
$flush_threshold = 1000; //the flush value should depend on your CSV size.
$response->setCallback(function () use ($w, $flush_threshold) {
foreach ($w->chunk(1024) as $offset => $chunk) {
echo $chunk;
if ($offset % $flush_threshold === 0) {
flush();
}
}
});
return $response;
}
}

View file

@ -0,0 +1,30 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class QuestionExport extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return auth()->check();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'brand' => 'required|numeric|exists:brands,id'
];
}
}

View file

@ -42,7 +42,12 @@
@endcan
@endforeach
<h6 class="sidebar-heading px-3 mb-1 text-muted">
<span>Export pour newsletter</span>
<span>{{ __('Export de segmentation') }}</span>
</h6>
<ul class="nav flex-column mb-2">
<li class="nav-item"><a class="nav-link" href="{{ route('questions.export') }}">{{ __('Exporter des questions') }}</a></li>
</ul>
<hr>
</h6>
<ul class="nav flex-column mb-2">
<li class="nav-item"><a class="nav-link" href="{{ route('customers.export') }}">{{ __('Exporter un fichier CSV') }}</a></li>

View file

@ -0,0 +1,53 @@
@extends('layouts.app')
@section('title', sprintf('%s - %s', transFb(sprintf('models.classes.%s', strtolower(Str::plural(class_basename($modelClass)))), Str::plural(class_basename($modelClass))), __('Export')))
@section('description', sprintf('%s - %s', transFb(sprintf('models.classes.%s', strtolower(Str::plural(class_basename($modelClass)))), Str::plural(class_basename($modelClass))), __('Export')))
@section('metaIndex', 'noindex,nofollow')
@section('content')
<div class="card">
@include('crud-policies::crud.modules.flashMessage')
<div class="card-header">
<nav aria-label="breadcrumb" class="d-inline">
<ol class="breadcrumb d-inline-flex">
<li class="breadcrumb-item">
<a href="{{ route('customers.index') }}">{{ __('models.classes.customers') }}</a>
</li>
<li class="breadcrumb-item active" aria-current="page">{{ __('Exporter les réponses au questions') }}</li>
</ol>
</nav>
</div>
<div class="card-body">
<form class="mt-5 mb-5" action="{{ route('questions.exportSubmit') }}" method="POST">
@csrf
<div class="row justify-content-center">
<div class="col-lg-6 col-md-10 col-12 mb-5">
<h1>{{ __('Exporter les réponses au questions') }}</h1>
</div>
</div>
<div class="row justify-content-center">
<div class="col-lg-6 col-md-10 col-12">
<fieldset>
<legend>{{ __('La marque concernée') }}</legend>
<div class="input-group mb-3">
<label class="input-group-text" for="exportBrand">{{ __('Les client de la marque') }}</label>
<select class="form-select" id="exportBrand" name="brand" required>
<option selected value="">{{ __('Choissez une marque') }}</option>
@foreach($brands as $i => $brand)
<option value="{{ $brand->id }}">{{ $brand->name }}</option>
@endforeach
</select>
</div>
</fieldset>
</div>
</div>
<div class="row justify-content-center mt-4">
<div class="col-lg-6 col-md-10 col-12">
<button type="submit" class="btn btn-primary">{{ __('Exporter') }}</button>
</div>
</div>
</form>
</div>
</div>
@include('crud-policies::crud.modules.scriptConstants')
@endsection

View file

@ -12,7 +12,6 @@
@include('crud-policies::crud.modules.actionbar.bar', ['action' => CrudAction::viewAny()])
</div>
<div class="card-body">
<div class="row justify-content-center">
<div class="row justify-content-center">
<div class="col">
<form action="{{ url()->current() }}">

View file

@ -54,9 +54,8 @@ Route::middleware(['auth'])->group(function () {
Route::post('/single_optins/{id}/delete', [SingleOptinController::class, 'delete'])->name('single-optins-delete');
// Questions
Route::get('/questions/export', [QuestionController::class, 'export'])->name('questions.export');
Route::post('/questions/export', [QuestionController::class, 'exportSubmit'])->name('questions.exportSubmit');
Route::resource('questions', QuestionController::class);
Route::resource('questions.answers', AnswerController::class);
// Answers
// Route::resource('answers', AnswerController::class);
});