Files
OMS/app/inventorydepth/lib/calculation/salesmaterial.php
2025-12-28 23:13:25 +08:00

323 lines
12 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.
*/
/**
* ============================
* @Author: yaokangming
* @Version: 1.0
* @DateTime: 2022/6/13 14:30:53
* @describe: 销售物料分配
* ============================
*/
class inventorydepth_calculation_salesmaterial {
protected $obj;
protected $isInit = false;
protected $releaseStock = [];
public function init($salesmaterial) {
$this->isInit = true;
$this->releaseStock = [];
$smBn = [];
foreach ($salesmaterial as $key => $value) {
$smBn[] = $value['sales_material_bn'];
}
$list = app::get('inventorydepth')->model('shop_adjustment')->getList('release_stock,shop_product_bn,shop_bn',array('shop_product_bn'=>$smBn));
if ($list) {
foreach ($list as $l) {
$tmpsha1 = sha1($l['shop_bn'].'-'.$l['shop_product_bn']);
$this->releaseStock[$tmpsha1] = (int)$l['release_stock'];
}
}
}
public function get_release_stock($sku)
{
$shop_product_bn = $sku['shop_product_bn'];
$shop_bn = $sku['shop_bn'];
$shop_id = $sku['shop_id'];
$sha1Str = $shop_bn.'-'.$shop_product_bn;
$sha1 = sha1($sha1Str);
if(isset($this->releaseStock[$sha1])) return [$this->releaseStock[$sha1], []];
if($this->isInit) {
return [0, ['warning'=>'初始化未查到']];
}
$skusLib = kernel::single('inventorydepth_shop_skus');
$shop_product_bn_crc32 = $skusLib->crc32($shop_product_bn);
$shop_bn_crc32 = $skusLib->crc32($shop_bn);
$list = $this->app->model('shop_adjustment')
->select()->columns('release_stock,shop_product_bn,shop_bn')
->where('shop_product_bn_crc32=?',$shop_product_bn_crc32)
->where('shop_bn_crc32=?',$shop_bn_crc32)
->instance()->fetch_all();
$release_stock = 0;
foreach ($list as $key => $value) {
if ($value['shop_product_bn'] == $shop_product_bn && $value['shop_bn'] == $shop_bn) {
$release_stock = $value['release_stock'];
break;
}
}
$this->releaseStock[$sha1] = (int)$release_stock > 0 ? (int)$release_stock : 0;
return [$this->releaseStock[$sha1], []];
}
/**
* 运行公式
*
* @param array $sku 商品明细
* @param string $result 公式
* @param string $msg 错信息
* @return int|false 计算结果或false
* @author
**/
public function formulaRun($formula,$sku,&$msg)
{
if (is_numeric($formula))
{
if ($formula < 0)
{
$regulation_code = isset($sku['regulation_code']) ? $sku['regulation_code'] : '';
$error_msg = '库存已经小于零,请重新填写';
if ($regulation_code) {
$error_msg .= ' (规则编码: ' . $regulation_code . ')';
}
throw new \Exception($error_msg);
}
return (int)$formula;
}
//-------------------变量实际替换校验------------------//
$benchmark = kernel::single('inventorydepth_stock')->get_benchmark();
$pattern = '/\{('.implode('|', $benchmark).')\}/';
preg_match_all($pattern,$formula,$matches);
$params = $detail = [];
if($matches)
{
foreach($matches[1] as $match){
$m = array_search($match,$benchmark);
if(false === $m) {
$regulation_code = isset($sku['regulation_code']) ? $sku['regulation_code'] : '';
$error_msg = '公式错误:' . $formula;
if ($regulation_code) {
$error_msg .= ' (规则编码: ' . $regulation_code . ')';
}
throw new \Exception($error_msg);
}
$method = 'get_'.$m;
list($quantity, $msg) = $this->{$method}($sku);
if($quantity === false) {
$regulation_code = isset($sku['regulation_code']) ? $sku['regulation_code'] : '';
$error_msg = $match . '计算错误:' . $msg;
if ($regulation_code) {
$error_msg .= ' (规则编码: ' . $regulation_code . ', 方法: ' . $method . ')';
}
throw new \Exception($error_msg);
}
$detail[$match]['quantity'] = $quantity;
$detail[$match]['info'] = $msg;
$params[$m] = $quantity;
}
$msg = $detail;
}
$update_stock = kernel::single('inventorydepth_stock')->cal($formula, $params);
if (!is_numeric($update_stock)) {
$regulation_code = isset($sku['regulation_code']) ? $sku['regulation_code'] : '';
$error_msg = '计算结果异常:' . $update_stock;
if ($regulation_code) {
$error_msg .= ' (规则编码: ' . $regulation_code . ')';
}
throw new \Exception($error_msg);
}else if (floor($update_stock) < 0) {
return 0;
}
return (int)$update_stock;
}
/**
* 获取库存回写数
* @param string $method 方法,库存回写规则变量值
* @param string $args 参数
* @return array [1, [
* 'error'=>'',
* 'info'=>'',
* 'basic'=>[
* 'bn' => [
* 'quantity' => 1,
* 'info' => [
* '公式' => '库存-全局预占-仓库预占-指定仓预占',
* '库存' => 1,
* '全局预占' => 0,
* '仓库预占' => 0,
* '指定仓预占' => 0,
* ]
* ]
* ],
* ]]
*/
public function __call($method, $args) {
$sku = $args[0];
if(empty($sku['shop_product_bn']) || empty($sku['shop_bn']) || empty($sku['shop_id']) || empty($method)) {
return [false, ['error'=>'参数不全'.json_encode($sku, JSON_UNESCAPED_UNICODE).$method]];
}
$basicObj = kernel::single('inventorydepth_calculation_basicmaterial');
// 设置专用供货仓信息
$basicObj->setApplySupplyBranches($sku['supply_branch_bn']);
$type = $basicObj->getSalesMaterialType($sku['shop_product_bn'], $sku['shop_id']);
$sales_material = $basicObj->getSalesMaterial($sku['shop_product_bn'], $sku['shop_id']);
if(empty($sales_material)) {
return [false, ['error'=>'未找到销售物料']];
}
$basic_materials = $sales_material['products'];
if(empty($basic_materials)) {
return [false, ['error'=>'未找到基础物料']];
}
//按销售物料类型
if($type == 'pkg' || $type == 'gift') {
$rs = [
'info'=>'最小基础物料的值',
'基准'=>'',
'basic'=>[],
];
if(isset($rsNum)) unset($rsNum);
foreach ($basic_materials as $basic_material) {
list($oriNum, $msg) = $basicObj->{$method}($basic_material['bm_id'], $sku['shop_bn'], $sku['shop_id']);
$num = floor($oriNum / $basic_material['number']);
if(!(isset($rsNum) && $rsNum < $num)) {
$rsNum = $num;
$rs['基准'] = $basic_material['material_bn'];
}
$rs['basic'][$basic_material['material_bn']] = [
'quantity' => $num,
'基础数量' => $oriNum,
'单位数量' => $basic_material['number'],
'info' => $msg
];
}
return [(int)$rsNum, $rs];
}elseif($type == 'fukubukuro'){
//福袋组合类型
$luckyBagLib = kernel::single('ome_order_luckybag');
//获取每个福袋组合最大可售卖的库存数量
$sales_material['skuInfo'] = $sku;
$basic_materials = $luckyBagLib->getLuckyBagProductStock($sales_material, $method);
//setting
$rs = [
'info' => '福袋组合最小库存',
'基准' => '',
'luckybag' => [],
'basic' => [],
];
//按福袋纬度获取最小可回写库存数量
//@todo福袋销售物料是三层结构(销售物料-->福袋组合-->基础物料);
$line_i = 0;
$min_stock = 0;
foreach ($basic_materials as $combine_id => $combineInfo)
{
$line_i++;
$combine_bn = $combineInfo['combine_bn'];
//福袋组合最大可售卖库存
$luckybag_stock = intval($combineInfo['luckybag_stock']);
//第一行赋值
if($line_i == 1){
$min_stock = $luckybag_stock;
$rs['基准福袋编码'] = $combineInfo['combine_bn'];
}elseif($min_stock > $luckybag_stock){
//获取最小可回写库存数量
$min_stock = $luckybag_stock;
$rs['基准福袋编码'] = $combine_bn;
}
//luckybag
$rs['luckybag'][$combine_bn] = [
'quantity' => $luckybag_stock,
'福袋最大库存数量' => $luckybag_stock,
];
//基础物料列表
foreach ($combineInfo['items'] as $itemKey => $bmInfo)
{
$material_bn = $bmInfo['material_bn'];
$actual_stock = $bmInfo['actual_stock']; //实际可用库存数量
$material_stock = $bmInfo['material_stock']; //基础物料总库存数量
$mateiral_number = $bmInfo['number']; //购买件数
//logs
$rs['basic'][$material_bn] = [
'quantity' => $actual_stock,
'基础数量' => $material_stock,
'单位数量' => $mateiral_number,
'info' => $bmInfo['stock_msg'],
];
}
}
return [(int)$min_stock, $rs];
}elseif($type == 'pko') {
//多选一商品
//@todo代码从上面搬迁下来,没有修改代码逻辑;
$rs = [
'info'=>'基础物料值之和',
'basic'=>[],
];
$rsNum = 0;
foreach ($basic_materials as $basic_material) {
list($num, $msg) = $basicObj->{$method}($basic_material['bm_id'], $sku['shop_bn'], $sku['shop_id']);
$rsNum += $num;
$rs['basic'][$basic_material['material_bn']] = [
'quantity' => $num,
'info' => $msg
];
}
return [(int)$rsNum, $rs];
}
//普通销售物料
$basic_material = current($basic_materials);
list($num, $msg) = $basicObj->{$method}($basic_material['bm_id'], $sku['shop_bn'], $sku['shop_id']);
$rs = [
'info'=>'基础物料的值',
'basic'=>[
$basic_material['material_bn'] => [
'quantity' => $num,
'info' => $msg
]
],
];
return [$num, $rs];
}
}