You are here

public function Reports::products in Ubercart 8.4

Displays the product reports.

1 string reference to 'Reports::products'
uc_report.routing.yml in uc_report/uc_report.routing.yml
uc_report/uc_report.routing.yml

File

uc_report/src/Controller/Reports.php, line 159

Class

Reports
Provides reports for Ubercart.

Namespace

Drupal\uc_report\Controller

Code

public function products() {
  $views_column = $this
    ->moduleHandler()
    ->moduleExists('statistics') && $this
    ->config('statistics.settings')
    ->get('count_content_views');
  $page = isset($_GET['page']) ? intval($_GET['page']) : 0;
  $page_size = isset($_GET['nopage']) ? UC_REPORT_MAX_RECORDS : $this
    ->config('uc_report.settings')
    ->get('table_size');
  $order_statuses = uc_report_order_statuses();
  $row_cell = $page * $this
    ->config('uc_report.settings')
    ->get('table_size') + 1;
  $rows = [];
  $csv_rows = [];

  // Hard code the ignore of the product kit for this report.
  $ignored_types = [
    'product_kit',
  ];

  // Build an array of valid product types to include on the report.
  $product_types = [];
  foreach (uc_product_types() as $type) {

    // Pass over any ignored types.
    if (!in_array($type, $ignored_types)) {
      $product_types[] = $type;
    }
  }
  $query = $this->database
    ->select('node_field_data', 'n', [
    'fetch' => \PDO::FETCH_ASSOC,
  ])
    ->extend('Drupal\\Core\\Database\\Query\\PagerSelectExtender')
    ->extend('Drupal\\Core\\Database\\Query\\TableSortExtender')
    ->limit($page_size);
  $query
    ->addField('n', 'nid');
  $query
    ->addField('n', 'title');
  $query
    ->addExpression("(SELECT SUM(uop.qty) FROM {uc_order_products} uop LEFT JOIN {uc_orders} uo ON uop.order_id = uo.order_id WHERE uo.order_status IN (:statuses[]) AND uop.nid = n.nid)", 'sold', [
    ':statuses[]' => $order_statuses,
  ]);
  $query
    ->addExpression("(SELECT (SUM(uop.price * uop.qty) - SUM(uop.cost * uop.qty)) FROM {uc_order_products} uop LEFT JOIN {uc_orders} uo ON uop.order_id = uo.order_id WHERE uo.order_status IN (:statuses2[]) AND uop.nid = n.nid)", 'gross', [
    ':statuses2[]' => $order_statuses,
  ]);
  $query
    ->addExpression("(SELECT (SUM(uop.price * uop.qty)) FROM {uc_order_products} uop LEFT JOIN {uc_orders} uo ON uop.order_id = uo.order_id WHERE uo.order_status IN (:statuses3[]) AND uop.nid = n.nid)", 'revenue', [
    ':statuses3[]' => $order_statuses,
  ]);
  $header = [
    [
      'data' => $this
        ->t('#'),
    ],
    [
      'data' => $this
        ->t('Product'),
      'field' => 'n.title',
    ],
    [
      'data' => $this
        ->t('Sold'),
      'field' => 'sold',
    ],
    [
      'data' => $this
        ->t('Revenue'),
      'field' => 'revenue',
      'sort' => 'desc',
    ],
    [
      'data' => $this
        ->t('Gross'),
      'field' => 'gross',
    ],
  ];
  $csv_rows[] = [
    $this
      ->t('#'),
    $this
      ->t('Product'),
    $this
      ->t('Sold'),
    $this
      ->t('Revenue'),
    $this
      ->t('Gross'),
  ];
  if ($views_column) {
    $header[] = [
      'data' => $this
        ->t('Views'),
      'field' => 'nc.totalcount',
    ];
    $csv_rows[0][] = $this
      ->t('Views');
  }
  $query
    ->orderByHeader($header);
  if ($views_column) {
    $query
      ->leftJoin('node_counter', 'nc', 'n.nid = nc.nid');
    $query
      ->addField('nc', 'totalcount');
  }
  $query
    ->condition('n.type', $product_types, 'IN')
    ->groupBy('n.nid')
    ->groupBy('n.title');
  $products = $query
    ->execute();
  foreach ($products as $product) {
    $product_cell = Link::createFromRoute($product['title'], 'entity.node.canonical', [
      'node' => $product['nid'],
    ])
      ->toString();
    $product_csv = $product['title'];
    $sold_cell = empty($product['sold']) ? 0 : $product['sold'];
    $sold_csv = $sold_cell;
    $revenue_csv = empty($product['revenue']) ? 0 : $product['revenue'];
    $revenue_cell = uc_currency_format($revenue_csv);
    $gross_csv = empty($product['gross']) ? 0 : $product['gross'];
    $gross_cell = uc_currency_format($gross_csv);
    $row = [
      'data' => [
        $row_cell,
        $product_cell,
        [
          'data' => [
            '#prefix' => '<strong>',
            '#markup' => $sold_cell,
            '#suffix' => '</strong>',
          ],
        ],
        [
          'data' => [
            '#prefix' => '<strong>',
            '#markup' => $revenue_cell,
            '#suffix' => '</strong>',
          ],
        ],
        [
          'data' => [
            '#prefix' => '<strong>',
            '#markup' => $gross_cell,
            '#suffix' => '</strong>',
          ],
        ],
      ],
      'primary' => TRUE,
    ];
    $csv_row = [
      $row_cell,
      $product_csv,
      $sold_csv,
      $revenue_csv,
      $gross_csv,
    ];
    if ($views_column) {
      $views = isset($product['totalcount']) ? $product['totalcount'] : 0;
      $row['data'][] = $views;
      $csv_row[] = $views;
    }
    $rows[] = $row;
    $csv_rows[] = $csv_row;
    if ($this
      ->moduleHandler()
      ->moduleExists('uc_attribute')) {

      // Get the SKUs from this product.
      $models = $this
        ->product_get_skus($product['nid']);

      // Add the product breakdown rows.
      foreach ($models as $model) {
        $sold = $this->database
          ->query("SELECT SUM(qty) FROM {uc_order_products} p LEFT JOIN {uc_orders} o ON p.order_id = o.order_id WHERE o.order_status IN (:statuses[]) AND p.model = :model AND p.nid = :nid", [
          ':statuses[]' => $order_statuses,
          ':model' => $model,
          ':nid' => $product['nid'],
        ])
          ->fetchField();
        $revenue = $this->database
          ->query("SELECT SUM(p.price * p.qty) FROM {uc_order_products} p LEFT JOIN {uc_orders} o ON p.order_id = o.order_id WHERE o.order_status IN (:statuses[]) AND p.model = :model AND p.nid = :nid", [
          ':statuses[]' => $order_statuses,
          ':model' => $model,
          ':nid' => $product['nid'],
        ])
          ->fetchField();
        $gross = $this->database
          ->query("SELECT (SUM(p.price * p.qty) - SUM(p.cost * p.qty)) FROM {uc_order_products} p LEFT JOIN {uc_orders} o ON p.order_id = o.order_id WHERE o.order_status IN (:statuses[]) AND p.model = :model AND p.nid = :nid", [
          ':statuses[]' => $order_statuses,
          ':model' => $model,
          ':nid' => $product['nid'],
        ])
          ->fetchField();
        $breakdown_product = [
          '#markup' => "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{$model}",
        ];
        $product_csv = "     {$model}";
        $sold_csv = !empty($sold) ? $sold : 0;
        $breakdown_sold = $sold_csv;
        $revenue_csv = !empty($revenue) ? $revenue : 0;
        $breakdown_revenue = [
          '#theme' => 'uc_price',
          '#price' => $revenue_csv,
        ];
        $gross_csv = !empty($gross) ? $gross : 0;
        $breakdown_gross = [
          '#theme' => 'uc_price',
          '#price' => $gross_csv,
        ];
        $row = [
          'data' => [
            '',
            [
              'data' => $breakdown_product,
            ],
            $breakdown_sold,
            [
              'data' => $breakdown_revenue,
            ],
            [
              'data' => $breakdown_gross,
            ],
          ],
        ];
        $csv_row = [
          '',
          $product_csv,
          $sold_csv,
          $revenue_csv,
          $gross_csv,
        ];
        if ($views_column) {
          $row['data'][] = '';
          $csv_row[] = '';
        }
        $rows[] = $row;
        $csv_rows[] = $csv_row;
      }
    }
    $row_cell++;
  }
  $csv_data = $this
    ->store_csv('uc_products', $csv_rows);
  $build['report'] = [
    // theme_uc_report_product_table stripes the rows differently than theme_table.
    // We want all of a product's SKUs to show up in separate rows, but they should all
    // be adjacent and grouped with each other visually by using the same striping for
    // each product SKU (all odd or all even).
    // '#theme' => 'uc_report_product_table',
    '#theme' => 'table',
    '#header' => $header,
    '#rows' => $rows,
    '#attributes' => [
      'width' => '100%',
      'class' => [
        'uc-sales-table',
      ],
    ],
    '#empty' => $this
      ->t('No products found'),
  ];
  $build['pager'] = [
    '#type' => 'pager',
  ];
  $build['links'] = [
    '#prefix' => '<div class="uc-reports-links">',
    '#suffix' => '</div>',
  ];
  $build['links']['export_csv'] = [
    '#markup' => Link::createFromRoute($this
      ->t('Export to CSV file.'), 'uc_report.getcsv', [
      'report_id' => $csv_data['report'],
      'user_id' => $csv_data['user'],
    ])
      ->toString(),
    '#suffix' => '&nbsp;&nbsp;&nbsp;',
  ];
  if (isset($_GET['nopage'])) {
    $build['links']['toggle_pager'] = [
      '#markup' => Link::createFromRoute($this
        ->t('Show paged records'), 'uc_report.products')
        ->toString(),
    ];
  }
  else {
    $build['links']['toggle_pager'] = [
      '#markup' => Link::createFromRoute($this
        ->t('Show all records'), 'uc_report.products', [
        'query' => [
          'nopage' => '1',
        ],
      ])
        ->toString(),
    ];
  }
  $build['instructions'] = [
    '#markup' => '<small>*' . $this
      ->t('Make sure %setting_name is set to %state in the <a href=":url">access log settings page</a> to enable views column.', [
      '%setting_name' => 'count content views',
      '%state' => 'enabled',
      ':url' => Url::fromUri('base:admin/config/system/statistics', [
        'query' => [
          'destination' => 'admin/store/reports/products',
        ],
      ])
        ->toString(),
    ]) . '</small>',
  ];
  return $build;
}