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

659 lines
23 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.
*/
/**
* 自动补货任务Lib类
*
* @author wangbiao<wangbiao@shopex.cn>
* @version $Id: Z
*/
class console_replenish
{
/**
* 确认生成补货单
*
* @param int $cursor_id
* @param array $params
* @param string $error_msg
* @return boolean
*/
public function disposeReplenish(&$cursor_id, $params, &$error_msg=null)
{
set_time_limit(0);
ini_set('memory_limit', '1024M');
$reTaskObj = app::get('console')->model('replenish_task');
$suggestObj = app::get('console')->model('replenish_suggest');
$suggestitemMdl = app::get('console')->model('replenish_suggest_items');
$branchProObj = app::get('ome')->model('branch_product');
$cpfrObj = app::get('console')->model('cpfr');
$cpfrItemObj = app::get('console')->model('cpfr_items');
$logMdl = app::get('ome')->model('operation_log');
//data
$sdfdata = $params['sdfdata'];
$sug_id = $sdfdata['sug_id'];
$task_bn = $sdfdata['task_bn'];
//操作人
$operator = kernel::single('desktop_user')->get_name();
$suggests = $suggestObj->dump(array('sug_id'=>$sug_id),'*');
if( in_array($suggests['bill_type'],array('try_drink','demo')) ){//试饮不生成单据。生成订单
return true;
}
//调出仓库
$out_branch_id = $suggests['out_branch_id'];
if(empty($out_branch_id)){
$error_msg = '调出仓库不能为空';
$logMdl->write_log('replenish_suggest@console',$sug_id,$error_msg);
return false;
}
$sql = "SELECT branch_id,branch_bn,name FROM sdb_ome_branch WHERE branch_id=".$out_branch_id;
$outBranchInfo = $suggestObj->db->selectrow($sql);
$out_branch_bn = $outBranchInfo['branch_bn'];
//补货建议单列表
$dataList = $suggestitemMdl->getList('*', array('sug_id'=>$sug_id));
if(empty($dataList)){
$error_msg = '没有补货建议单';
return false;
}
$o2o_branch_id = $suggests['branch_id'];
$product_ids = array();
foreach ($dataList as $key => $val)
{
$bm_id = $val['bm_id'];
$product_ids[$bm_id] = $bm_id;
}
//门店仓库列表
$sql = "SELECT branch_id,branch_bn,name FROM sdb_ome_branch WHERE branch_id IN(". $o2o_branch_id .")";
$tempList = $suggestObj->db->select($sql);
$o2oBranchList = array_column($tempList, null, 'branch_id');
//获取调出仓库库存
$tempList = $branchProObj->getList('branch_id,product_id,store,store_freeze,is_locked,safe_store', array('branch_id'=>$out_branch_id, 'product_id'=>$product_ids));
if(empty($tempList)){
$error_msg = '调出仓库与商品没有映射库存关系';
return false;
}
$branchStore = array();
foreach ($tempList as $key => $val)
{
$branch_id = $val['branch_id'];
$product_id = $val['product_id'];
$branchStore[$branch_id][$product_id] = $val['store'] - $val['store_freeze'];
}
//获取门店仓库库存
$tempList = $branchProObj->getList('branch_id,product_id as bm_id,store,store_freeze', array('branch_id'=>$o2o_branch_id, 'product_id'=>$product_ids));
if(empty($tempList)){
$error_msg = '门店仓库没有库存';
$logMdl->write_log('replenish_suggest@console',$sug_id,$error_msg);
//return false;
}
$o2oBranchStore = array();
foreach ($tempList as $key => $val)
{
$branch_id = $val['branch_id'];
$product_id = $val['bm_id'];
$o2oBranchStore[$branch_id][$product_id] = $val['store'] - $val['store_freeze'];
}
//params
$apply_total = 0; //申请补货总数
$actual_total = 0; //实际补货总数
$sku_total = 0; //调拨SKU总数
$store_bn = $suggests['store_bn'];
//组织数据
$sdf = array();
foreach ($dataList as $key => $val)
{
$o2o_branch_bn = $o2oBranchList[$o2o_branch_id]['branch_bn'];
$bm_id = $val['bm_id'];
$reple_nums = $val['reple_nums']; //申请补货数量
//check
if(empty($reple_nums)){
continue;
}
//调出仓库库存
$from_branch_store = $branchStore[$out_branch_id][$bm_id];
$from_branch_store = intval($from_branch_store);
//门店仓库库存
$to_branch_store = $o2oBranchStore[$o2o_branch_id][$bm_id];
$to_branch_store = intval($to_branch_store);
//实际补货数量
$in_nums = $reple_nums;
if ($from_branch_store < $reple_nums) {
$in_nums = $from_branch_store;
$branchStore[$out_branch_id][$bm_id] = 0;
} else {
$branchStore[$out_branch_id][$bm_id] -= $in_nums;
}
//items
$sdf[$store_bn][$bm_id] = array(
'bm_id' => $bm_id,
'material_bn' => $val['material_bn'],
'in_nums' => $in_nums, //实际补货数量
'reple_nums' => $val['reple_nums'], //建议补货数量
'apply_nums' => $val['apply_nums'], //申请补货数量
'from_branch_store' => $from_branch_store, //调出仓库存
'to_branch_store' => $to_branch_store, //调入门店仓库存
'to_branch_id' => $o2o_branch_id, //调入仓库ID
);
//count
$sku_total++; //SKU总数
$apply_total += $apply_nums; //申请补货总数
$actual_total += $in_nums; //实际补货总数
}
if(empty($sdf)){
$error_msg = '没有可调拨入库的货品';
return false;
}
//门店总数
$store_total = count($sdf);
$cpfr_detail = $cpfrObj->dump(array('origin_bn'=>$suggests['task_bn']),'cpfr_id');
if($cpfr_detail){
$error_msg = '补货任务已存在';
$logMdl->write_log('replenish_suggest@console',$sug_id,$error_msg);
return false;
}
//开启事务
$transaction = kernel::database()->beginTransaction();
//插入到配货单表
$masterSdf = array(
'cpfr_bn' => uniqid(date('YmdHis')), //补货单编码
'cpfr_name' => $suggests['task_bn'], //补货单名称
'branch_id' => $out_branch_id, //调出仓库ID
'branch_bn' => $out_branch_bn, //调出仓库编码
'store_total' => $store_total, //门店总数
'sku_total' => $sku_total, //SKU总数
'num_total' => $actual_total, //申请补货总数
'actual_total' => $apply_total, //实际补货总数
'operator' => $operator, //操作人
'adjust_type' => 'replenish', //调整库存类型
'physics_id' =>$suggests['physics_id'],
'origin_bn' => $suggests['task_bn'], //补货任务号
'create_time' => time(), //创建时间
'last_modified' => time(), //最后更新时间
);
$cpfr_id = $cpfrObj->insert($masterSdf);
if(!$cpfr_id){
//回滚事务
kernel::database()->rollBack();
$error_msg = '创建配货单失败';
return false;
}
//items
foreach ($sdf as $store_bn => $itemList)
{
if(empty($itemList)){
continue;
}
foreach ($itemList as $bm_id => $itemVal)
{
$itemSdf = array(
'cpfr_id' => $cpfr_id,
'store_bn' => $store_bn, //门店编码
'to_branch_id' => $itemVal['to_branch_id'], //调入仓库ID
'product_id' => $itemVal['bm_id'],
'bn' => $itemVal['material_bn'],
'num' => $itemVal['in_nums'], //实际补货数量
'original_num' => $itemVal['apply_nums'], //申请补货数量
'reple_nums' => $itemVal['reple_nums'], //建议补货数量
'from_branch_store' => $itemVal['from_branch_store'], //调出仓库存
'to_branch_store' => $itemVal['to_branch_store'], //调入仓库存
);
$cpfr_item_id = $cpfrItemObj->insert($itemSdf);
if(!$cpfr_item_id){
//回滚事务
kernel::database()->rollBack();
$error_msg = '创建配货单明细失败';
return false;
}
}
}
//提交事务
kernel::database()->commit($transaction);
//更新补货建议单状态
$suggestObj->update(array('sug_status'=>'1'), array('sug_id'=>$sug_id));
//创建调拨单
$msg = '';
$params = array(
'cpfr_id' => $cpfr_id, //配货单ID
'cpfr_bn' => $masterSdf['cpfr_bn'], //配货单编码
'business_bn'=>$suggests['task_bn'],
'physics_id'=>$suggests['physics_id'],
'sug_id' => $sug_id,
);
$result = $this->createAppropriation($params, $msg);
if(!$result && $msg){
$error_msg = $msg;
}
//更新配货单状态
$cpfrObj->update(array('bill_status'=>'2'), array('cpfr_id'=>$cpfr_id));
//销毁
unset($tempList, $dataList, $sdf);
return false;
}
/**
* 创建调拨单
*
* @param array $params 配货单信息
* @param string $error_msg
* @return bool
*/
public function createAppropriation($params, $error_msg=null)
{
$cpfrObj = app::get('console')->model('cpfr');
$cpfrItemObj = app::get('console')->model('cpfr_items');
$cpfr_id = intval($params['cpfr_id']);
$cpfr_bn = $params['cpfr_bn'];
$sug_id = $params['sug_id'];
$logMdl = app::get('ome')->model('operation_log');
//check
if(empty($cpfr_id) || empty($cpfr_bn)){
$error_msg = '创建调拨单失败,没有配货单信息';
return false;
}
//filter
$filter = array();
if($cpfr_id){
$filter['cpfr_id'] = $cpfr_id;
}else{
$filter['cpfr_bn'] = $cpfr_bn;
}
//配货单信息
$cpfrInfo = $cpfrObj->dump($filter, '*');
if(empty($cpfrInfo)){
$error_msg = '创建调拨单失败,没有获取到配货单信息';
return false;
}
if($cpfrInfo['bill_status'] == '2'){
$error_msg = '创建调拨单失败,配货单状态不允许操作';
return false;
}
$cpfr_id = $cpfrInfo['cpfr_id'];
$out_branch_id = intval($cpfrInfo['branch_id']);
$operator = $cpfrInfo['operator'];
//check
if(empty($out_branch_id)){
$error_msg = '创建调拨单失败,没有调出仓库';
return false;
}
//随机调拨出库仓对应的物流公司
$sql = "SELECT corp_id,type,name FROM sdb_ome_dly_corp WHERE branch_id=". $out_branch_id ." AND disabled='false'";
$corpInfo = $cpfrObj->db->selectrow($sql);
if(empty($corpInfo)){
//随机获取一个物流公司
$sql = "SELECT corp_id,type,name FROM sdb_ome_dly_corp WHERE disabled='false' AND d_type=1";
$corpInfo = $cpfrObj->db->selectrow($sql);
}
$corp_id = $corpInfo['corp_id'];
//不同门店列表
$sql = "SELECT DISTINCT to_branch_id,store_bn FROM sdb_console_cpfr_items WHERE cpfr_id=". $cpfr_id ."";
$storeList = $cpfrObj->db->select($sql);
if(empty($storeList)){
$error_msg = '创建调拨单失败,没有入库仓信息';
return false;
}
//检查实际补货数量
$sql = "SELECT item_id FROM sdb_console_cpfr_items WHERE cpfr_id=". $cpfr_id ." AND num>0";
$checkItems = $cpfrObj->db->selectrow($sql);
if(empty($checkItems)){
$error_msg = '没有实际补货数量,调出仓库存不足';
return false;
}
$iso_ids = array();
$errorMsgs = array();
$appropriation_type = 2; //出入库调拨类型
//按门店进行创建调拨单
foreach ($storeList as $key => $val)
{
$store_bn = $val['store_bn'];
$to_branch_id = $val['to_branch_id']; //调入仓库
//配货单明细
$itemList = $cpfrItemObj->getList('*', array('cpfr_id'=>$cpfr_id, 'store_bn'=>$store_bn,'to_branch_id'=>$to_branch_id));
if(empty($itemList)){
continue;
}
//防止重复
$appropriation_detail = $cpfrObj->db->selectrow("SELECT appropriation_id FROM sdb_taoguanallocate_appropriation WHERE original_bn='".$cpfr_bn."' AND to_branch_id=".$to_branch_id."");
if($appropriation_detail){
continue;
}
//开启事务
$transaction = kernel::database()->beginTransaction();
//format
$itemList[0]['corp_id'] = $corp_id; //物流公司
$itemList[0]['from_branch_id'] = $out_branch_id; //调出仓库
$itemList[0]['to_branch_id'] = $to_branch_id; //调入仓库
$itemList[0]['original_bn'] = $cpfr_bn; //配货单号
$itemList[0]['bill_type'] = 'replenishment';
$itemList[0]['business_bn'] = $params['business_bn']; //业务单号
$itemList[0]['to_physics_id'] = $params['physics_id']; //业务单号
$memo = sprintf('配货单[%s]门店[%s]创建调拨单', $cpfr_bn, $store_bn);
$msg = '';
//iso
$iso_id = kernel::single('console_receipt_allocate')->to_savestore($itemList, $appropriation_type, $memo, $operator, $msg);
if(!$iso_id){
//回滚事务
kernel::database()->rollBack();
//error_msg
$errorMsgs[] = sprintf('配货单[%s]创建调拨单失败:%s', $cpfr_bn, $msg);
continue;
}
//提交事务
kernel::database()->commit($transaction);
$iso_ids[] = $iso_id;
}
//更新配货单状态
//更新配货单状态
$cpfrObj->update(array('bill_status'=>'2'), array('cpfr_id'=>$cpfr_id));
//error
if($errorMsgs){
$error_msg = implode(';', $errorMsgs);
$error_msg = substr($error_msg, 0, 180);
return false;
}
//自动审核调拨单
$errorMsgs = array();
foreach ($iso_ids as $key => $iso_id)
{
$result = kernel::single('console_iostockorder')->autoCheck($iso_id);
if($result[0] === false){
$errorMsgs[] = 'iso_id:'.$iso_id.'审核失败:'.$result[1];
}
}
if($errorMsgs){
$error_msg = implode(';', $errorMsgs);
$error_msg = substr($error_msg, 0, 180);
return false;
}
return true;
}
/**
* 更新补货任务为失败状态
*/
public function updateTaskailStatus($task_id, $task_msg)
{
$reTaskObj = app::get('console')->model('replenish_task');
//更新为失败状态
$reTaskObj->update(array('task_status'=>'7', 'task_msg'=>$task_msg), array('task_id'=>$task_id));
return true;
}
/**
* 补货建议单创建
* @return
*/
public function create($data, $msg)
{
$suggestMdl = app::get('console')->model('replenish_suggest');
$branchMdl = app::get('ome')->model('branch');
$sugitemsMdl = app::get('console')->model('replenish_suggest_items');
$basicMaterialObj = app::get('material')->model('basic_material');
$suggest_data = array(
'create_time' => time(),
'apply_name' => $data['apply_name'],
'memo' => $data['memo'],
'task_bn' => $data['task_bn'],
'store_bn' => $data['store_bn'],
'branch_id' => $data['branch_id'],
'source' => $data['source'],
'physics_id' => $data['physics_id'],
'product_amount' => $data['product_amount'],
'out_branch_bn' => $data['out_branch_bn'],
'out_branch_id' => $data['out_branch_id'],
);
if($data['bill_type']) $suggest_data['bill_type'] = $data['bill_type'];
$suggestMdl->save($suggest_data);
$sug_id = $suggest_data['sug_id'];
foreach ((array) $data['items'] as $k => $v) {
$product = $basicMaterialObj->dump(array('material_bn' => $v['material_bn']), 'bm_id, material_bn, material_name');
$items_data = array(
'sug_id' => $sug_id,
'material_bn' => $v['material_bn'],
'bm_id' => $product['bm_id'],
'reple_nums' => $v['nums'],
'apply_nums' => $v['nums'],
'price' => $v['price'],
);
$sugitemsMdl->save($items_data);
}
$is_auto_check = true;
if (isset($data['check_auto']) && $data['check_auto'] === '0' ){
$is_auto_check = false;
}
if($suggest_data['out_branch_id']>0 && $is_auto_check==true){
$this->confirmReplenish($suggest_data);
}
return true;
}
/**
* 生成入库单
*/
public function createStockin($sug_id){
$suggestMdl= app::get('console')->model('replenish_suggest');
$suggest = $suggestMdl->dump(array('sug_id'=>$sug_id),'*');
//判断是否已生成
$isoMdl = app::get('taoguaniostockorder')->model('iso');
$iso = $isoMdl->db_dump(array('bill_type'=>array('try_drink','demo') ,'original_bn'=>$suggest['task_bn']),'iso_id');
if($iso){
return [false, ['msg'=>'入库单已存在']];
}
$sugitemsMdl = app::get('console')->model('replenish_suggest_items');
$items = $sugitemsMdl->getlist('*',array('sug_id'=>$sug_id));
if(empty($items)) {
return [true, ['msg'=>'缺少明细']];
}
kernel::database()->beginTransaction();
$products = [];
foreach ($items as $v) {
$products[$v['bm_id']] = [
'bn' => $v['material_bn'],
'name' => '',
'nums' => $v['reple_nums'],
'unit' => '',
'price' => 0,
];
}
$op = kernel::single('ome_func')->getDesktopUser();
$bill_type = $suggest['bill_type'];
$data = array(
'iostockorder_name' => date('Ymd') .'('.$suggest['bill_type'].')补货入库单',
'supplier' => '',
'supplier_id' => 0,
'branch' => $suggest['branch_id'],
'extrabranch_id' => $suggest['out_branch_id'],
'type_id' => ome_iostock::DIRECT_STORAGE,
'iso_price' => 0,
'memo' => (string)$addData['memo'],
'operator' => $op['op_name'],
'original_bn' => $suggest['task_bn'],
'original_id' => $suggest['task_id'],
'physics_id' => $suggest['physics_id'],
'products' => $products,
'appropriation_no' => '',
'bill_type' => $suggest['bill_type'],
'business_bn' => $suggest['task_bn'],
);
$data['check'] = 'Y';
$iostockorder_instance = kernel::single('console_iostockorder');
$rs = $iostockorder_instance->save_iostockorder($data, $msg);
$msg = '生成试饮入库单';
if($rs) {
$msg.="成功";
kernel::database()->commit();
} else {
kernel::database()->rollBack();
$msg.="失败";
}
$logMdl = app::get('ome')->model('operation_log');
$logMdl->write_log('replenish_suggest@console',$sug_id,$msg);
return [$rs, ['msg'=>$msg]];
}
/**
* 补货审核
* @return
*/
public function confirmReplenish($data){
$sug_id = $data['sug_id'];
$suggestObj = app::get('console')->model('replenish_suggest');
$suggest = $suggestObj->dump(array('sug_id'=>$sug_id),'*');
if(!in_array($suggest['sug_status'],array('0'))){
return [false, ['msg'=>'非为审核状态']];
}
//判断库存不足
$sugitemsMdl = app::get('console')->model('replenish_suggest_items');
$items = $sugitemsMdl->getlist('*',array('sug_id'=>$sug_id));
$bm_id_list = array_column($items, 'bm_id');
$bpModel = app::get('ome')->model('branch_product');
$out_branch_id = $data['out_branch_id'];
$product_store = array();
foreach($bpModel->getList('product_id,branch_id,store,store_freeze', array('product_id' => $bm_id_list, 'branch_id' => $out_branch_id)) as $value){
$product_store[$value['branch_id']][$value['product_id']] = $value['store'] - $value['store_freeze'];
}
foreach ((array)$items as $key => $value) {
$bm_id = $value['bm_id'];
if ($value['nums'] > $product_store[$out_branch_id][$bm_id]) {
$msg = $value['material_bn'].'库存不足';
return [false, ['msg'=>$msg]];
}
}
$suggestObj->update(array('sug_status'=>'1'), array('sug_id'=>$sug_id));
$sdf = array('sug_id'=>$data['sug_id'], 'task_bn'=>$data['task_bn']);
$rs = $this->disposeReplenish($cursor_id, array('sdfdata'=>$sdf), $error_msg);
$logMdl = app::get('ome')->model('operation_log');
if($rs){
//更新补货建议单状态
$suggestObj->update(array('sug_status'=>'2'), array('sug_id'=>$sug_id));
}else{
$logMdl->write_log('replenish_suggest@console',$sug_id,$error_msg);
}
return [true, ['msg'=>'成功']];
}
}