Как получить последнюю запись об отношениях в Laravel - PullRequest
1 голос
/ 18 апреля 2019

Пользователи хранят планы в таблице invoices.Эти планы основаны на месячной основе.

Что мне нужно сделать

Я хочу добавить новую строку для пользователя, если истек срок действия его плана, и они не продлили свои планы (я не знаюне хотите обновлять старый)

Проблема

У каждого пользователя есть неограниченное количество строк в таблице invoices, поскольку они обновляются каждый месяц.Теперь, когда я пытаюсь получить их последнюю строку и проверить дату истечения срока действия, она получает и другие строки этих пользователей.

Пример

  1. У моего пользователя 3 rows в invoices
  2. два из них уже просрочены и обновлены, текущим является id=3
  3. , когда я пытаюсь истечь это id=3 и создать id=4 для этого пользователя
  4. он получает все 3 rows и отправляет пользователю 3 электронных письма.

Код

public function handle()
    {
        $invoices = Invoice::where('plan_expire', '<=', Carbon::now())->get();
        $current = Carbon::now();
        $expiredatetime = $current->addDays(30);
        $useType = Type::where('name', 'Free')->first();

        foreach($invoices as $invoice)
        {
            Invoice::create([
                'user_id' => $invoice->user->id,
                'type_id' => $useType->id,
                'amount' => $useType->price,
                'status' => 'Approved',
                'plan_expire' => $expiredatetime->toDateTimeString(),
            ]);
            Mail::to($invoice->user->email)->send(new UserPlansReset($invoice));
        }
    }

User model

public function invoices()
{
  return $this->hasMany(Invoice::class);
}

Invoice model

protected $fillable = [
        'user_id', 'type_id', 'amount', 'status', 'plan_expire',
    ];

    protected $casts = [
        'plan_expire' => 'datetime',
    ];

    public function user()
    {
        return $this->belongsTo(User::class);
    }

Вопрос

Есть ли у вас какие-либо идеи, как я могу получить только последнюю строку пользователей в таблице invoices?

Обновление

на основе ответов нижеЯ изменил свой код на:

$current = Carbon::now();
        $expiredatetime = $current->addDays(30);
        $useType = Type::where('name', 'Free')->first();

        $users = User::all();
        foreach($users as $user){
          $latestInvoice = $user->invoices()->latest()->first();

          if(!empty($latestInvoice) && $latestInvoice->plan_expire <= Carbon::now()){
              Invoice::create([
                  'user_id' => $user->id,
                  'type_id' => $useType->id,
                  'amount' => $useType->price,
                  'status' => 'Approved',
                  'plan_expire' => $expiredatetime->toDateTimeString(),
              ]);
              Mail::to($user->email)->send(new UserPlansReset($user));
          }
        }

Теперь эта функция вернет

Expected response code 220 but got an empty response

и не будет отправлять письма .

Ответы [ 2 ]

2 голосов
/ 18 апреля 2019

Изменение в модели счета, добавьте переменную plan_expire в $ date вместо $ castts:

protected $dates = ["plan_expire"];

Вы можете попробовать так:

$users = User::all();
foreach($users as $user){

  $latestInvoice = $user->invoices()->latest()->first();

  if($latestInvoice->plan_expire->isPast()){

       //create invoice and mailed it
  }
  //other steup

}

Для отправки по электронной почте вернуть пустую проблему ответа, Вы можете проверить этот вопрос нажмите здесь

0 голосов
/ 18 апреля 2019

Найти просроченные счета, сгруппировать по идентификатору пользователя и упорядочить по plan_expire и выбрать первую запись в каждой группе.

Версия сервера MySQL <8 не имеет оконных функций, которые могут упростить выполнение строкинумерация в соответствующих строках. </p>

Обходной путь - установить клиентские переменные, которые могут использоваться для нумерации счетов одним и тем же пользователем, начиная с 1 и выбирая только первые.


$now = Carbon::now();
$nowDS = $now->toDateTimeString();

$expired_invoices = "
SET @rownum := 0;
SET @userid := NULL;

SELECT *, uid as user_id, plan_expire 
FROM (
    SELECT 
        *,
        @rownum := CASE
            WHEN @userid = uid 
            THEN @rownum + 1
            ELSE 1
            END AS rn,
        @userid := user_id AS uid,
        num
    FROM invoices AS i
    WHERE plan_expire <= $nowDS
    ORDER BY user_id, plan_expire DESC
) AS num_invoices WHERE rn = 1;
"

$invoices = DB::select($expired_invoices);

Теперь,$invoices можно повторить и отправить его владельцу.

$expiredatetime = $now->addDays(30);
$useType = Type::where('name', 'Free')->first();
$users = User::all();


foreach ($invoices as $invoice)
{
    Invoice::create([
        'user_id' => $invoice->user_id,
        'type_id' => $useType->id,
        'amount' => $useType->price,
        'status' => 'Approved',
        'plan_expire' => $expiredatetime,
    ]);

    $user = $users->find(['id' => $invoice->user_id]);
    Mail::to($user->email)->send(new UserPlansReset($user));
}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...