Files
OMS/app/inventorydepth/lib/offline/calculation.php
2026-01-04 19:08:31 +08:00

311 lines
12 KiB
PHP

<?php
/**
* Copyright 2012-2026 ShopeX (https://www.shopex.cn)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class inventorydepth_offline_calculation
{
public static $branchBn = array();
public static $shopFreeze = array();
public static $tmpBmShopFreeze = array();
public static $actualStock = array();
public static $storeAndFreeze = array();
public static $pkgActualStockBn = array();
public static $pkgActualStockBnNum = array();
public function __construct($app)
{
$this->app = $app;
$this->db = kernel::database();
}
public function init()
{
self::$shopFreeze =
self::$actualStock =
self::$storeAndFreeze =
self::$pkgActualStockBn =
self::$pkgActualStockBnNum = array();
}
/**
* 指定仓预占;根据订单来计算
*/
public function get_shop_freeze($shop_product_bn, $shop_id, $branch_id)
{
$sha1Str = $shop_id . '-' . strtolower($shop_product_bn) . '-' . $branch_id;
$sha1 = sha1($sha1Str);
if (isset(self::$shopFreeze[$sha1])) {
return (int) self::$shopFreeze[$sha1];
}
$bm_id_sm = $sm_id_bns = [];
foreach ((array) inventorydepth_stock_products::$products as $key=>$value) {
$bm_id_sm[$value['bm_id']] = $value['sm_id'];
$sm_id_bns[$value['sm_id']] = $value['sales_material_bn'];
}
$bm_id_sm = array_filter($bm_id_sm);
if ( !$bm_id_sm ) {
return 0;
}
//根据销售物料与基础物料的对应关系获取销售物料的店铺预占
$basicMStockFreezeLib = kernel::single('material_basic_material_stock_freeze');
foreach($bm_id_sm as $bm_id => $sm_id){
//识别一个进程处理过程中是否获取过基础物料店铺预占
$tmpBmShop = sha1($bm_id.'-'.$branch_id);
if(isset(self::$tmpBmShopFreeze[$tmpBmShop])){
$shop_freeze = self::$tmpBmShopFreeze[$tmpBmShop];
}else{
$shop_freeze = $basicMStockFreezeLib->getOrderBranchFreeze($bm_id, $branch_id);
self::$tmpBmShopFreeze[$tmpBmShop] = $shop_freeze;
}
$sales_material_bn = $sm_id_bns[$sm_id];
$tmpsha1 = sha1($shop_id.'-'.strtolower($sales_material_bn).'-'.$branch_id);
self::$shopFreeze[$tmpsha1] = (int) $shop_freeze;
}
return (int)self::$shopFreeze[$sha1];
}
/**
* 可售库存 = 仓库库存 - 冻结库存 - 预占
* @return int
*/
public function get_actual_stock($shop_product_bn,$shop_id,$branch_id)
{
$sha1Str = $shop_id.'-'.$shop_product_bn.'-'.$branch_id;
$sha1 = sha1($sha1Str);
$storeAndFreeze = $this->get_store_and_freeze($shop_product_bn,$shop_id,$branch_id);
$store = 0;
$actual_stock = $storeAndFreeze['store']
- $this->get_shop_freeze($shop_product_bn,$shop_id,$branch_id)
- $storeAndFreeze['freeze'];
self::$actualStock[$sha1] = (int)$actual_stock > 0 ? $actual_stock : 0;
return self::$actualStock[$sha1];
}
public function get_actual_stock_make($shop_product_bn,$shop_id,$branch_id) {
$storeAndFreeze = $this->get_store_and_freeze($shop_product_bn,$shop_id,$branch_id);
$str = '库存:'.$storeAndFreeze['store'] .
'- 指定仓预占:' . $this->get_shop_freeze($shop_product_bn,$shop_id,$branch_id) .
'- 仓库预占:' . $storeAndFreeze['freeze'];
return $str;
}
public function get_branch_bn($branch_id) {
if (isset(self::$branchBn[$branch_id])) {
return self::$branchBn[$branch_id];
}
$branch = app::get('ome')->model('branch')->db_dump($branch_id, 'branch_bn');
self::$branchBn[$branch_id] = $branch['branch_bn'];
return self::$branchBn[$branch_id];
}
/**
* 获取仓库库存和冻结
*/
public function get_store_and_freeze($shop_product_bn, $shop_id, $branch_id)
{
$sha1Str = $shop_id . '-' . $shop_product_bn . '-' . $branch_id;
$sha1 = sha1($sha1Str);
if (isset(self::$storeAndFreeze[$sha1])) {
return self::$storeAndFreeze[$sha1];
}
$stockProductsLib = kernel::single('inventorydepth_stock_products');
$store_sum = $store_freeze_sum = $arrive_num = $safe_num = 0;
$branch_bn = $this->get_branch_bn($branch_id);
$branch_product = $stockProductsLib->fetch_o2o_products($branch_bn, $shop_product_bn);
self::$storeAndFreeze[$sha1] = array(
'store' => $branch_product['store'],
'freeze' => $branch_product['store_freeze'],
'arrive' => $branch_product['arrive_store'],
'safe' => $branch_product['safe_store'],
);
return self::$storeAndFreeze[$sha1];
}
//获取在途库存
public function get_arrive_stock($shop_product_bn,$shop_id,$branch_id) {
$storeAndFreeze = $this->get_store_and_freeze($shop_product_bn,$shop_id,$branch_id);
return (int) $storeAndFreeze['arrive'];
}
//获取安全库存
public function get_safe_stock($shop_product_bn,$shop_id,$branch_id) {
$storeAndFreeze = $this->get_store_and_freeze($shop_product_bn,$shop_id,$branch_id);
return (int) $storeAndFreeze['safe'];
}
//获取仓库预占
public function get_branch_freeze($shop_product_bn,$shop_id,$branch_id) {
$storeAndFreeze = $this->get_store_and_freeze($shop_product_bn,$shop_id,$branch_id);
return (int) $storeAndFreeze['freeze'];
}
/**
* @description 捆绑商品店铺预占
*/
public function get_pkg_shop_freeze($shop_product_bn, $shop_id, $branch_id)
{
$sha1Str = $shop_id . '-' . strtolower($shop_product_bn) . '-' . $branch_id . '-pkg';
$sha1 = sha1($sha1Str);
if (isset(self::$shopFreeze[$sha1]) || $this->recal_pkg_shop_freeze === false) {
return (int) self::$shopFreeze[$sha1];
}
$this->recal_pkg_shop_freeze = false;
$pkgGoodsIds = $pkgGoodsIdBn = $pkgProduct = array();
foreach ((array) inventorydepth_stock_pkg::$pkg as $key => $value) {
$pkgGoodsIds[] = $value['goods_id'];
$pkgGoodsIdBn[$value['goods_id']] = $key;
$pkgProduct[$value['goods_id']] = $value['products'];
}
$offset = 0;
$limit = 1000;
do {
$filter = array(
'obj_id' => $pkgGoodsIds,
'obj_type' => 'pkg',
'branch_id|than' => 0
);
$list = app::get('ome')->model('shop_freeze_stock')->getList('shop_id,product_id,obj_id,freez_num,branch_id', $filter, $offset, $limit);
if (empty($list)) {break;}
if ($list) {
foreach ($list as $k => $val) {
$firstProduct = $pkgProduct[$val['obj_id']][0];
if ($val['product_id'] == $firstProduct['product_id']) {
$tmpsha1 = sha1($val['shop_id'] . '-' . strtolower($pkgGoodsIdBn[$val['obj_id']]) . '-' . $val['branch_id'] . '-pkg');
self::$shopFreeze[$tmpsha1] += intval($val['freez_num'] / $firstProduct['pkgnum']);
}
}
}
if (count($list) < $limit) {
break;
}
$offset += $limit;
} while (true);
return (int) self::$shopFreeze[$sha1];
}
/**
* @description 捆绑商品可售库存
* @access public
* @return void
*/
public function get_pkg_actual_stock($shop_product_bn,$shop_id, $branch_id)
{
$sha1Str = $shop_id . '-' . $shop_product_bn . $branch_id . '-pkg';
$sha1 = sha1($sha1Str);
if (isset(self::$actualStock[$sha1])) {
return (int) self::$actualStock[$sha1];
}
$pkg = kernel::single('inventorydepth_stock_pkg')->fetch_pkg($shop_product_bn);
if (!$pkg || !$pkg['products'] || !is_array($pkg['products'])) {
return false;
}
$stockList = array();
$pkgNum = array();
foreach ($pkg['products'] as $product) {
$stock = $this->get_actual_stock(trim($product['bn']),$shop_id,$branch_id);
if ($stock === false) return false;
$stockList[$product['bn']] = (int)$stock/$product['pkgnum'];
$pkgNum[$product['bn']] = $product['pkgnum'];
}
asort($stockList);
self::$pkgActualStockBn[$sha1] = key($stockList);
self::$pkgActualStockBnNum[$sha1] = $pkgNum[self::$pkgActualStockBn[$sha1]];
$actual_stock = array_shift($stockList);
self::$actualStock[$sha1] = (int) $actual_stock > 0 ? $actual_stock : 0;
return (int)self::$actualStock[$sha1];
}
public function get_pkg_actual_stock_make($shop_product_bn,$shop_id,$branch_id){
$storeAndFreeze = $this->get_pkg_store_and_freeze($shop_product_bn,$shop_id,$branch_id);
$str = '最小可售库存商品:' . $storeAndFreeze['bn'] .
'(库存('.$storeAndFreeze['store'].'):' .
'- 指定仓预占:' . $storeAndFreeze['shop_freeze'] .
'- 仓库预占:' . $storeAndFreeze['freeze'] . ') / 捆绑子商品数:' . $storeAndFreeze['pkg_bn_num'];
return $str;
}
/**
* @description 捆绑商品 仓库库存与冻结
*/
public function get_pkg_store_and_freeze($shop_product_bn, $shop_id, $branch_id)
{
$sha1Str = $shop_id . '-' . $shop_product_bn . '-' . $branch_id . '-pkg';
$sha1 = sha1($sha1Str);
if (isset(self::$storeAndFreeze[$sha1])) {
return self::$storeAndFreeze[$sha1];
}
if (!isset(self::$pkgActualStockBn[$sha1])) {
$this->get_pkg_actual_stock($shop_product_bn, $shop_id, $branch_id);
}
$bn = self::$pkgActualStockBn[$sha1];
$tmpArr = $this->get_store_and_freeze($bn, $shop_id, $branch_id);
$shopFreeze = $this->get_shop_freeze($bn, $shop_id, $branch_id);
$pkgBnNum = self::$pkgActualStockBnNum[$sha1];
$storeAndFreeze = array();
$storeAndFreeze['bn'] = $bn;
$storeAndFreeze['pkg_bn_num'] = $pkgBnNum;
$storeAndFreeze['shop_freeze'] = $shopFreeze;
$storeAndFreeze['store'] = $tmpArr['store'];
$storeAndFreeze['freeze'] = $tmpArr['freeze'];
$storeAndFreeze['arrive'] = $tmpArr['arrive'];
$storeAndFreeze['safe'] = $tmpArr['safe'];
self::$storeAndFreeze[$sha1] = $storeAndFreeze;
return self::$storeAndFreeze[$sha1];
}
//获取在途库存
public function get_pkg_arrive_stock($shop_product_bn,$shop_id,$branch_id) {
$storeAndFreeze = $this->get_pkg_store_and_freeze($shop_product_bn,$shop_id,$branch_id);
return (int) $storeAndFreeze['arrive'] / $storeAndFreeze['pkg_bn_num'];
}
//获取安全库存
public function get_pkg_safe_stock($shop_product_bn,$shop_id,$branch_id) {
$storeAndFreeze = $this->get_pkg_store_and_freeze($shop_product_bn,$shop_id,$branch_id);
return (int) $storeAndFreeze['safe'] / $storeAndFreeze['pkg_bn_num'];
}
//获取仓库预占
public function get_pkg_branch_freeze($shop_product_bn,$shop_id,$branch_id) {
$storeAndFreeze = $this->get_pkg_store_and_freeze($shop_product_bn,$shop_id,$branch_id);
return (int) $storeAndFreeze['freeze'] / $storeAndFreeze['pkg_bn_num'];
}
}