// Updated OrderHistory / StockManager. Added feature to StockCover: it is now possible to display the number of sales per product / and highlight products which coverage is less than a given threshold

This commit is contained in:
bMancone
2011-12-13 09:48:52 +00:00
parent 133de02a11
commit 4180588c40
7 changed files with 132 additions and 36 deletions

View File

@@ -222,7 +222,7 @@ form#product_form h4 { font-size:18px; font-weight:normal;}
.filter-module .button-filter { float:right;}
/*FILTER STOCK*/
.filter-stock { background-color:#ebedf4; border:1px solid #c2c4d9; margin-bottom:15px; padding:10px; display:block; min-height:25px;}
.filter-stock { background-color:#ebedf4; border:1px solid #c2c4d9; margin-bottom:15px; padding:10px; display:block; min-height:65px;}
.filter-stock #stock_cover {float:left; margin-right:30px;}
.filter-stock #stock_instant_state {float:left; margin-right:30px;}
.filter-stock #supply_orders {float:left; margin-right:30px;}

View File

@@ -55,6 +55,10 @@ $(document).ready(function() {
.attr('colspan', $('#details_{$id}').parent().parent().find('td').length)));
$.each(data.data, function(it, row)
{
var bg_color = ''; // Color
if (row.color)
bg_color = 'style="background:' + row.color +';"';
var content = $('<tr class="action_details details_{$id} '+(alt_row ? 'alt_row' : '')+'"></tr>');
content.append($('<td class="empty"></td>'));
var first = true;
@@ -69,9 +73,9 @@ $(document).ready(function() {
if (typeof(row[it]) == 'undefined')
{
if (first || count == 0)
content.append($('<td class="'+this.align+' empty"></td>'));
content.append($('<td class="'+this.align+' empty"' + bg_color + '></td>'));
else
content.append($('<td class="'+this.align+'"></td>'));
content.append($('<td class="'+this.align+'"' + bg_color + '></td>'));
}
else
{
@@ -79,12 +83,12 @@ $(document).ready(function() {
if (first)
{
first = false;
content.append($('<td class="'+this.align+' first">'+row[it]+'</td>'));
content.append($('<td class="'+this.align+' first"' + bg_color + '>'+row[it]+'</td>'));
}
else if (count == 0)
content.append($('<td class="'+this.align+' last">'+row[it]+'</td>'));
content.append($('<td class="'+this.align+' last"' + bg_color + '>'+row[it]+'</td>'));
else
content.append($('<td class="'+this.align+' '+count+'">'+row[it]+'</td>'));
content.append($('<td class="'+this.align+' '+count+'"' + bg_color + '>'+row[it]+'</td>'));
}
});
content.append($('<td class="empty"></td>'));

View File

@@ -30,20 +30,31 @@
<input type="hidden" name="controller" value="AdminStockCover" />
<input type="hidden" name="token" value="{$token}" />
{if count($stock_cover_periods) > 1}
<label for="coverage_period">{l s='Filter by period/warehouse:'}</label>
<select name="coverage_period" onChange="$(this).parent().submit();">
<div>
<label for="coverage_period">{l s='Filter by period:'}</label>
<select name="coverage_period" onChange="$(this).parent().parent().submit();">
{foreach from=$stock_cover_periods key=k item=i}
<option {if $i == $stock_cover_cur_period} selected="selected"{/if} value="{$i}">{$k}</option>
{/foreach}
</select>
</div>
{/if}
{if count($stock_cover_warehouses) > 0}
<select name="id_warehouse" onChange="$(this).parent().submit();">
<div>
<label for="id_warehouse">{l s='Filter by warehouse:'}</label>
<select name="id_warehouse" onChange="$(this).parent().parent().submit();"">
{foreach from=$stock_cover_warehouses key=k item=i}
<option {if $i.id_warehouse == $stock_cover_cur_warehouse} selected="selected"{/if} value="{$i.id_warehouse}">{$i.name}</option>
{/foreach}
</select>
</div>
{/if}
<div>
<label for="warn_days">{l s='Highlight when coverage is less than:'}</label>
<input name="warn_days" type="text" size="3" onChange="$(this).parent().parent().submit();"
value="{if isset($stock_cover_warn_days)}{$stock_cover_warn_days}{/if}">
</input>
</div>
</form>
</div>
{/block}

View File

@@ -30,13 +30,18 @@
<form id="supply_orders" type="get">
<input type="hidden" name="controller" value="AdminSupplyOrders" />
<input type="hidden" name="token" value="{$token}" />
<label for="filter_status">{l s='Choose not to display completed/canceled orders and filter by warehouse:'}</label>
<input type="checkbox" name="filter_status" class="noborder" onChange="$(this).parent().submit();" {if $filter_status == 1}value="on" checked{/if}></input>
<select name="id_warehouse" onChange="$(this).parent().submit();">
<div>
<label for="id_warehouse">{l s='Filter by warehouse:'}</label>
<select name="id_warehouse" onChange="$(this).parent().parent().submit();">
{foreach from=$warehouses key=k item=i}
<option {if $i.id_warehouse == $current_warehouse} selected="selected"{/if} value="{$i.id_warehouse}">{$i.name}</option>
{/foreach}
</select>
</select>
</div>
<div style="margin-top: 5px;">
<label for="filter_status">{l s='Choose not to display completed/canceled orders:'}</label>
<input type="checkbox" name="filter_status" class="noborder" onChange="$(this).parent().parent().submit();" {if $filter_status == 1}value="on" checked{/if}></input>
</div>
</form>
</div>
{/if}

View File

@@ -127,6 +127,11 @@ class OrderHistoryCore extends ObjectModel
true,
(int)$id_order
);
if (StockAvailable::dependsOnStock($product['id_product'], $order->id_shop))
StockAvailable::synchronize($product['id_product']);
else
StockAvailable::updateQuantity($product['id_product'], $product['id_product_attribute'], -(int)$product['cart_quantity'], $order->id_shop);
}
else if ($newOS->shipped == 0 && $oldOrderStatus->shipped == 1 && Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT'))
{

View File

@@ -554,7 +554,7 @@ class StockManagerCore implements StockManagerInterface
/**
* @see StockManagerInterface::getProductCoverage()
* Here, $coverage is a number of days
* @return int number of days left
* @return int number of days left (-1 if infinite)
*/
public function getProductCoverage($id_product, $id_product_attribute, $coverage, $id_warehouse = null)
{
@@ -584,14 +584,14 @@ class StockManagerCore implements StockManagerInterface
$quantity_out = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query);
if (!$quantity_out)
return '--';
return -1;
$quantity_per_day = round($quantity_out / $coverage);
$quantity_per_day = Tools::ps_round($quantity_out / $coverage);
$physical_quantity = $this->getProductPhysicalQuantities($id_product,
$id_product_attribute,
($id_warehouse ? array($id_warehouse) : null),
true);
$time_left = ($quantity_per_day == 0) ? '--' : round($physical_quantity / $quantity_per_day);
$time_left = ($quantity_per_day == 0) ? (-1) : Tools::ps_round($physical_quantity / $quantity_per_day);
return $time_left;
}

View File

@@ -39,6 +39,7 @@ class AdminStockCoverControllerCore extends AdminController
$this->table = 'product';
$this->className = 'Product';
$this->lang = true;
$this->colorOnBackground = true;
$this->fieldsDisplay = array(
'reference' => array(
@@ -63,12 +64,19 @@ class AdminStockCoverControllerCore extends AdminController
'title' => $this->l('Name'),
'filter_key' => 'b!name'
),
'qty_sold' => array(
'title' => $this->l('Quantity sold'),
'width' => 160,
'orderby' => false,
'search' => false,
'hint' => $this->l('Quantity sold during the defined period.'),
),
'coverage' => array(
'title' => $this->l('Coverage'),
'width' => 160,
'orderby' => false,
'search' => false,
'hint' => $this->l('Days left before you run out of stock.')
'hint' => $this->l('Days left before you run out of stock.'),
),
'stock' => array(
'title' => $this->l('Quantity'),
@@ -135,11 +143,25 @@ class AdminStockCoverControllerCore extends AdminController
{
$data['name'] = Product::getProductName($data['id_product'], $data['id']);
if ($this->getCurrentCoverageWarehouse() == -1)
$data['coverage'] = StockManagerFactory::getManager()->getProductCoverage($data['id_product'], $data['id'], $period);
else
$data['coverage'] = StockManagerFactory::getManager()->getProductCoverage($data['id_product'], $data['id'], $period, $warehouse);
// computes coverage
$coverage = StockManagerFactory::getManager()->getProductCoverage(
$data['id_product'],
$data['id'],
$period,
(($this->getCurrentCoverageWarehouse() == -1) ? null : $warehouse)
);
if ($coverage != -1) // if coverage is available
{
if ($coverage < $this->getCurrentWarning()) // if highlight needed
$data['color'] = '#BDE5F8';
$data['coverage'] = $coverage;
}
else // infinity
$data['coverage'] = '--';
$data['qty_sold'] = $this->getQuantitySold($data['id_product'], $data['id'], $this->getCurrentCoveragePeriod());
}
echo Tools::jsonEncode(array('data'=> $datas, 'fields_display' => $this->fieldsDisplay));
}
die;
@@ -169,7 +191,12 @@ class AdminStockCoverControllerCore extends AdminController
$this->tpl_list_vars['stock_cover_cur_period'] = $this->getCurrentCoveragePeriod();
$this->tpl_list_vars['stock_cover_warehouses'] = $this->stock_cover_warehouses;
$this->tpl_list_vars['stock_cover_cur_warehouse'] = $this->getCurrentCoverageWarehouse();
$this->ajax_params = array('period' => $this->getCurrentCoveragePeriod(), 'id_warehouse' => $this->getCurrentCoverageWarehouse());
$this->tpl_list_vars['stock_cover_warn_days'] = $this->getCurrentWarning();
$this->ajax_params = array(
'period' => $this->getCurrentCoveragePeriod(),
'id_warehouse' => $this->getCurrentCoverageWarehouse(),
'warn_days' => $this->getCurrentWarning()
);
$this->displayInformation($this->l('Considering the coverage period choosen and the quantity of products/combinations that you sold,
this interface gives you an idea of when one product will run out of stock.'));
@@ -191,22 +218,30 @@ class AdminStockCoverControllerCore extends AdminController
$item = &$this->_list[$i];
if ((int)$item['variations'] <= 0)
{
if ($this->getCurrentCoverageWarehouse() == -1) // if all warehouses
$item['coverage'] = StockManagerFactory::getManager()->getProductCoverage(
$item['id'],
0,
$this->getCurrentCoveragePeriod()
);
else // else selected warehouse
$item['coverage'] = StockManagerFactory::getManager()->getProductCoverage(
$item['id'],
0,
$this->getCurrentCoveragePeriod(),
$this->getCurrentCoverageWarehouse()
);
// computes coverage and displays (highlights if needed)
$coverage = StockManagerFactory::getManager()->getProductCoverage(
$item['id'],
0,
$this->getCurrentCoveragePeriod(),
(($this->getCurrentCoverageWarehouse() == -1) ? null : $this->getCurrentCoverageWarehouse())
);
if ($coverage != -1) // coverage is available
{
if ($coverage < $this->getCurrentWarning())
$item['color'] = '#BDE5F8';
$item['coverage'] = $coverage;
}
else // infinity
$item['coverage'] = '--';
// computes quantity sold
$item['qty_sold'] = $this->getQuantitySold($item['id'], 0, $this->getCurrentCoveragePeriod());
// removes 'details' action on products without attributes
$this->addRowActionSkipList('details', array($item['id']));
}
else
{
@@ -253,4 +288,40 @@ class AdminStockCoverControllerCore extends AdminController
}
return $warehouse;
}
/**
* Gets the current warning
*
* @return int warn period
*/
private function getCurrentWarning()
{
static $warning = 0;
if ($warning == 0)
{
$warning = 0;
if (Tools::getValue('warn_days') && Validate::isInt(Tools::getValue('warn_days')))
$warning = (int)Tools::getValue('warn_days');
}
return $warning;
}
protected function getQuantitySold($id_product, $id_product_attribute, $coverage)
{
$query = new DbQuery();
$query->select('SUM(od.product_quantity)');
$query->from('order_detail od');
$query->leftJoin('orders o ON (od.id_order = o.id_order)');
$query->leftJoin('order_history oh ON (o.date_upd = oh.date_add)');
$query->leftJoin('order_state os ON (os.id_order_state = oh.id_order_state)');
$query->where('od.product_id = '.(int)$id_product);
$query->where('od.product_attribute_id = '.(int)$id_product_attribute);
$query->where('TO_DAYS(NOW()) - TO_DAYS(oh.date_add) <= '.(int)$coverage);
$query->where('o.valid = 1');
$query->where('os.logable = 1 AND os.delivery = 1 AND os.shipped = 1');
$quantity = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query);
return $quantity;
}
}