Laravel: как получить все заказы клиентов, назначенных определенному агенту

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

Agents (Users)
  id
  name
  email
  password
  created_at
  updated_at

Customers
  id
  agent_id
  firstname
  lastname
  email
  created_at
  updated_at

Orders
  id
  customer_id
  product_id
  amount

Customer_Tags
  id
  customer_id
  name

Products
  id
  name

Мне нужно написать оператор SQL, который получает все заказы клиентов, которые назначены текущему вошедшему в систему пользователю (по agent_id) и имеют этот тег (ID: 234), но не любой из этих тегов [3343, 445, 333] и имеет купил любой из этих товаров (ID: 18, 33, 29).

Просто чтобы вы понимали, что делают теги. Клиенты помечаются на основе действий, которые они предпринимают. Это делается в маркетинговых целях. Если клиент покупает продукт, к этому покупателю прикрепляется специальный тег. Если они продолжают совершать другие действия, например, смотреть вебинар, к ним прикрепляется еще один тег, и так далее и тому подобное.

Приложение построено на фреймворке Laravel. Я попытался использовать встроенный Eloquent ORM.

return Order::with('customer')
    ->whereHas('customer', function (Builder $query) {
        $query->where('agent_id', Auth::id());
      })
      ->whereHas('customer.tags', function (Builder $query) {
        $query->whereIn('id', [234])
          ->whereNotIn('id', [3343, 445, 333]);
        })
        ->whereHas('product', function (Builder $query) {
            $query->whereIn('id', [18, 33, 29]);
          })
          ->get();

Он работает, вытягивая заказы всех клиентов с идентификатором тега 234. Однако он также включает заказы клиентов, имеющих любой из этих тегов (3343, 445, 333), что противоположно тому, что я хочу.

Я также попытался использовать встроенный конструктор запросов и получил те же результаты.

return DB::table('orders')
        ->join('customers', 'orders.custom_id', '=', 'customers.id')
          ->join('customer_tags', function ($join) {
              $join->on('customers.id', '=', 'customer_tags.customer_id')
                ->whereIn('customer_tags.id', [234])
                  ->whereNotIn('customer_tags.id', [3343, 445, 333]);
              })
              ->join('products', 'products.id', '=', 'orders.product_id')
                ->whereIn('orders.product_id', [18, 33, 29])
                  ->where('customers.agent_id', Auth::id())
                    ->select('orders.invoice_at', 'customers.*', 'products.name')
                      ->get();

Пожалуйста помоги. Прямо сейчас, я просто открыт для чего угодно. Будь то Eloquent ORM, Query Builder или просто четкий оператор SQL.


person lotsonj    schedule 11.12.2019    source источник


Ответы (1)


Разве вы не можете просто добавить предложение tags в запрос customer и использовать где не имеет?

Order::with('customer')
    ->whereHas('customer', function ($query) {
        $query
            ->where('agent_id', Auth::id())
            ->whereHas('tags', function ($query) {
                $query->whereIn('id', [234]);
            })
            ->whereDoesntHave('tags', function ($query) {
                $query->whereIn('id', [3343, 445, 333]);
            });
    })
    ->whereHas('product', function ($query) {
        $query->whereIn('id', [18, 33, 29]);
    });

Кроме того, вы можете использовать ->toSql(), чтобы увидеть окончательный SQL-запрос, чтобы убедиться, что он вам нужен.

person Chin Leung    schedule 11.12.2019
comment
ты гений. Ты просто решаешь проблему, которую я корил себя несколько дней. Я даже разместил его на форуме Laracast, и никто там не смог помочь. Спасибо, мой друг. Как включить клиентов без тегов? - person lotsonj; 12.12.2019
comment
@lotsonj Нет проблем. Вы можете просто добавить orDoesntHave('tags') к запросу клиента. - person Chin Leung; 12.12.2019