magento|mageworx_advanced_product_options实现简单产品单个custom option负库存销售
以下内容只针对,magento1.9.2.4,简单产品,mageworx_advanced_product_options插件以及产品详情页使用。
mageworx_advanced_product_options是一款针对magento简单产品不同custom option开发的插件,支持针对custom option定义颜色图片,库存数量,重量等等。而应用在我们的系统里面主要的需求分为几个:
1、精确到单一色块的库存控制和显示,后台统计,前台根据每一个属性的库存动态显示对应的提示和库存效果;
2、精确控制每个色块的负库存,根据色块的库存情况动态允许是否可以购买,并支持负库存销售;
那么根据需求可以整理为两个,一就是允许负库存销售,二就是需要在色块上面加开关,动态控制是否预售,是否允许负库存购买;最终效果展现如下:
先说第一个负库存销售的问题,一开始经测试发现,后台在产品编辑里面的custom option里面编辑qty,可以设置为负数,保存之后数据库里面存储的值为负数,但界面上显示的为0,那么就考虑是程序输出的时候进行了处理还是js进行了处理。还有负库存的问题,前期规划准备就是把默认的简单产品的库存设置为较大值,这样把系统默认的库存校验在加购的时候去掉,然后把插件里面对库存数量的校验修改,这样就能够完全实现。结果经过代码分析,一大堆的监听事件发现很不好修改,牵扯的校验地方有好几个。最后经过一天的摸索,发现里面存在一个$backorders==2,最终和后台配置里面对应上,转了一圈发现后台配置直接可以控制是否允许负库存销售,也就是原生的避过负库存的校验。相关文件罗列如下:
app\code\community\MageWorx\CustomOptions\etc\config.xml中109行到206定义不同事件的监听对象
app\code\community\MageWorx\CustomOptions\Model\Observer.php监听事件处理
app\code\community\MageWorx\CustomOptions\Model\Observer\Stock.php监听事件处理
最后形成的后台设置:
另外再说一下,上图中配置里面有个low stock value值,只能输入正整数,这个控制的地方在app\code\community\MageWorx\CustomOptions\etc\system.xml中定义字段值的位置,第247行,把下图中的validate验证注释掉即可使用负数。默认值是0,也可以在这个配置里面更改。
<low_stock_value translate="label">
<label>Low Stock Value</label>
<frontend_type>text</frontend_type>
<sort_order>192</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
<!-- <validate>validate-digits validate-not-negative-number</validate>-->
<depends><inventory_enabled>1</inventory_enabled></depends>
</low_stock_value>
接着再处理编辑option时候的显示问题,因为重用了一个cost和weight分别做开关,但是这两个显示的是0.000,需要处理,而且qty显示不了负数,这个经过查找发现是在php输出的时候进行了处理,具体位置如下:
E:\WWW\glass\app\code\community\MageWorx\CustomOptions\Block\Adminhtml\Options\Edit\Tab\Options\Option.php
E:\WWW\glass\app\code\community\MageWorx\CustomOptions\Block\Adminhtml\Catalog\Product\Edit\Tab\Options\Option.php
getOptionValues()方法中的'customoptions_qty' => $helper->removeQtyZeroes($customoptionsQty),更改为'customoptions_qty' => floor($customoptionsQty),这样就能数据库里面存储的值直接显示出来。
最后汇集到前端展示,上代码,大体来讲就是在详情页读取每个option对应的属性值,然后根据选择的option切换,对应的切换显示效果,下面的代码同样包含了,详情页根据选中效果动态切换sku,左侧的轮播图,属性名字等功能。
<?php
$id=$this->getProduct()->getId();
$product=Mage::getModel('catalog/product')->load($id);
$sku='';
$i=0;
foreach ($product->getOptions() as $o) {
$values = $o->getValues();
foreach ($values as $v) {
$data=$v->getData();
//dump($data);
$qty=intval($data['customoptions_qty']);
$sku=$product->getSku().'-'.$data['sku'];
$is_sale=intval($data['weight']);
$cost=intval($data['cost']);
$title=replace_color($data['default_title']);
echo "<input type='hidden' id='product_"."$id"."_".$title."' value='".$sku."'/>";
echo "<input type='hidden' id='product_qty_"."$id"."_".$title."' value='".$qty."'/>";
echo "<input type='hidden' id='product_sale_"."$id"."_".$title."' value='".$is_sale."'/>";
echo "<input type='hidden' id='product_cost_"."$id"."_".$title."' value='".$cost."'/>";
}
$i++;
}
$p_price=Magento\Product::formatPrice($product);
if($p_price['price']!=$p_price['final_price']){
echo "<input type='hidden' id='is_dazhe' value='1'/>";
}else{
echo "<input type='hidden' id='is_dazhe' value='0'/>";
}
?>
<script type="text/javascript">
jQuery(function() {
//alert(prodcut_medias_json);
var json=eval(prodcut_medias_json);
jQuery('#product-options-wrapper .swatches-container img').click(function () {
var img_str = '';
var img_main = '';
var pid='<?php echo $id ?>';
var temp_span = jQuery(this).attr('title').replace(/(^\s*)|(\s*$)/g, "");
//console.log(temp_span);
jQuery(".color_change_detail").html(temp_span);
if(pid && temp_span){
var new_span=temp_span.replace("/","-").replace(" ","-");
var sku=jQuery("#product_"+pid+"_"+new_span).val();
var qty=jQuery("#product_qty_"+pid+"_"+new_span).val();
var sale=jQuery("#product_sale_"+pid+"_"+new_span).val();
var cost=jQuery("#product_cost_"+pid+"_"+new_span).val();
var is_dazhe=jQuery("#is_dazhe").val();
console.log(qty,sale,is_dazhe);
jQuery(".instock").hide();
if(cost>0){
jQuery(".yushou_day").html(cost);
}
if(qty<=0){
jQuery(".outofstock").show();
if(sale>0){
//jQuery(".outofstock").hide();
jQuery(".yushou").show();
jQuery(".btn_lens").removeClass("none");
jQuery(".btn_only").removeClass("none");
jQuery(".btn_lens").removeAttr("disabled");
jQuery(".btn_only").removeAttr("disabled");
}else{
// jQuery(".outofstock").show();
jQuery(".yushou").hide();
jQuery(".btn_lens").addClass("none");
jQuery(".btn_only").addClass("none");
jQuery(".btn_lens").attr("disabled","disabled");
jQuery(".btn_only").attr("disabled","disabled");
}
if(is_dazhe==1){
//五折区
jQuery(".pro_wap_cart_info").hide();
}else{
//正价区
jQuery(".pro_wap_cart_info").show();
}}else{
jQuery(".outofstock").hide();
//库存>0
jQuery(".btn_lens").removeClass("none");
jQuery(".btn_only").removeClass("none");
jQuery(".btn_lens").removeAttr("disabled");
jQuery(".btn_only").removeAttr("disabled");
jQuery(".yushou").hide();
if(is_dazhe==1){
//五折区
jQuery(".pro_wap_cart_info").hide();
}else{
//正价区
jQuery(".pro_wap_cart_info").show();
}}
jQuery(".product_sku").html(sku);
//jQuery(".product_sku").html(sku);}
//alert(temp_span);
jQuery.each(json,function(i,n){
//console.log(json[i].name.replace(/(^\s*)|(\s*$)/g, ""));
if(temp_span == json[i].name.replace(/(^\s*)|(\s*$)/g, "")){img_str = img_str + ' <li title="'+ json[i].name + '"><img src="' + json[i].img + '" alt="'+ json[i].name +'" οnmοusemοve="preview(this);" bimg="' + json[i].img + '"/></li>';
}
});
for (var i=0;i<json.length;i++)
{
if(temp_span == json[i].name.replace(/(^\s*)|(\s*$)/g, "")){
img_main='<img jqimg="'+json[i].img+'" src="'+json[i].img+'" alt="">';
break;
}
//document.write(cars[i] + "<br>");
}
jQuery('.slider ul').html(img_str);
jQuery('.jqzoom').html(img_main);});
});
</script>