You are here

function farm_livestock_weight_group_report in farmOS 7

Generate Animal Weight Group Report

2 calls to farm_livestock_weight_group_report()
farm_livestock_weight_group_report_csv in modules/farm/farm_livestock/farm_livestock_weight/farm_livestock_weight.module
Animal Weight Group Report CSV Export
farm_livestock_weight_group_report_form_submit in modules/farm/farm_livestock/farm_livestock_weight/farm_livestock_weight.module
Submit handler for the weight report form

File

modules/farm/farm_livestock/farm_livestock_weight/farm_livestock_weight.module, line 453
Farm livestock weight module.

Code

function farm_livestock_weight_group_report(&$form_state) {

  // Get the submitted group IDs to include in the report.
  $group_ids = $form_state['values']['group'];

  // Check if we should include archived assets.
  $include_archived = (bool) $form_state['values']['archived'];
  $only_archived = $form_state['values']['archived'] == 1;

  // Get list of flags to filter by.
  $flags = $form_state['values']['flags'];

  // Get date of birth filters.
  $earliest_birth = strtotime($form_state['values']['earliest_birth']);
  $latest_birth = strtotime($form_state['values']['latest_birth']);

  // Get the start and end dates.
  $start_date = strtotime($form_state['values']['start_date']);
  $end_date = strtotime($form_state['values']['end_date']);

  // Array to store dates of animal weight logs for CSV export.
  $date_format = 'Y-m-d';
  $all_log_dates = array();

  // Array to store animals and log data
  $animals = array();

  // Loop through each group, its members, and all weight logs.
  foreach ($group_ids as $id) {

    // Load the farm group asset.
    $group = farm_asset_load($id);

    // Load the farm group members.
    $members = farm_group_members($group, REQUEST_TIME, TRUE, $include_archived);

    // Loop through members.
    foreach ($members as $asset) {

      // If member is not an animal, bail.
      if ($asset->type != 'animal') {
        continue;
      }

      // Skip non-archived assets if only displaying archived assets.
      if ($only_archived && !$asset->archived) {
        continue;
      }

      // Check if asset has required flags.
      if (!empty($flags)) {

        // Compare asset flags to required flags.
        $asset_flags = farm_flags_load($asset);
        $diff = array_diff($flags, $asset_flags);

        // Skip the asset if it doesn't have required flags.
        if (!empty($diff)) {
          continue;
        }
      }

      // Check if a birth date filter is specified.
      if ($earliest_birth || $latest_birth) {

        // Get the assets birth date.
        $birth_date = NULL;
        if (!empty($asset->field_farm_date[LANGUAGE_NONE][0]['value'])) {
          $birth_date = $asset->field_farm_date[LANGUAGE_NONE][0]['value'];
        }

        // Skip assets without a birth date.
        if (empty($birth_date)) {
          continue;
        }

        // Skip assets born before earliest birth date.
        if ($earliest_birth) {
          if ($birth_date < $earliest_birth) {
            continue;
          }
        }

        // Skip assets born after latest birth date.
        if ($latest_birth) {
          if ($birth_date > $latest_birth) {
            continue;
          }
        }
      }

      // Save the animal info
      $asset->group = $group;

      // Load the group member's weights
      $time = REQUEST_TIME;
      if (!empty($end_date)) {
        $time = $end_date;
      }
      $logs = farm_quantity_log_asset($asset, 'weight', NULL, $time, TRUE, 'farm_observation', FALSE);

      // Array to save log dates for this one animal.
      $log_dates = array();

      // Array to save data from animal logs.
      $all_log_data = array();

      // Loop through weight logs.
      foreach ($logs as $log) {

        // Get the date of the log from the timestamp.
        $log_date = date($date_format, $log->timestamp);

        // Check that the log timestamp fits the date parameters. Note that we
        // only need to check the start date bound, because end date is already
        // filtered by farm_quantity_log_asset().
        if ($log->timestamp < $start_date) {
          continue;
        }

        // Add the log date to the array if not already included.
        if (!in_array($log_date, $log_dates)) {
          $log_dates[] = $log_date;
        }
        else {
          continue;
        }

        // Extract quantity data from the log.
        $data = farm_quantity_log_data($log, 'weight');

        // Iterate through the data and return the first one with a value.
        foreach ($data as $quantity) {
          if (!empty($quantity['value'])) {
            $value = $quantity['value'];
            $units = $quantity['units'];

            // Add the log data to array of logs.
            $log_data = array();
            $log_data['date'] = $log_date;
            $log_data['value'] = $value;
            $log_data['units'] = $units;
            $all_log_data[] = $log_data;
          }
        }
      }

      // Merge animal's log dates with all_log_dates.
      $all_log_dates = array_unique(array_merge($all_log_dates, $log_dates));

      // Save all log data with the animal.
      $asset->all_log_data = $all_log_data;

      // Add animal data to array of all animals.
      $animals[] = $asset;
    }
  }

  // Sort all collected log_dates.
  sort($all_log_dates);

  // Create a header for CSV and HTML Table
  $header = array(
    t('Asset ID'),
    t('Asset Name'),
    t('Group'),
  );

  // Add columns for each date collected.
  foreach ($all_log_dates as $date) {
    $header[] = t('Date - ') . $date;
    $header[] = t('Weight');
    $header[] = t('Units');
  }

  // Add the CSV header.
  $csvdata = implode(',', $header) . PHP_EOL;

  // Initialize array for Date Averages
  $group_date_averages = array();
  foreach ($group_ids as $id) {
    $group_date_averages[$id] = array(
      'group' => farm_asset_load($id),
      'dates' => array(),
    );
  }
  foreach ($animals as $animal) {

    // Add a row of data.
    $row = array();
    $name_label = htmlspecialchars(entity_label('farm_asset', $animal));
    if ($animal->archived) {
      $date = strftime('%Y-%m-%d', $animal->archived);
      $name_label = $name_label . ' (' . t('archived') . ' ' . $date . ')';
    }
    $row[] = $animal->id;
    $row[] = $name_label;
    $row[] = htmlspecialchars(entity_label('farm_asset', $animal->group));

    // Save the logs.
    $logs = $animal->all_log_data;

    // Skip adding logs if the animal has no logs
    if (sizeof($logs) == 0) {

      // Add Animal info to results.
      $table_data[] = $row;
      $csvdata .= implode(',', $row) . PHP_EOL;
      continue;
    }

    // Sort the logs by date.
    usort($logs, "farm_livestock_weight_log_array_sort_date");

    // Save a counter for which log to compare.
    $curr_log_index = 0;

    // Save a counter for which column to compare.
    $curr_column_index = 0;

    // Walk through each column and add log data if log date == column date.
    // Note that each date requires 3 columns in the CSV file to display the
    // date, value and units of recorded log weights.
    while ($curr_log_index < sizeof($logs) && $curr_column_index < sizeof($all_log_dates)) {

      // Conert the dates to times for easier comparison.
      $column_time = strtotime($all_log_dates[$curr_column_index]);
      $log_time = strtotime($logs[$curr_log_index]['date']);

      // If the log_time is less than column_time, then there are multiple logs
      // on the same date for the animal. The first one has already been saved,
      // skip any additional logs with the same date.
      if ($column_time > $log_time) {
        $curr_log_index += 1;

        // Set empty values if the times don't match.
        // Move to next column
      }
      else {
        if ($column_time != $log_time) {
          $row[] = '';
          $row[] = '';
          $row[] = '';
          $curr_column_index += 1;
        }
        else {
          $log_date = $logs[$curr_log_index]['date'];
          $log_value = $logs[$curr_log_index]['value'];
          $log_units = $logs[$curr_log_index]['units'];

          // Save the log date, value and units if the times match.
          $row[] = $log_date;
          $row[] = $log_value;
          $row[] = $log_units;

          // For displaying graphs of average weights
          // Tally the weight of the animal in the All Log Dates array
          // Initialize the Group's average weight array for the log date.
          if (!isset($group_date_averages[$animal->group->id]['dates'][$log_date])) {
            $group_date_averages[$animal->group->id]['dates'][$log_date] = array(
              'units' => $log_units,
              'total_weight' => $log_value,
              'animal_count' => 1,
            );
          }
          else {
            $group_date_averages[$animal->group->id]['dates'][$log_date]['total_weight'] += $log_value;
            $group_date_averages[$animal->group->id]['dates'][$log_date]['animal_count'] += 1;
          }

          // Move to next column, and next log.
          $curr_column_index += 1;
          $curr_log_index += 1;
        }
      }
    }

    // Add row to HTML Table
    $table_data[] = $row;

    // Add to CSV string
    $csvdata .= implode(',', $row) . PHP_EOL;
  }
  $table = '<div class="alert alert-danger">' . t('No animal assets match the above criteria.') . '</div>';
  if (!empty($table_data)) {

    // Create HTML Table
    $table = theme('table', array(
      'header' => $header,
      'rows' => $table_data,
    ));
  }

  // Create the div to hold report graphs.
  $graph_markup = array();

  // Create a graph object to pass to JS.
  $graphs = array();

  // Create graphs for each group
  foreach ($group_date_averages as $group) {
    $group_name = $group['group']->name;

    // Sort the array by date
    ksort($group['dates']);
    $dates = array_keys($group['dates']);
    for ($i = 0; $i < count($group['dates']); $i++) {
      $date = $dates[$i];

      // Calculate average weight.
      $date_average = $group['dates'][$date]['total_weight'] / $group['dates'][$date]['animal_count'];
      $group['dates'][$date]['average_weight'] = $date_average;

      // Calculate Average Daily Gain after the first date.
      if ($i > 0) {
        $previous_date = $dates[$i - 1];
        $previous_average = $group['dates'][$previous_date]['average_weight'];

        // Calculate gain between the two dates.
        $gain = $date_average - $previous_average;

        // Calculate days elapsed.
        $dStart = new DateTime($previous_date);
        $dEnd = new DateTime($date);
        $days_elapsed = (int) $dStart
          ->diff($dEnd)
          ->format("%a");

        // Save the daily gain value within the 'date' array.
        $group['dates'][$date]['gain'] = $gain / $days_elapsed;
      }
    }

    // Create Average Weight Graph
    $graph = array(
      'name' => t('Average Weight - ') . $group_name,
      'id' => 'farm-livestock-average-weight-' . $group_name . '-graph',
      'data' => $group['dates'],
    );
    $graphs[] = $graph;
    $graph_markup[] = '<div id="farm-livestock-average-weight-' . $group_name . '-graph" class="farm-report-graph"></div>';
  }
  $graph_settings = array(
    'farm_livestock_report' => array(
      'graphs' => $graphs,
    ),
  );
  return array(
    'graph-settings' => $graph_settings,
    'graph-markup' => $graph_markup,
    'table' => $table,
    'csv' => $csvdata,
  );
}