mirror of
https://gitee.com/ShopeX/OMS
synced 2026-03-22 18:35:35 +08:00
467 lines
19 KiB
PHP
467 lines
19 KiB
PHP
<?php
|
||
/**
|
||
* Copyright © ShopeX (http://www.shopex.cn). All rights reserved.
|
||
* See LICENSE file for license details.
|
||
*/
|
||
/**
|
||
* ============================
|
||
* @Author: yaokangming
|
||
* @Version: 1.0
|
||
* @DateTime: 库存调整单
|
||
* @describe: 类
|
||
* ============================
|
||
*/
|
||
class console_adjust {
|
||
|
||
/**
|
||
* dealSave
|
||
* @param mixed $data 数据
|
||
* @return mixed 返回值
|
||
*/
|
||
|
||
public function dealSave($data) {
|
||
if(empty($data['branch_id'])) {
|
||
return [false, ['msg'=>'仓库不存在']];
|
||
}
|
||
if(empty($data['negative_branch_id'])) {
|
||
return [false, ['msg'=>'出库仓库不存在']];
|
||
}
|
||
if(mb_strlen($data['memo']) > 255) {
|
||
return [false, ['msg'=>'备注过长,建议80字以下']];
|
||
}
|
||
if(empty($data['items'])) {
|
||
return [false, ['msg'=>'缺少明细']];
|
||
}
|
||
$branch = app::get('ome')->model('branch')->db_dump(array('branch_id'=>$data['branch_id'],'check_permission' => 'false'), 'branch_bn,type');
|
||
if(empty($branch)) {
|
||
return [false, ['msg'=>'仓库不存在']];
|
||
}
|
||
$op = kernel::single('ome_func')->getDesktopUser();
|
||
$adjustMdl = app::get('console')->model('adjust');
|
||
kernel::database()->beginTransaction();
|
||
$main = [
|
||
'adjust_bn' => $data['adjust_bn'] ? : $adjustMdl->gen_id($branch['branch_bn']),
|
||
'adjust_type' => $data['adjust_type'] ? : 'tz',
|
||
'adjust_bill_type' => (string) $data['adjust_bill_type'],
|
||
'adjust_mode' => $data['adjust_mode'] ? : 'zl',
|
||
'branch_id' => $data['branch_id'],
|
||
'negative_branch_id' => json_encode($data['negative_branch_id'], 1),
|
||
'is_check' => $data['is_check'],
|
||
'iso_status' => $data['iso_status'] ? : 'check',
|
||
'bill_status' => '1',
|
||
'operator' => $data['application_name'] ? $data['application_name'] : $op['op_name'],
|
||
'origin_id' => $data['origin_id'] ? : 0,
|
||
'origin_bn' => (string)$data['origin_bn'],
|
||
'business_bn' => (string)($data['business_bn'] ? : $data['origin_bn']),
|
||
'memo' => (string)$data['memo'],
|
||
'adjust_channel' => $data['adjust_channel']=='storeadjust'?'storeadjust':'branchadjust',
|
||
];
|
||
if($data['source']){
|
||
$main['source'] = $data['source'];
|
||
}
|
||
if($data['create_time']) {
|
||
$main['at_time'] = $data['create_time'];
|
||
}
|
||
$rs = $adjustMdl->insert($main);
|
||
if(!$rs) {
|
||
$errmsg = '主表保存失败:'.kernel::database()->errorinfo();
|
||
kernel::database()->rollBack();
|
||
return [false, ['msg'=>$errmsg]];
|
||
}
|
||
if($main['origin_id']) {
|
||
$oiRows = $adjustMdl->getList('id', ['origin_id'=>$main['origin_id'], 'adjust_type'=>$main['adjust_type'], 'adjust_bill_type'=>$main['adjust_bill_type']]);
|
||
if(count($oiRows) > 1) {
|
||
kernel::database()->rollBack();
|
||
return [false, ['msg'=>$main['origin_bn'].'已经存在调整单类型:'.$adjustMdl->schema['columns']['adjust_type']['type'][$main['adjust_type']].',子类型:'.$main['adjust_bill_type']]];
|
||
}
|
||
}
|
||
$productIds = array_keys($data['items']);
|
||
$oldProductStore = app::get('ome')->model('branch_product')->getList('product_id,branch_id,store,store_freeze', ['branch_id'=>$data['negative_branch_id'], 'product_id'=>$productIds]);
|
||
|
||
$productStore = [];
|
||
foreach($oldProductStore as $v) {
|
||
$productStore[$v['product_id']]['store'] += $v['store'];
|
||
$productStore[$v['product_id']]['store_freeze'] += $v['store_freeze'];
|
||
}
|
||
$products = app::get('material')->model('basic_material')->getList('bm_id,material_bn,material_name', ['bm_id'=>$productIds]);
|
||
$products = array_column($products, null, 'bm_id');
|
||
|
||
$batch = $data['batch'];
|
||
$items = [];
|
||
$freezeItems = [];
|
||
foreach ($data['items'] as $bmId => $number) {
|
||
if($main['adjust_mode'] == 'zl' && bccomp($number, 0, 0) == 0) {
|
||
continue;
|
||
}
|
||
$tmp = [
|
||
'adjust_id' => $main['id'],
|
||
'bm_id' => $bmId,
|
||
'bm_bn' => $products[$bmId]['material_bn'],
|
||
'bm_name' => $products[$bmId]['material_name'],
|
||
'origin_number' => (int)$productStore[$bmId]['store'],
|
||
|
||
];
|
||
|
||
$tmp['number'] = $main['adjust_mode'] == 'zl' ? (int)$number : bcsub($number, $tmp['origin_number'], 0);
|
||
$tmp['final_number'] = bcadd($tmp['origin_number'], $tmp['number'], 0);
|
||
if(bccomp($tmp['final_number'], 0, 0) == -1) {
|
||
kernel::database()->rollBack();
|
||
return [false, ['msg'=>'商品:'.$tmp['bm_bn'].'调整后数量不能为负数 调整后数量为:'.$tmp['final_number'].' 调整前数量为:'.$tmp['origin_number'].' 调整数量为:'.$tmp['number']]];
|
||
}
|
||
if($data['sn'][$bmId]) {
|
||
if(count($data['sn'][$bmId]) != $tmp['number']) {
|
||
kernel::database()->rollBack();
|
||
return [false, ['msg'=>'商品:'.$tmp['bm_bn'].' SN数量不对']];
|
||
}
|
||
$tmp['sn'] = json_encode($data['sn'][$bmId]);
|
||
}
|
||
|
||
if($batch[$bmId]){
|
||
$tmp['batch'] = $batch[$bmId];
|
||
}
|
||
if(($productStore[$bmId]['store'] - $productStore[$bmId]['store_freeze'] + $tmp['number']) < 0
|
||
&& $data['source'] != '初始化导入') {
|
||
kernel::database()->rollBack();
|
||
return [false, ['msg'=>'商品:'.$tmp['bm_bn'].'库存不足 库存为:'.$productStore[$bmId]['store'].' 冻结为:'.$productStore[$bmId]['store_freeze'].' 调整数量为:'.$tmp['number']]];
|
||
}
|
||
$items[] = $tmp;
|
||
}
|
||
if(empty($items)) {
|
||
kernel::database()->rollBack();
|
||
return [false, ['msg'=>'缺少保存明细']];
|
||
}
|
||
$adjustItemsMdl = app::get('console')->model('adjust_items');
|
||
$sql = kernel::single('ome_func')->get_insert_sql($adjustItemsMdl, $items);
|
||
$adjustItemsMdl->db->exec($sql);
|
||
app::get('ome')->model('operation_log')->write_log('adjust@console',$main['id'],"新建成功,来源:".($data['source']?:'新建操作'));
|
||
kernel::database()->commit();
|
||
|
||
if($data['is_check'] == '0') {
|
||
$this->confirmBill($main);
|
||
}
|
||
return [true, ['msg'=>'操作成功']];
|
||
}
|
||
|
||
|
||
/**
|
||
* confirmBill
|
||
* @param mixed $main main
|
||
* @return mixed 返回值
|
||
*/
|
||
public function confirmBill($main) {
|
||
$items = app::get('console')->model('adjust_items')->getList('id', ['adjust_id'=>$main['id'], 'adjust_status'=>'0']);
|
||
|
||
$itemIds = array_column($items, 'id');
|
||
foreach (array_chunk($itemIds, 100000) as $val) {
|
||
$this->confirmItems($val,$main);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* confirmItems
|
||
* @param mixed $itemIds ID
|
||
* @param mixed $main main
|
||
* @return mixed 返回值
|
||
*/
|
||
public function confirmItems($itemIds, $main) {
|
||
$adjustItemsMdl = app::get('console')->model('adjust_items');
|
||
|
||
$items = $adjustItemsMdl->getList('id,bm_id,bm_bn,number,sn,batch', ['id'=>$itemIds, 'adjust_id'=>$main['id'], 'adjust_status'=>'0']);
|
||
|
||
if(empty($items)) {
|
||
return [true, ['msg'=>'明细已经调整完']];
|
||
}
|
||
$adjust_channel = $main['adjust_channel'].($main['adjust_bill_type'] == '库存初始化' ? '_init' : '');
|
||
if($main['adjust_type'] == 'pd') {
|
||
$adjust_channel = $main['adjust_channel'] == 'storeadjust' ? 'storeinventory' : 'branchinventory';
|
||
}
|
||
$op = kernel::single('ome_func')->getDesktopUser();
|
||
$adjustMdl = app::get('console')->model('adjust');
|
||
$adjustMdl->update(['bill_status'=>'2'], ['id'=>$main['id']]);
|
||
$addData= $subData = array(
|
||
'original_bn' => $main['adjust_bn'],
|
||
'original_id' => $main['id'],
|
||
'branch_id' => $main['branch_id'],
|
||
'negative_branch_id' => json_decode($main['negative_branch_id'], 1),
|
||
'iso_status' => $main['iso_status'],
|
||
'adjust_channel' => $adjust_channel,
|
||
'operator' => $op['op_name'],
|
||
'memo' => $main['memo'],
|
||
'business_bn' => $main['business_bn'] ? : $main['adjust_bn'],
|
||
);
|
||
|
||
foreach ($items as $v) {
|
||
if($v['number'] > 0) {
|
||
$addData['item_id'][] = $v['id'];
|
||
$addData['items'][] = array(
|
||
'product_id'=>$v['bm_id'],
|
||
'bn' =>$v['bm_bn'],
|
||
'nums'=>$v['number'],
|
||
|
||
'sn' =>$v['sn'] ? json_decode($v['sn'],true) : [],
|
||
'memo'=>$main['memo'],
|
||
'batch'=>$v['batch'] ? json_decode($v['batch'],true) : [],
|
||
);
|
||
}
|
||
if($v['number'] < 0) {
|
||
$subData['item_id'][$v['bm_id']] = $v['id'];
|
||
if(is_array($v['batch'])) {
|
||
foreach($v['batch'] as $bak => $bav) {
|
||
$v['batch'][$bak]['num'] = abs($bav['num']);
|
||
}
|
||
}
|
||
$subData['items'][] = array(
|
||
'product_id'=>$v['bm_id'],
|
||
'bn' =>$v['bm_bn'],
|
||
|
||
'sn' =>$v['sn'] ? json_decode($v['sn'],true) : [],
|
||
'nums'=>abs($v['number']),
|
||
'memo'=>$main['memo'],
|
||
'batch'=>$v['batch'] ? json_decode($v['batch'],true) : [],
|
||
);
|
||
}
|
||
if($v['number'] == 0) {
|
||
$adjustItemsMdl->update(['adjust_status'=>'1'], ['id'=>$v['id']]);
|
||
}
|
||
}
|
||
|
||
$msg = '';
|
||
$failNum = 0;
|
||
if($addData['items']) {
|
||
list($rs, $rsData) =$this->_dealInItems($addData);
|
||
if(!$rs) {
|
||
$msg .= '入库失败:' . $rsData['msg'];
|
||
$failNum += count($addData['items']);
|
||
}
|
||
}
|
||
if($subData['items']) {
|
||
list($rs, $rsData) = $this->_dealOutItems($subData);
|
||
if(!$rs) {
|
||
$msg .= '出库失败:' . $rsData['msg'];
|
||
$failNum += count($subData['items']);
|
||
}
|
||
}
|
||
$opLog = "调整单部分确认,";
|
||
if(!$adjustItemsMdl->db_dump(['adjust_id'=>$main['id'], 'adjust_status'=>'0'], 'id')) {
|
||
$adjustMdl->update(['bill_status'=>'4'], ['id'=>$main['id']]);
|
||
$opLog = "调整单确认完成,";
|
||
}
|
||
$opLog .= $msg;
|
||
app::get('ome')->model('operation_log')->write_log('adjust@console',$main['id'],$opLog);
|
||
if($msg) {
|
||
return [false, ['msg'=>$msg, 'fail_num'=>$failNum]];
|
||
}
|
||
return [true, ['msg'=>'操作成功']];
|
||
}
|
||
|
||
|
||
private function _dealInItems($addData) {
|
||
if(empty($addData['items'])) {
|
||
return [true, ['msg'=>'缺少明细']];
|
||
}
|
||
kernel::database()->beginTransaction();
|
||
$products = [];
|
||
foreach ($addData['items'] as $v) {
|
||
$products[$v['product_id']] = [
|
||
'bn' => $v['bn'],
|
||
'name' => '',
|
||
'nums' => $v['nums'],
|
||
|
||
'sn_list' => $v['sn'],
|
||
'unit' => '',
|
||
'price' => 0,
|
||
'batch'=>$v['batch'],
|
||
];
|
||
}
|
||
$op = kernel::single('ome_func')->getDesktopUser();
|
||
$data = array(
|
||
'iostockorder_name' => date('Ymd') . '入库单',
|
||
'supplier' => '',
|
||
'supplier_id' => 0,
|
||
'branch' => $addData['branch_id'],
|
||
'extrabranch_id' => 0,
|
||
'type_id' => ome_iostock::DIRECT_STORAGE,
|
||
'iso_price' => 0,
|
||
'memo' => (string)$addData['memo'],
|
||
'operator' => $op['op_name'],
|
||
'original_bn' => $addData['original_bn'],
|
||
'original_id' => $addData['original_id'],
|
||
'products' => $products,
|
||
'appropriation_no' => '',
|
||
'bill_type' => $addData['adjust_channel'],
|
||
'business_bn' => $addData['business_bn'],
|
||
);
|
||
$branch = app::get('ome')->model('branch')->db_dump(['branch_id'=>$addData['branch_id']], 'type');
|
||
if($branch['type']=='damaged') {
|
||
$data['type_id'] = ome_iostock::DAMAGED_STORAGE;
|
||
}
|
||
if($addData['iso_status'] == 'confirm') {
|
||
$data['confirm'] = 'Y';
|
||
} else {
|
||
$data['check'] = 'Y';
|
||
}
|
||
$iostockorder_instance = kernel::single('console_iostockorder');
|
||
$rs = $iostockorder_instance->save_iostockorder($data, $msg);
|
||
if($rs) {
|
||
$adjustItemsMdl = app::get('console')->model('adjust_items');
|
||
$adjustItemsMdl->update(['adjust_status'=>'1'], ['id'=>$addData['item_id']]);
|
||
kernel::database()->commit();
|
||
} else {
|
||
kernel::database()->rollBack();
|
||
|
||
}
|
||
return [$rs, ['msg'=>$msg]];
|
||
}
|
||
|
||
private function _dealOutItems($subData){
|
||
if(empty($subData['items'])) {
|
||
return [true, ['msg'=>'缺少明细']];
|
||
}
|
||
$arrBmNum = [];
|
||
$arrBmBn = [];
|
||
|
||
$arrSn = [];
|
||
$batchlist = [];
|
||
foreach ($subData['items'] as $v) {
|
||
$arrBmNum[$v['product_id']] = $v['nums'];
|
||
$arrBmBn[$v['product_id']] = $v['bn'];
|
||
|
||
$arrSn[$v['product_id']] = $v['sn'];
|
||
$batchlist[$v['product_id']] = $v['batch'];
|
||
}
|
||
$arrBmIds = array_keys($arrBmNum);
|
||
$bpRows = app::get('ome')->model('branch_product')->getList('*', ['branch_id'=>$subData['negative_branch_id'], 'product_id'=>$arrBmIds]);
|
||
|
||
|
||
$arrBranchRows = [];
|
||
foreach ($bpRows as $v) {
|
||
$arrBranchRows[$v['branch_id']][$v['product_id']] = (int)($v['store'] - $v['store_freeze']);
|
||
}
|
||
$op = kernel::single('ome_func')->getDesktopUser();
|
||
$rsbool = true;
|
||
$failBranchId = [];
|
||
$rsMsg = '';
|
||
foreach ($arrBranchRows as $branch_id => $v) {
|
||
kernel::database()->beginTransaction();
|
||
|
||
$products = [];
|
||
$itemIds = [];
|
||
foreach ($v as $bm_id => $vv) {
|
||
if($arrBmNum[$bm_id] < 1) {
|
||
continue;
|
||
}
|
||
$itemIds[] = $subData['item_id'][$bm_id];
|
||
if($arrBmNum[$bm_id] > $vv) {
|
||
$n = $vv;
|
||
} else {
|
||
$n = $arrBmNum[$bm_id];
|
||
}
|
||
$arrBmNum[$bm_id] -= $n;
|
||
$products[$bm_id] = [
|
||
'bn' => $arrBmBn[$bm_id],
|
||
'name' => '',
|
||
|
||
'sn' => $arrSn[$bm_id],
|
||
'nums' => $n,
|
||
'unit' => '',
|
||
'price' => 0,
|
||
'batch'=>$batchlist[$bm_id],
|
||
];
|
||
}
|
||
$data = array(
|
||
'iostockorder_name' => date('Ymd') . '出库单',
|
||
'supplier' => '',
|
||
'supplier_id' => 0,
|
||
'branch' => $branch_id,
|
||
'extrabranch_id' => 0,
|
||
'type_id' => ome_iostock::DIRECT_LIBRARAY,
|
||
'iso_price' => 0,
|
||
'memo' => (string)$subData['memo'],
|
||
'operator' => $op['op_name'],
|
||
'original_bn' => $subData['original_bn'],
|
||
'original_id' => $subData['original_id'],
|
||
'products' => $products,
|
||
'appropriation_no' => '',
|
||
'bill_type' => $subData['adjust_channel'],
|
||
'business_bn' => $subData['business_bn'],
|
||
);
|
||
if($subData['iso_status'] == 'confirm') {
|
||
$data['confirm'] = 'Y';
|
||
} else {
|
||
$data['check'] = 'Y';
|
||
}
|
||
$iostockorder_instance = kernel::single('console_iostockorder');
|
||
$rs = $iostockorder_instance->save_iostockorder($data, $msg);
|
||
if($rs) {
|
||
$adjustItemsMdl = app::get('console')->model('adjust_items');
|
||
$adjustItemsMdl->update(['adjust_status'=>'1'], ['id'=>$itemIds]);
|
||
kernel::database()->commit();
|
||
} else {
|
||
|
||
$rsbool = false;
|
||
$failBranchId[] = $branch_id;
|
||
$rsMsg .= '仓库ID:'.$branch_id.','.$msg.'</br>';
|
||
|
||
kernel::database()->rollBack();
|
||
}
|
||
}
|
||
return [$rsbool, ['msg'=>$rsMsg, 'branch_id'=>$failBranchId]];
|
||
}
|
||
|
||
/**
|
||
* 创建AdjustDiff
|
||
* @param mixed $data 数据
|
||
* @return mixed 返回值
|
||
*/
|
||
public function createAdjustDiff($data)
|
||
{
|
||
$adjsutMdl = app::get('console')->model('adjust');
|
||
$diff_bn = $data['original_bn'];
|
||
|
||
$branch = app::get('ome')->model('branch')->db_dump(['branch_id' => $data['branch'], 'check_permission' => 'false']);
|
||
|
||
$filter = ['adjust_type' => 'tz', 'origin_bn' => $diff_bn, 'branch_id' => $data['branch']];
|
||
//盘盈和盘亏分别生成调整单
|
||
if (isset($data['type_id']) && $data['type_id']) {
|
||
$filter['adjust_bill_type'] = $data['type_id'] == '921' ? 'less' : 'more';
|
||
}
|
||
$adjustInfo = $adjsutMdl->db_dump($filter);
|
||
if ($adjustInfo) {
|
||
return [false, "差异单" . $diff_bn . "已生成" . $branch['branch_bn'] . "的库存调整单"];
|
||
}
|
||
$adjust_bill_type = $data['type_id'] == '921' ? 'less' : 'more';
|
||
$adjustMain = [
|
||
'adjust_mode' => 'zl',
|
||
'is_check' => 0,
|
||
'iso_status' => 'confirm',
|
||
'branch_id' => $data['branch'],
|
||
'negative_branch_id' => [$data['branch']],
|
||
'memo' => '差异处理',
|
||
'source' => '差异处理',
|
||
'adjust_type' => 'cy',
|
||
'adjust_bill_type' => $branch['branch_bn'].'_'.$adjust_bill_type,
|
||
'origin_id' => $data['original_id'],
|
||
'origin_bn' => $diff_bn,
|
||
];
|
||
if ($data['at_time']) {
|
||
if (is_string($data['at_time'])) {
|
||
$adjustMain['create_time'] = date('Y-m-d H:i:s', strtotime($data['at_time']));
|
||
} elseif (is_numeric($data['at_time'])) {
|
||
$adjustMain['create_time'] = date('Y-m-d H:i:s', $data['at_time']);
|
||
}
|
||
}
|
||
|
||
$items = [];
|
||
foreach ($data['products'] as $bm_id => $v) {
|
||
$items[$bm_id] = $data['type_id'] == '921' ? $v['nums'] : (-1) * $v['nums'];
|
||
}
|
||
|
||
|
||
$adjustMain['items'] = $items;
|
||
list($res,$arr_msg) = $this->dealSave($adjustMain);
|
||
if(!$res){
|
||
return [false,$arr_msg['msg']];
|
||
}
|
||
return [true,'差异处理成功'];
|
||
}
|
||
} |