
Originally Posted by
jeking
I did a search but came up empty. Is there a way to report sales that includes the attribute? My client, a non-profit fog rescue, sells t-shirts and tracks inventory by size. The plugin is great for the site, but they need a report on sales to update inventory. The Sales Report plugin does not include attribute data.
I came up with a solution for this that involves only php changes and no database additions. I am reluctant to share it because it's queries are very intensive and a product with 100+ attributes can take several minutes to return results. For our business this data was essential, so it was worth the cost for us. I modified the stats_products_purchased.php file to add the following code:
PHP Code:
<!-- BOF FGB Attribute Sales Report -->
<table border="0" width="80%" cellspacing="0" cellpadding="2">
<tr>
<td><table border="0" width="80%" cellspacing="0" cellpadding="0">
<tr>
<td class="pageHeading"><?php echo "Best Attributes Purchased"; ?></td>
<td class="pageHeading" align="right"><?php echo zen_draw_separator('pixel_trans.gif', 1, HEADING_IMAGE_HEIGHT); ?></td>
<td class="smallText" align="right">
<?php
// field for user to enter two order numbers to search between
echo zen_draw_form('search', FILENAME_STATS_PRODUCTS_PURCHASED, '', 'get', '', true);
echo "Enter two order numbers seperated by a comma:" . ' ' . zen_draw_input_field('order_numbers') . zen_hide_session_id();
echo '<br/ >' . "Enter one product ID number:". ' ' . zen_draw_input_field('product_id') . zen_hide_session_id();
?><input type="submit"><?php
echo '</form>';
?>
</td>
</tr>
</table></td>
</tr>
<?php
echo $_GET["order_numbers"]; ?><br><?php
echo $_GET["product_id"]; ?><br><?php
// create orders_id_array to hold all orders_products_id arrays
$orders_id_array = array();
$our_product_number = 7;
$our_beginning_order_number = 20500;
$our_ending_order_number = 30000;
// if the user has entered and submitted some order numbers, use those
if (!(is_null($_GET["order_numbers"]))) {
$order_numbers = explode(",", $_GET["order_numbers"]);
$our_beginning_order_number = $order_numbers[0];
$our_ending_order_number = $order_numbers[1];
}
// if the user has entered and submitted an item number, use that
if (!(is_null($_GET["product_id"]))) {
$our_product_number = $_GET["product_id"];
}
// building query from orders_products table for product quantity, id, name, and orders_products_id
// need to add user input fields for order range and product id
$attributes_query_raw=
"select op.products_quantity, op.orders_products_id, op.products_name, op.products_id
from ".TABLE_ORDERS_PRODUCTS." op
where (op.orders_id BETWEEN $our_beginning_order_number AND $our_ending_order_number) AND op.products_id = $our_product_number";
// fire off this query
$attributes = $db->Execute($attributes_query_raw);
// loop though all returned records
while(!$attributes->EOF) {
// create orders_products_id_array to hold the fields for each purchase
$orders_products_id_array = array();
// push these onto our orders_id array
array_push($orders_products_id_array, $attributes->fields['products_id'],
$attributes->fields['orders_products_id'],
$attributes->fields['products_quantity'],
$attributes->fields['products_name']);
// grab orders_products_id to use when filtering variants query
$var_opi = $attributes->fields['orders_products_id'];
// building query from orders_products_attributes table for product options values and orders_products_id
$variants_query_raw=
"select products_options_values, orders_products_id
from " . TABLE_ORDERS_PRODUCTS_ATTRIBUTES . "
where orders_products_id=$var_opi";
// fire off this query
$variants = $db->Execute($variants_query_raw);
// loop though all returned records
while(!$variants->EOF) {
// push this attribute to the end of our orders_id array
$orders_products_id_array[] = $variants->fields['products_options_values'];
// move on to the next attribute option value if there is one
$variants->MoveNext();
} // while loop completed; orders_products_id array completed
// push this completed orders_products_id array onto the larger products_id array
$orders_id_array[] = $orders_products_id_array;
// move on to the next orders_products_id if there is one
$attributes->MoveNext();
} // while loop completed; orders_id array completed
// funtion to sort on the first attribute (e.g. tip size)
function cmp_first_attribute($a, $b) {
if ($a[4] == $b[4]) {
return strcmp($a[5], $b[5]);
}
return strcmp($a[4], $b[4]);
}
// function to sort on the second attribute (e.g. color)
function cmp_second_attribute($a, $b) {
return strcmp($a[5], $b[5]);
}
// function to sort on the quantity
function cmp_quantity($a, $b) {
if ($a[2] == $b[2]) {
return 0;
}
return ($a[2] > $b[2]) ? -1 : 1;
}
// sort the orders_id array so that all the matching products are adjacent
usort($orders_id_array, "cmp_first_attribute");
// we should check if this index exists before sorting, this might break on single attribute products
//usort($orders_id_array, "cmp_second_attribute");
// create new array to hold summed quantitys of attributes purchased
$summed_quantities = array();
// create tokens to hold our summed array index and product attribute options while traversing orders_id array
$summed_quantities_index = -1;
$product_name_token = array(4=>'',5=>'');
// create loop that pulls each unique combination of attributes out of orders_id array` and summs their quantities
foreach ($orders_id_array as $orders_id_line) {
// if we are starting on a new set of attribtues, set the name token and incriment the summed array index
if (($orders_id_line[4] != $product_name_token[4]) || ($orders_id_line[5] != $product_name_token[5])) {
$product_name_token[4] = $orders_id_line[4];
$product_name_token[5] = $orders_id_line[5];
$summed_quantities_index++;
// since we are on a new set of attributes, populate the next array in summmed_quantities with
// our new info, and set quantity to zero
$summed_quantities[$summed_quantities_index] = $orders_id_line;
$summed_quantities[$summed_quantities_index][2] = 0;
}
// if this is another instance of the same set of attributes wer were already working with,
// add the quanitity of this new instance to our running total
$summed_quantities[$summed_quantities_index][2] = $summed_quantities[$summed_quantities_index][2] + $orders_id_line[2];
}
// sort our summed list in descending order by quantity
usort($summed_quantities, "cmp_quantity");
// build table header row for Best Attributes Table
?>
<tr>
<td><table border="0" width="80%" cellspacing="0" cellpadding="0">
<tr>
<td valign="top"><table border="0" width="80%" cellspacing="0" cellpadding="2">
<tr class="dataTableHeadingRow">
<td class="dataTableHeadingContent"><?php echo "Product Name"; ?></td>
<td class="dataTableHeadingContent"><?php echo "Attribute"; ?></td>
<td class="dataTableHeadingContent"><?php echo "Attribute"; ?></td>
<td class="dataTableHeadingContent"><?php echo "Quantity"; ?></td>
</tr>
<?php
if (isset($_GET['page']) && ($_GET['page'] > 1)) $rows = $_GET['page'] * MAX_DISPLAY_SEARCH_RESULTS_REPORTS - MAX_DISPLAY_SEARCH_RESULTS_REPORTS;
$rows = 0;
foreach ($summed_quantities as $summed_quantity) {
$rows++;
if (strlen($rows) < 2) {
$rows = '0' . $rows;
}?>
<tr class="dataTableRow" onmouseover="rowOverEffect(this)" onmouseout="rowOutEffect(this)">
<td class="dataTableContent"><?php echo $summed_quantity[3]; ?> </td>
<td class="dataTableContent"><?php echo $summed_quantity[4]; ?></td>
<td class="dataTableContent"><?php echo $summed_quantity[5]; ?></td>
<td class="dataTableContent"><?php echo $summed_quantity[2]; ?></td>
</tr><?php
}
?>
</table></td>
</tr>
<tr>
<td colspan="3"><table border="0" width="80%" cellspacing="0" cellpadding="2">
<tr>
</tr>
</table></td>
</tr>
</table></td>
</tr>
</table></td>
<!-- EOF FGB Attribute Sales Report -->
I hope this helps.
Bookmarks