Files
OMS/app/console/lib/stock/freeze.php
2025-12-28 23:13:25 +08:00

454 lines
20 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* Copyright © ShopeX http://www.shopex.cn. All rights reserved.
* See LICENSE file for license details.
*/
/**
* 重置货品冻结库存流水记录
*
* @access public
* @author wangbiao<wangbiao@shopex.cn>
*/
class console_stock_freeze
{
function __construct()
{
$this->_stockFreezeObj = app::get('material')->model('basic_material_stock_freeze');
}
/**
* 重置流水记录
* redis库存高可用废弃掉直接修改db库存、冻结的方法
*/
function reset_stock_freeze($product_id,$is_local = '')
{
if (empty($is_local) || $is_local != 'local') {
return false;
}
if(empty($product_id))
{
return false;
}
//初始化预占数量为0
$sql = "UPDATE sdb_material_basic_material_stock_freeze SET num=0, last_modified=". time() ." WHERE bm_id=". $product_id;
$this->_stockFreezeObj->db->exec($sql);
//订单预占
$this->order_freeze($product_id,$is_local);
//经销一件代发订单预占流水
$this->dealer_order_freeze($product_id);
//仓库预占
$this->branch_freeze($product_id,$is_local);
return true;
}
/**
* 预占流水记录
* redis库存高可用废弃掉直接修改db库存、冻结的方法
*/
function freeze($bm_id, $obj_type, $bill_type, $obj_id, $shop_id, $branch_id, $bmsq_id, $num, $obj_bn, $sub_bill_type,$is_local = '')
{
if (empty($is_local) || $is_local != 'local') {
return false;
return false;
return false;
}
if(empty($bm_id) || empty($obj_type) || empty($bmsq_id)){
return false;
}
$num = intval($num);
switch($obj_type){
//订单预占
case 1:
$filter = array('bm_id'=>$bm_id, 'obj_type'=>1, 'obj_id'=>$obj_id, 'bmsq_id'=>$bmsq_id);
$insertExtData = array('shop_id'=>$shop_id, 'bill_type'=>$bill_type);
break;
case 2:
$filter = array('bm_id'=>$bm_id, 'obj_type'=>2, 'obj_id'=>$obj_id, 'bmsq_id'=>$bmsq_id, 'bill_type'=>$bill_type);
$insertExtData = array('shop_id'=>$shop_id, 'branch_id'=>$branch_id);
break;
case 3:
$filter = array('bm_id'=>$bm_id, 'obj_type'=>3, 'obj_id'=>$obj_id, 'bmsq_id'=>$bmsq_id, 'bill_type'=>$bill_type);
$insertExtData = array('shop_id'=>$shop_id, 'branch_id'=>$branch_id);
break;
}
$freezeRow = $this->_stockFreezeObj->getList('bmsf_id', $filter, 0, 1);
if($freezeRow){
$sql = "UPDATE sdb_material_basic_material_stock_freeze SET num=num+". $num .", last_modified=". time() ." WHERE bmsf_id=".$freezeRow[0]['bmsf_id'];
return $this->_stockFreezeObj->db->exec($sql);
}else{
$insertData = $filter;
$insertData['num'] = $num;
$insertData['obj_bn'] = (string)$obj_bn;
$insertData['sub_bill_type'] = (string)$sub_bill_type;
$insertData['create_time'] = time();
$insertData['last_modified'] = time();
if($insertExtData){
$insertData = array_merge($insertData, $insertExtData);
}
return $this->_stockFreezeObj->insert($insertData);
}
}
/**
* 订单预占
*
* redis库存高可用废弃掉直接修改db库存、冻结的方法
* @param intval $product_id 基础物料ID
* @return true
*/
function order_freeze($product_id,$is_local = '')
{
if (empty($is_local) || $is_local != 'local') {
return false;
return false;
return false;
}
$orderSplitLib = kernel::single('ome_order_split');
$obj_type = material_basic_material_stock_freeze::__ORDER;
$bmsq_id = material_basic_material_stock_freeze::__SHARE_STORE;
$bill_type = 0;
$branch_id = 0;
//条件
$where = " AND i.product_id=". $product_id;
//订单
$sql = "SELECT o.order_id, o.order_bn, o.shop_id, o.order_type, o.process_status, o.ship_status, i.item_id, i.product_id, i.nums, i.sendnum, (i.nums-i.sendnum) AS freeze FROM sdb_ome_orders AS o
LEFT JOIN sdb_ome_order_items AS i ON o.order_id=i.order_id
WHERE o.ship_status IN('0','2','3') AND o.status='active' AND o.process_status in ('unconfirmed','confirmed','splitting','is_declare','splited','is_retrial')
AND i.delete='false' ". $where;
$order_list = $this->_stockFreezeObj->db->select($sql);
if($order_list)
{
foreach ($order_list as $key => $val)
{
$num = ($val['freeze']<0 ? 0 : $val['freeze']);
//brush特殊订单(刷单订单不预占冻结库存)
if($val['order_type'] == 'brush'){
continue;
}
//未生成发货单的数量
if($val['process_status']=='splitting' || $val['process_status']=='splited')
{
$dly_num = $orderSplitLib->get_item_product_num($val['order_id'], $val['item_id'], $val['product_id']);
$num = $val['nums'] - $dly_num;
}
$this->freeze($val['product_id'], $obj_type, $bill_type, $val['order_id'], $val['shop_id'], $branch_id, $bmsq_id, $num, $val['order_bn'], '',$is_local);
}
}
// //复审订单
// $sql = "SELECT o.order_id, o.order_bn, o.shop_id, o.order_type, o.process_status, o.ship_status, i.item_id, i.product_id, i.nums, i.sendnum, (i.nums-i.sendnum) AS freeze FROM sdb_ome_orders AS o
// LEFT JOIN sdb_ome_order_items AS i ON o.order_id=i.order_id
// WHERE o.ship_status IN('0','2') AND o.status='active' AND o.process_status='is_retrial' AND i.delete='false' ". $where;
// $retrial_list = $this->_stockFreezeObj->db->select($sql);
// if($retrial_list)
// {
// foreach ($retrial_list as $key => $val)
// {
// $num = ($val['freeze']<0 ? 0 : $val['freeze']);
//
// //brush特殊订单(刷单订单不预占冻结库存)
// if($val['order_type'] == 'brush'){
// continue;
// }
//
// //未发货的数量
// if($val['ship_status']=='2')
// {
// $dly_num = $orderSplitLib->get_item_product_num($val['order_id'], $val['item_id'], $val['product_id']);
// $num = $val['nums'] - $dly_num;
// }
//
// $this->freeze($val['product_id'], $obj_type, $bill_type, $val['order_id'], $val['shop_id'], $branch_id, $bmsq_id, $num, $val['order_bn'], '');
// }
// }
return true;
}
/**
* 仓库预占
*
* @param intval $product_id 基础物料ID
* @return true
* redis库存高可用废弃掉直接修改db库存、冻结的方法
*/
function branch_freeze($product_id,$is_local = '')
{
if (empty($is_local) || $is_local != 'local') {
return false;
return false;
return false;
}
$branchLib = kernel::single('ome_branch');
$branchPrdLib = kernel::single('o2o_branch_product');
$obj_type = material_basic_material_stock_freeze::__BRANCH;
$bmsq_id = material_basic_material_stock_freeze::__SHARE_STORE;
//条件
$where = ' AND b.product_id='. $product_id;
//发货单
$sql = 'SELECT a.delivery_id, a.delivery_bn, a.branch_id, b.item_id, b.product_id, b.number FROM sdb_ome_delivery AS a
LEFT JOIN sdb_ome_delivery_items as b ON a.delivery_id=b.delivery_id
WHERE a.status IN ("progress", "ready", "stop") and a.process="false" and type="normal" and a.is_bind="false" '. $where;
$dly_list = $this->_stockFreezeObj->db->select($sql);
if($dly_list)
{
//业务类型
$bill_type = material_basic_material_stock_freeze::__DELIVERY;
foreach ($dly_list as $key => $val)
{
//所属店铺
$order_sql = "SELECT b.shop_id FROM sdb_ome_delivery_order AS a LEFT JOIN sdb_ome_orders AS b ON a.order_id=b.order_id WHERE a.delivery_id=". $val['delivery_id'];
$tempInfo = $this->_stockFreezeObj->db->selectrow($order_sql);
$shop_id = $tempInfo['shop_id'];
//根据仓库识别是否门店仓还是电商仓
$store_id = $branchLib->isStoreBranch($val['branch_id']);
if($store_id)
{
//识别门店货品是否管控库存,不管控直接跳过
$is_bm_ctrl_store = $branchPrdLib->isCtrlBmStore($val['branch_id'], $val['product_id']);
if($is_bm_ctrl_store)
{
//门店仓
$this->freeze($val['product_id'], $obj_type, $bill_type, $val['delivery_id'], $shop_id, $val['branch_id'], material_basic_material_stock_freeze::__STORE_CONFIRM, $val['number'], $val['delivery_bn'],'',$is_local);
}
else
{
continue;
}
}
else
{
//电商仓
$this->freeze($val['product_id'], $obj_type, $bill_type, $val['delivery_id'], $shop_id, $val['branch_id'], $bmsq_id, $val['number'], $val['delivery_bn'],'',$is_local);
}
}
}
//售后换货
$sql = "SELECT r.reship_id, r.reship_bn, r.shop_id, r.changebranch_id AS branch_id, b.product_id, b.num FROM sdb_ome_reship AS r
LEFT JOIN sdb_ome_reship_items AS b ON r.reship_id=b.reship_id
WHERE r.return_type='change' AND b.return_type='change' AND r.change_status='0' AND r.is_check in('1','11') ". $where;
$reship_list = $this->_stockFreezeObj->db->select($sql);
if($reship_list)
{
//业务类型
$bill_type = material_basic_material_stock_freeze::__RESHIP;
// 查库存,是否足够预占,如果不足,则不冻到仓,冻结到商品上。
$bpList = app::get('ome')->model('branch_product')->getList('product_id,store,store_freeze,branch_id', ['branch_id'=>array_unique(array_column($reship_list,'branch_id')),'product_id'=>$product_id]);
$bpList = array_column($bpList,null,'branch_id');
foreach ($reship_list as $key => $val)
{
$bpInfo = $bpList[$val['branch_id']] ?? [];
if ($bpInfo && $bpInfo['store'] - $bpInfo['store_freeze'] < $val['num']) {
// 可用库存不够,冻结到商品
$obj_type = material_basic_material_stock_freeze::__AFTERSALE;
$val['branch_id'] = 0;
}
//根据仓库识别是否门店仓还是电商仓
$store_id = $branchLib->isStoreBranch($val['branch_id']);
if($store_id)
{
//门店仓
$this->freeze($val['product_id'], $obj_type, $bill_type, $val['reship_id'], $val['shop_id'], $val['branch_id'], material_basic_material_stock_freeze::__STORE_CONFIRM, $val['num'],$val['reship_bn'],'',$is_local);
}
else
{
//电商仓
$this->freeze($val['product_id'], $obj_type, $bill_type, $val['reship_id'], $val['shop_id'], $val['branch_id'], $bmsq_id, $val['num'],$val['reship_bn'],'',$is_local);
}
}
}
//采购退货
$sql = "SELECT a.rp_id, a.rp_bn, a.branch_id, b.product_id, b.num FROM sdb_purchase_returned_purchase AS a
LEFT JOIN sdb_purchase_returned_purchase_items AS b ON a.rp_id=b.rp_id
WHERE a.rp_type IN ('eo') AND a.return_status IN ('1','4') AND a.check_status IN ('2') ". $where;
$purchase_list = $this->_stockFreezeObj->db->select($sql);
if($purchase_list)
{
//业务类型
$bill_type = material_basic_material_stock_freeze::__RETURNED;
foreach ($purchase_list as $key => $val)
{
$this->freeze($val['product_id'], $obj_type, $bill_type, $val['rp_id'], '', $val['branch_id'], $bmsq_id, $val['num'], $val['rp_bn'], '',$is_local);
}
}
//调拨出库
$sql = "SELECT a.iso_id, a.iso_bn, a.branch_id, b.product_id, b.nums FROM sdb_taoguaniostockorder_iso AS a
LEFT JOIN sdb_taoguaniostockorder_iso_items AS b ON a.iso_id=b.iso_id
WHERE a.iso_status IN ('1','2') AND a.check_status IN ('2') AND a.type_id in('5','7','100','300','40') ". $where;
$iso_list = $this->_stockFreezeObj->db->select($sql);
if($iso_list)
{
//业务类型
$bill_type = material_basic_material_stock_freeze::__STOCKOUT;
foreach ($iso_list as $key => $val)
{
$this->freeze($val['product_id'], $obj_type, $bill_type, $val['iso_id'], '', $val['branch_id'], $bmsq_id, $val['nums'], $val['iso_bn'], '',$is_local);
}
}
//库内转储
$sql = "SELECT d.stockdump_id, d.stockdump_bn, d.from_branch_id AS branch_id, b.product_id, b.num FROM sdb_console_stockdump AS d
LEFT JOIN sdb_console_stockdump_items AS b ON d.stockdump_id=b.stockdump_id
WHERE d.confirm_type='1' AND d.self_status='1' AND d.in_status='0' ". $where;
$stockdump_list = $this->_stockFreezeObj->db->select($sql);
if($stockdump_list)
{
//业务类型
$bill_type = material_basic_material_stock_freeze::__STOCKDUMP;
foreach ($stockdump_list as $key => $val)
{
$this->freeze($val['product_id'], $obj_type, $bill_type, $val['stockdump_id'], '', $val['branch_id'], $bmsq_id, $val['num'],$val['stockdump_bn'], '',$is_local);
}
}
//唯品会出库
$product_bns = array();
$sql = "SELECT material_bn FROM sdb_material_basic_material WHERE bm_id=". $product_id;
$productInfo = $this->_stockFreezeObj->db->select($sql);
if($productInfo)
{
foreach ($productInfo as $key => $val)
{
$product_bns[] = $val['material_bn'];
}
$where = " AND b.bn in ('". implode("','", $product_bns) ."')";
$sql = "SELECT a.stockout_id, a.stockout_no, a.branch_id, b.bn, b.num FROM sdb_purchase_pick_stockout_bills AS a
LEFT JOIN sdb_purchase_pick_stockout_bill_items AS b ON a.stockout_id=b.stockout_id
WHERE a.status=1 AND a.confirm_status=2 ". $where;
$stockout_list = $this->_stockFreezeObj->db->select($sql);
if($stockout_list)
{
//业务类型
$bill_type = material_basic_material_stock_freeze::__VOPSTOCKOUT;
foreach ($stockout_list as $key => $val)
{
//bm_id
$pro_sql = "SELECT bm_id FROM sdb_material_basic_material WHERE material_bn='". $val['bn'] ."'";
$productInfo = $this->_stockFreezeObj->db->selectrow($pro_sql);
if(empty($productInfo))
{
continue;
}
$product_id = $productInfo['bm_id'];
$this->freeze($product_id, $obj_type, $bill_type, $val['stockout_id'], '', $val['branch_id'], $bmsq_id, $val['num'], $val['stockout_no'], '',$is_local);
}
}
}
//人工库存预占记录(状态:预占中)
$bill_type = material_basic_material_stock_freeze::__ARTIFICIALFREEZE;
$sql_af = "select bmsaf_id,branch_id,bm_id,freeze_num,original_bn from sdb_material_basic_material_stock_artificial_freeze where status=1 and bm_id = ".$product_id;
$af_list = $this->_stockFreezeObj->db->select($sql_af);
if(!empty($af_list)){
foreach ($af_list as $val_af){
$this->freeze($val_af['bm_id'], $obj_type, $bill_type, $val_af['bmsaf_id'], '', $val_af['branch_id'], $bmsq_id, $val_af['freeze_num'], $val_af['original_bn'], '',$is_local);
}
}
//盘点差异单预占
$bill_type = material_basic_material_stock_freeze::__DIFFERENCEOUT;
$sql_af = "select i.diff_id, m.diff_bn, i.branch_id,i.bm_id,i.freeze_num as number from sdb_console_difference m
left join sdb_console_difference_items_freeze i on(m.id=i.diff_id)
where m.status in('4','2') and bm_id = ".$product_id;;
$af_list = $this->_stockFreezeObj->db->select($sql_af);
if(!empty($af_list)){
$adjustMdl = app::get('console')->model('adjust');
foreach($af_list as $val_af){
$this->freeze($val_af['bm_id'], $obj_type, $bill_type, $val_af['diff_id'], '', $val_af['branch_id'], $bmsq_id, abs($val_af['number']), $val_af['diff_bn'], '',$is_local);
}
}
//加工单预占
$bill_type = material_basic_material_stock_freeze::__MATERIALPACKAGEOUT;
$sql_af = "select i.mp_id, m.mp_bn, m.branch_id,i.bm_id,i.number from sdb_console_material_package m
left join sdb_console_material_package_items_detail i on(m.id=i.mp_id)
where m.status in('2') and bm_id = ".$product_id;;
$af_list = $this->_stockFreezeObj->db->select($sql_af);
if(!empty($af_list)){
$adjustMdl = app::get('console')->model('adjust');
foreach($af_list as $val_af){
$this->freeze($val_af['bm_id'], $obj_type, $bill_type, $val_af['mp_id'], '', $val_af['branch_id'], $bmsq_id, abs($val_af['number']), $val_af['mp_bn'], '',$is_local);
}
}
return true;
}
/**
* 经销一件代发订单预占流水
*
* @param intval $product_id 基础物料ID
* @return true
*/
public function dealer_order_freeze($product_id)
{
//库存预占类型
$obj_type = material_basic_material_stock_freeze::__ORDER;
$bmsq_id = material_basic_material_stock_freeze::__SHARE_STORE;
$bill_type = material_basic_material_stock_freeze::__DEALER_ORDER;
$branch_id = 0;
//检查是否安装dealer应用
if(!app::get('dealer')->is_installed()){
return false;
}
//经销一件代发订单库存预占
$sql = "SELECT a.plat_item_id,a.product_id,a.bn,a.nums, b.plat_order_id,b.plat_order_bn,b.shop_id FROM sdb_dealer_platform_order_items AS a LEFT JOIN sdb_dealer_platform_orders AS b ON a.plat_order_id=b.plat_order_id ";
$sql .= " WHERE a.product_id=". $product_id ." AND is_shopyjdf_type='2' AND a.process_status='unconfirmed' AND a.is_delete='false'";
$sql .= " AND b.process_status IN('unconfirmed', 'fail')";
$tempList = kernel::database()->select($sql);
if(empty($tempList)){
return true;
}
foreach ($tempList as $itemKey => $itemVal)
{
$plat_order_id = $itemVal['plat_order_id'];
$product_id = $itemVal['product_id'];
$nums = $itemVal['nums'];
//freeze
$this->freeze($product_id, $obj_type, $bill_type, $plat_order_id, $itemVal['shop_id'], $branch_id, $bmsq_id, $nums, $itemVal['plat_order_bn'], '');
}
return true;
}
}