Laravel-Excel: [QUESTION] or [BUG] Export only includes the first batch/chunk

Prerequisites

Versions

  • PHP version: 7.4
  • Laravel version: 7.27
  • Package version: 3.1.21

Description

I have an export that relies on a query, the export works fine except that it only includes the first chunk, or first batch.
For example, if the Laravel-Excel chunk_size configuration is set to 1000 the generated file will be 1000, if I set to 2000 it will be 2000 and so on.
I already tried generating an Excel file and a CSV file, the issue is the same.

I searched on the GitHub issues a lot and I could not find anything that points me to a solution.

Additional Information

Here’s my export:

<?php

namespace App\Exports;

use App\Models\PatientSchedule\PatientScheduleModel;
use Carbon\CarbonInterface;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;

class PatientScheduleExport implements FromQuery, WithHeadings, WithMapping, ShouldQueue
{
    use Exportable;

    public const EXPORT_FILE_NAME = 'agenda_pacientes.xlsx';

    private Collection $filters;

    public function __construct(Collection $filters)
    {
        $this->filters = $filters;
    }

    public function headings(): array
    {
        return [
            'Data',
            'Horário',
            'Procedimento',
            'Especialidade',
            'CRA',
            'Paciente',
            'Profissional',
            'Status',
            'Check-In',
            'Triagem',
            'Atendimento',
            'Retorno',
            'Médico Retorno',
            'Quantidade',
            'Alteração',
            'Notificação',
        ];
    }

    public function map($row): array
    {
        return [
            $this->formatDate($row->appointment_date),
            $row->appointment_time,
            $row->procedure,
            $row->speciality_type,
            $row->external_id,
            $row->patient_name,
            $row->doctor_name,
            $row->status,
            $this->formatDate($row->received, 'H:i:s'),
            $this->formatDate($row->screened, 'H:i:s'),
            $this->formatDate($row->attended, 'H:i:s'),
            $this->checkStatus($row->mr_schedule_appointment, $row->procedure, $row->status),
            $row->mr_doctor_return_name,
            $row->mr_quantity,
            $this->checkStatus($row->mr_abnormal, $row->procedure, $row->status),
            $this->checkStatus($row->mr_notification, $row->procedure, $row->status),
        ];
    }

    public function query()
    {
        return PatientScheduleModel::query()->toExport($this->filters);
    }

    private function checkStatus($status, $procedure, $appointment_status)
    {
        if ('EXAME' === strtoupper($procedure) && 'ATTENDED' === strtoupper($appointment_status)) {
            if (! $status) {
                return 'não';
            }

            return 'sim';
        }

        return null;
    }

    private function formatDate($date, string $format = 'd/m/Y')
    {
        if ($date instanceof CarbonInterface) {
            return $date->format($format);
        }

        return $date;
    }
}

And here’s the toExport query you see I’m calling above (I omitted some query details cause I don’t think they are necessary):


    public function toExport(\Illuminate\Support\Collection $filters)
    {
        return $this
            ->select([
                'patient_schedules.appointment_date',
                'patient_schedules.appointment_time',
                'schedule_procedures.description as procedure',
                'speciality_types.type as speciality_type',
                'patients.external_id',
                'patients.name as patient_name',
                'doctors.name as doctor_name',
                'patient_schedule_status.label as status',
                'medical_reports.qty as mr_quantity',
                'medical_reports.schedule_appointment as mr_schedule_appointment',
                'medical_reports.abnormal as mr_abnormal',
                'medical_reports.notification as mr_notification',
            ])
            ->addSelect([
                'received' => PatientScheduleStatusEventModel::query()->select('created_at')
                    ->whereColumn('patient_schedule_status_events.patient_schedule_id', '=', 'patient_schedules.id')
                    ->where('patient_schedule_status_events.new_status', '=', PatientScheduleStatusModel::RECEIVED)
                    ->limit(1),
            ])
            ->addSelect([
                'screened' => PatientScheduleStatusEventModel::query()->select('created_at')
                    ->whereColumn('patient_schedule_status_events.patient_schedule_id', '=', 'patient_schedules.id')
                    ->where('patient_schedule_status_events.new_status', '=', PatientScheduleStatusModel::SCREENED)
                    ->limit(1),
            ])
            ->addSelect([
                'attended' => PatientScheduleStatusEventModel::query()->select('created_at')
                    ->whereColumn('patient_schedule_status_events.patient_schedule_id', '=', 'patient_schedules.id')
                    ->where('patient_schedule_status_events.new_status', '=', PatientScheduleStatusModel::ATTENDED)
                    ->limit(1),
            ])
            ->addSelect([
                'mr_doctor_return_name' => DB::table('doctors as d')->select('name')
                    ->whereColumn('medical_reports.appointment_doctor_id', 'd.id')
                    ->where('medical_reports.schedule_appointment', '=', 1)
                    ->limit(1),
            ])
            ->withCasts([
                'received' => 'datetime',
                'screened' => 'datetime',
                'attended' => 'datetime',
            ])
            ->joinDoctors()
            ->joinPatients()
            ->joinSpecialityTypes()
            ->joinScheduleProcedures()
            ->joinPatientScheduleStatus()
            ->joinMedicalReports()
            ->when($filters->has('appointment_date'), static function (PatientScheduleQueryBuilder $query) use ($filters) {
                $filter = json_decode($filters->get('appointment_date'), true);

                return $query->whereBetween('patient_schedules.appointment_date', [$filter['from'], $filter['to']]);
            })
            ->when($filters->has('procedure_id'), static function (PatientScheduleQueryBuilder $query) use ($filters) {
                return $query->where('patient_schedules.procedure_id', '=', $filters->get('procedure_id'));
            })
            ->when($filters->has('speciality_type_id'), static function (PatientScheduleQueryBuilder $query) use ($filters) {
                return $query->where('patient_schedules.speciality_type_id', '=', $filters->get('speciality_type_id'));
            })
            ->when($filters->has('doctor_id'), static function (PatientScheduleQueryBuilder $query) use ($filters) {
                return $query->where('patient_schedules.doctor_id', '=', $filters->get('doctor_id'));
            })
            ->when($filters->has('appointment_status'), static function (PatientScheduleQueryBuilder $query) use ($filters) {
                $status = $filters->get('appointment_status');

                return $query->{$status}();
            })
            ->groupBy('patient_schedules.id', 'schedule_procedures.description', 'patient_schedule_status.label')
            ->orderByRaw('doctors.name')
            ->orderBy(
                PatientScheduleStatusEventModel::query()->select('created_at')
                    ->whereColumn('patient_schedule_status_events.patient_schedule_id', '=', 'patient_schedules.id')
                    ->where('patient_schedule_status_events.new_status', '=', PatientScheduleStatusModel::RECEIVED)
                    ->limit(1)
            );
    }

Thanks!

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 15 (6 by maintainers)

Most upvoted comments