mirror of
https://gitee.com/ShopeX/OMS
synced 2026-03-22 18:35:35 +08:00
505 lines
22 KiB
PHP
505 lines
22 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 o2o_mdl_inventory extends dbeav_model{
|
||
|
||
var $export_name = '门店盘点表';
|
||
|
||
//csv字段标题定义
|
||
function io_title( $filter, $ioType='csv' ){
|
||
switch( $filter ){
|
||
case 'export':
|
||
$this->oSchema['csv'][$filter] = array(
|
||
'*:物料名称' => 'material_name',
|
||
'*:物料编码' => 'material_bn',
|
||
'*:规格' => 'spec_info',
|
||
'*:线上账面数' => 'accounts_num',
|
||
'*:共享账面数' => 'accounts_share_num',
|
||
);
|
||
break;
|
||
case 'branch':
|
||
$this->oSchema['csv'][$filter] = array(
|
||
'*:门店名称' => 'store_name',
|
||
'*:门店编码' => 'store_bn',
|
||
'*:盘点类型' => 'type',
|
||
'*:盘点申请人' => 'op_name',
|
||
);
|
||
break;
|
||
}
|
||
$this->ioTitle[$ioType][$filter] = array_keys( $this->oSchema[$ioType][$filter] );
|
||
return $this->ioTitle[$ioType][$filter];
|
||
}
|
||
|
||
//csv导出
|
||
function fgetlist_csv(&$data, $filter, $offset){
|
||
$post = $filter;
|
||
if ($post["selected_store_bn"] && $post["selected_store_bn"] != "_NULL_"){
|
||
//导出的完整数据数组
|
||
$data['content']['main'] = array();
|
||
//门店仓信息
|
||
$mdlO2oStore = app::get('o2o')->model('store');
|
||
$store_info = $mdlO2oStore->dump(array("store_bn"=>$post["selected_store_bn"]));
|
||
$data['content']['branch']['store_name'] = $store_info['name'];
|
||
$data['content']['branch']['store_bn'] = $store_info['store_bn'];
|
||
$data['content']['branch']['type'] = $this->get_inventory_type($post['inventory_type'],'key');
|
||
$data['content']['branch']['op_name'] = ''; //导出模板后自行填写
|
||
|
||
//导出数据第一行,门店仓相关信息标题
|
||
$title = array();
|
||
foreach( $this->io_title('branch') as $k => $v ){
|
||
$title[] = $this->charset->utf2local($v);
|
||
}
|
||
$data['content']['main'][] = '"'.implode('","',$title).'"';
|
||
|
||
//门店仓相关信息数据行
|
||
foreach( $this->oSchema['csv']['branch'] as $k => $v ){
|
||
$branchRow[$v] = $this->charset->utf2local( utils::apath( $data['content']['branch'],explode('/',$v) ) );
|
||
}
|
||
$data['content']['main'][] = '"'.implode('","',$branchRow).'"';
|
||
|
||
//盘点明细内容的标题行
|
||
$title = array();
|
||
foreach( $this->io_title('export') as $k => $v ){
|
||
$title[] = $this->charset->utf2local($v);
|
||
}
|
||
$data['content']['main'][] = '"'.implode('","',$title).'"';
|
||
|
||
if($post['inventory_type'] == 2){
|
||
//选择了全盘类型 显示所有与此门店相关的物料明细信息内容
|
||
$mdlO2oBranchProduct = app::get('o2o')->model('branch_product');
|
||
$rs_product = $mdlO2oBranchProduct->getList("*",array("branch_id"=>$store_info["branch_id"]));
|
||
if(!empty($rs_product)){
|
||
//先整体获取所有的bm_id
|
||
$bm_ids = array();
|
||
foreach ($rs_product as $var_product){
|
||
$bm_ids[] = $var_product["bm_id"];
|
||
}
|
||
//统一获取material_name和material_bn 与bm_id的关系
|
||
$mdlMaterialBasic = app::get('material')->model('basic_material');
|
||
$rs_material = $mdlMaterialBasic->getList("bm_id,material_bn,material_name",array("bm_id|in"=>$bm_ids));
|
||
$rl_bm_id_material_info = array();
|
||
foreach ($rs_material as $var_material){
|
||
$rl_bm_id_material_info[$var_material["bm_id"]] = array(
|
||
"material_bn" => $var_material["material_bn"],
|
||
"material_name" => $var_material["material_name"]
|
||
);
|
||
}
|
||
//统一获取spec_info规格 与bm_id的关系
|
||
$mdlMaterialBasicExt = app::get('material')->model('basic_material_ext');
|
||
$rs_material_ext = $mdlMaterialBasicExt->getList("bm_id,specifications",array("bm_id|in"=>$bm_ids));
|
||
$rl_bm_id_spec_info = array();
|
||
foreach ($rs_material_ext as $var_material_ext){
|
||
$rl_bm_id_spec_info[$var_material_ext["bm_id"]] = $var_material_ext["specifications"];
|
||
}
|
||
//统一获取accounts_num线上账面数和accounts_share_num共享账面数 与bm_id的关系
|
||
$mdlO2oInventoryItems = app::get('o2o')->model('inventory_items');
|
||
$rs_inventory_items = $mdlO2oInventoryItems->getList("bm_id,accounts_num,accounts_share_num",array("bm_id|in"=>$bm_ids));
|
||
if(!empty($rs_inventory_items)){
|
||
$rl_bm_id_inventory_items = array();
|
||
foreach ($rs_inventory_items as $var_inventory_item){
|
||
$rl_bm_id_inventory_items[$var_inventory_item["bm_id"]] = array(
|
||
"accounts_num" => $var_inventory_item["accounts_num"],
|
||
"accounts_share_num" => $var_inventory_item["accounts_share_num"],
|
||
);
|
||
}
|
||
}
|
||
//组明细内容
|
||
foreach ($rs_product as $f_var){
|
||
$row = array(
|
||
"material_name" => $rl_bm_id_material_info[$f_var["bm_id"]]["material_name"],
|
||
"material_bn" => $rl_bm_id_material_info[$f_var["bm_id"]]["material_bn"],
|
||
"spec_info" => $rl_bm_id_spec_info[$f_var["bm_id"]],
|
||
"accounts_num" => $rl_bm_id_inventory_items[$f_var["bm_id"]]["accounts_num"],
|
||
"accounts_share_num" => $rl_bm_id_inventory_items[$f_var["bm_id"]]["accounts_share_num"],
|
||
);
|
||
|
||
foreach( $this->oSchema['csv']['export'] as $k => $v ){
|
||
if ($v){
|
||
$pRow[$v] = $this->utf8togbk( utils::apath( $row,explode('/',$v) ) );
|
||
}else{
|
||
$pRow[$v] = '';
|
||
}
|
||
}
|
||
$data['content']['main'][] = '"'.implode('","',$pRow).'"';
|
||
}
|
||
}
|
||
}
|
||
|
||
return true;
|
||
|
||
}
|
||
}
|
||
|
||
function utf8togbk($s){
|
||
return iconv("UTF-8", "GBK//TRANSLIT", $s);
|
||
}
|
||
|
||
//准备导入
|
||
function prepared_import_csv(){
|
||
set_time_limit(0);
|
||
$this->ioObj->cacheTime = time();
|
||
$this->kvdata = '';
|
||
}
|
||
|
||
//准备导入 行
|
||
function prepared_import_csv_row($row,$title,&$tmpl,&$mark,&$newObjFlag,&$msg){
|
||
if (empty($row)){
|
||
//最后一次$row就是空的 这里做错误信息处理
|
||
//先判如果盘点类型是期初或者是部分盘的时候 csv填写的物料明细不能为空
|
||
$f_kvdata = $this->kvdata;
|
||
if ($this->flag){
|
||
if ($this->not_exist_product_bn){
|
||
$temp = $this->not_exist_product_bn;
|
||
$error_text = '\n数据库中不存在的商品货号:';
|
||
$msg['error'] = $this->get_import_error_msg($temp,$error_text,$msg['error']);
|
||
}
|
||
if ($this->not_exist_account_numbers){
|
||
$temp = $this->not_exist_account_numbers;
|
||
$error_text = '\n相应物料的线上账面数或者共享账面数不能为空:';
|
||
$msg['error'] = $this->get_import_error_msg($temp,$error_text,$msg['error']);
|
||
}
|
||
if ($this->not_exist_rl_branch_product){
|
||
$temp = $this->not_exist_rl_branch_product;
|
||
$error_text = '\n此门店仓和物料不存在供货关系:';
|
||
$msg['error'] = $this->get_import_error_msg($temp,$error_text,$msg['error']);
|
||
}
|
||
$this->kvdata = '';
|
||
return false;
|
||
}
|
||
if(in_array($f_kvdata["branch"]["contents"][0][2], array(1,3))){
|
||
//盘点类型是期初或部分盘 物料明细必须有值
|
||
if(!$f_kvdata["products"]["contents"]){
|
||
$msg['error'] .= '\n盘点类型是期初或部分盘时必须填写下面的物料信息。';
|
||
$this->kvdata = '';
|
||
return false;
|
||
}
|
||
}
|
||
//通过错误处理检查后返回true
|
||
return true;
|
||
}
|
||
|
||
$mark = false;
|
||
$fileData = $this->kvdata;
|
||
|
||
if( !$fileData ) $fileData = array();
|
||
|
||
if( substr($row[0],0,2) == '*:' ){
|
||
$titleRs = array_flip($row);
|
||
$mark = 'title';
|
||
return $titleRs;
|
||
}else{
|
||
$basicMaterialObj = app::get('material')->model('basic_material');
|
||
$mdlOmeBranch = app::get('ome')->model('branch');
|
||
$mdlO2oInventory = app::get('o2o')->model('inventory');
|
||
$mdlO2oBranchProduct = app::get('o2o')->model('branch_product');
|
||
if( $row[0] ){
|
||
if( array_key_exists( '*:物料名称',$title ) ){
|
||
//盘点货品处理
|
||
//先判断 线上账面数或者共享账面数不能为空
|
||
if($row[3] == "" || $row[4] == ""){
|
||
$this->flag = true;
|
||
$this->not_exist_account_numbers = isset($this->not_exist_account_numbers)?array_merge($this->not_exist_account_numbers,array($row[1])):array($row[1]);
|
||
}else{
|
||
//判断是否存在该物料
|
||
$product = $basicMaterialObj->dump(array('material_bn'=>trim($row[1])), 'bm_id');
|
||
if(!$product){
|
||
$this->flag = true;
|
||
$this->not_exist_product_bn = isset($this->not_exist_product_bn)?array_merge($this->not_exist_product_bn,array($row[1])):array($row[1]);
|
||
}else{
|
||
//判断物料是否与门店仓有关联关系
|
||
$rs_o2o_rl = $mdlO2oBranchProduct->dump(array("branch_id"=>$this->import_branch_id,"bm_id"=>$product["bm_id"]),'id');
|
||
if(!$rs_o2o_rl){
|
||
$this->flag = true;
|
||
$this->not_exist_rl_branch_product = isset($this->not_exist_rl_branch_product)?array_merge($this->not_exist_rl_branch_product,array($row[1])):array($row[1]);
|
||
}
|
||
$row['product_id'] = $product['bm_id'];
|
||
}
|
||
unset($product);
|
||
$fileData['products']['contents'][] = $row;
|
||
}
|
||
}else {
|
||
//盘点门店仓处理
|
||
$branch = $mdlOmeBranch->dump(array("branch_bn"=>$row["1"],"b_type"=>2),"branch_id,name");
|
||
if (!$branch){
|
||
$msg['error'] = "没有此门点仓:".$row[0];
|
||
unset($branch);
|
||
return false;
|
||
}
|
||
$branch_id = $branch['branch_id'];
|
||
$this->import_branch_id = $branch_id;
|
||
$fileData['branch']['branch_id'] = $branch_id;
|
||
$fileData['branch']['name'] = $branch['name'];
|
||
$inventory_type = $this->get_inventory_type($row[2],'value');
|
||
if(!$inventory_type){
|
||
$msg['error'] = "盘点类型无法标识";
|
||
return false;
|
||
}
|
||
if($inventory_type == "2"){
|
||
//全盘 判断是否有此门店仓未确认的全盘和部分盘的盘点单
|
||
$inv_exist2 = $mdlO2oInventory->dump(array("branch_id"=>$branch_id,"status"=>1,"inventory_type|in"=>array(2,3)),"inventory_id");
|
||
if($inv_exist2){
|
||
$msg['error'] = "此门店仓已有盘点方式为全盘或部分的盘点单存在,请确认后再导入";
|
||
unset($inv_exist2);
|
||
return false;
|
||
}
|
||
}else if($inventory_type == "3"){
|
||
//部分盘 判断是否有此门店仓未确认的全盘单
|
||
$inv_exist3 = $mdlO2oInventory->dump(array("branch_id"=>$branch_id,"status"=>1,"inventory_type"=>2),'inventory_id');
|
||
if($inv_exist3){
|
||
$msg['error'] = "请将此门店仓全盘确认后再新建部分盘点";
|
||
unset($inv_exist3);
|
||
return false;
|
||
}
|
||
}else if($inventory_type == "1"){
|
||
//期初
|
||
$branch_product = kernel::single('o2o_inventorylist')->check_product_iostock($branch_id);
|
||
if($branch_product){
|
||
$msg['error'] = "此门店仓已存在库存记录不可以期初盘点";
|
||
unset($branch_product);
|
||
return false;
|
||
}
|
||
$branch_inventory = kernel::single('o2o_inventorylist')->get_inventorybybranch_id($branch_id);
|
||
if($branch_inventory){
|
||
$msg['error'] = "此门店仓已有盘点单存在!";
|
||
unset($branch_inventory);
|
||
return false;
|
||
}
|
||
}
|
||
$row[2] = $inventory_type;
|
||
$fileData['branch']['contents'][] = $row;
|
||
}
|
||
$this->kvdata = $fileData;
|
||
}else {
|
||
$msg['error'] = "物料名称不能为空!";
|
||
return false;
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
//导入 获取数据 加入队列
|
||
function finish_import_csv(){
|
||
$data = $this->kvdata; unset($this->kvdata);
|
||
|
||
$oQueue = app::get('base')->model('queue');
|
||
$mdlO2oInventory = app::get('o2o')->model('inventory');
|
||
|
||
//每50个物料记录 一个队列
|
||
$number = $page = 0; $limit = 50;
|
||
|
||
//获取盘点申请人的ID
|
||
$op_id = 1;
|
||
$mdlDesktopUser = app::get('desktop')->model('users');
|
||
$user_name = trim($data['branch']['contents'][0][3]);
|
||
if($user_name){
|
||
$rs_user = $mdlDesktopUser->dump(array("name"=>$user_name),"user_id");
|
||
if(!empty($rs_user)){
|
||
$op_id = $rs_user["user_id"];
|
||
}
|
||
}
|
||
|
||
//盘点主表
|
||
$inv = array(
|
||
"inventory_bn" => $this->get_inventory_bn(),
|
||
"inventory_type" => $data['branch']['contents'][0][2],
|
||
"op_id" => $op_id,
|
||
"createtime" => time(),
|
||
"branch_id" => $data['branch']['branch_id'],
|
||
);
|
||
$re = $mdlO2oInventory->save($inv);
|
||
if($inv["inventory_type"] == "2"){
|
||
//全盘获取有库存的物料记录并补全 漏填物料记录线上账面数和共享账面数为0
|
||
$material_list = $this->get_import_material_list($data['branch']['branch_id'],$data['products']['contents']);
|
||
}else{
|
||
//期初 部分盘 拿csv填写的物料信息
|
||
$material_list = $data['products']['contents'];
|
||
}
|
||
|
||
$psdf['branch_id'] = $data['branch']['branch_id'];
|
||
$psdf['inv_id'] = $inv['inventory_id'];
|
||
|
||
$sdfs = array();
|
||
foreach ($material_list as $k => $v){
|
||
$sdf = array(
|
||
"accounts_num" => (int)trim($v[3]),
|
||
"accounts_share_num" => (int)trim($v[4]),
|
||
"bm_id" => $v["product_id"],
|
||
);
|
||
if ($number < $limit){
|
||
$number++;
|
||
}else{
|
||
$page++;
|
||
$number = 0;
|
||
}
|
||
$sdfs[$page][] = $sdf;
|
||
}
|
||
|
||
unset($data, $inv, $material_list);#销毁
|
||
|
||
foreach ($sdfs as $i){
|
||
$psdf['products'] = $i;
|
||
$queueData = array(
|
||
'queue_title'=>'门店盘点导入',
|
||
'start_time'=>time(),
|
||
'params'=>array(
|
||
'sdfdata'=>$psdf,
|
||
'app' => 'o2o',
|
||
'mdl' => 'inventory'
|
||
),
|
||
'worker'=>'o2o_inventory_import.run',
|
||
);
|
||
$oQueue->save($queueData);
|
||
}
|
||
$oQueue->flush();
|
||
|
||
return null;
|
||
}
|
||
|
||
//导入时组合错误信息
|
||
private function get_import_error_msg($temp,$error_test,&$error_msg){
|
||
$tmp = array_unique($temp); sort($tmp);
|
||
$error_msg .= $error_test;
|
||
$ms = ''; $tmp1 = array(); $tmp2 = array();
|
||
foreach ($tmp as $k => $v){
|
||
if ($k >= 10){
|
||
$ms = '...\n'; break;
|
||
}
|
||
if ($k < 5){
|
||
$tmp1[] = $v; continue;
|
||
}
|
||
$tmp2[] = $v;
|
||
}
|
||
$error_msg .= '\n'.implode(',', $tmp1);
|
||
if (!empty($tmp2)) $error_msg .= '\n'.implode(',', $tmp2);
|
||
$error_msg .= $ms;
|
||
return $error_msg;
|
||
}
|
||
|
||
//全盘导入时获取物料信息
|
||
private function get_import_material_list($branch_id,$products_contents){
|
||
$material_list = array();
|
||
$import_bm_ids = array();
|
||
foreach ($products_contents as $var_product){
|
||
$import_bm_ids[] = $var_product["product_id"];
|
||
$material_list[] = $var_product;
|
||
}
|
||
//如有遗漏的物料信息 则补全
|
||
$mdlO2oBranchProduct = app::get('o2o')->model('branch_product');
|
||
$rs_product = $mdlO2oBranchProduct->getList("bm_id",array("branch_id"=>$branch_id,"bm_id|notin"=>$import_bm_ids));
|
||
if(!empty($rs_product)){
|
||
foreach ($rs_product as $var_p){
|
||
$temp_arr = array(
|
||
"3" => 0, //线上账面数
|
||
"4" => 0, //共享账面数
|
||
"product_id" => $var_p["bm_id"],
|
||
);
|
||
$material_list[] = $temp_arr;
|
||
}
|
||
}
|
||
return $material_list;
|
||
}
|
||
|
||
|
||
//$search是'key'时$inventory_type传1/2/3来获取$type的value 如$search是默认value时$inventory_type传期初/全盘/部分盘 来获取$type的key
|
||
function get_inventory_type($inventory_type,$search="value"){
|
||
$type = array (
|
||
'1' => '期初',
|
||
'2' => '全盘',
|
||
'3' => '部分盘',
|
||
);
|
||
if($search=='key'){
|
||
return $type[$inventory_type];
|
||
}else{
|
||
$result = array_search($inventory_type,$type);
|
||
return $result;
|
||
}
|
||
}
|
||
|
||
//生成盘点单号
|
||
function get_inventory_bn(){
|
||
$head = "MDPD";
|
||
$rand4 = rand(1,9999);
|
||
$current_date = date('ymdHis');
|
||
$inventory_bn = "MDPD".$current_date.str_pad($rand4,4,'0',STR_PAD_LEFT);
|
||
return $inventory_bn;
|
||
}
|
||
|
||
//盘点类型
|
||
function modifier_inventory_type($row){
|
||
switch ($row){
|
||
case "1":
|
||
$inventory_type = "期初";
|
||
break;
|
||
case "2":
|
||
$inventory_type = "全盘";
|
||
break;
|
||
case "3":
|
||
$inventory_type = "部分盘";
|
||
break;
|
||
}
|
||
return $inventory_type;
|
||
}
|
||
|
||
//盘点时间
|
||
function modifier_confirm_time($row){
|
||
if(!$row){
|
||
return "-";
|
||
}else{
|
||
return date("Y-m-d H:i:s",$row);
|
||
}
|
||
}
|
||
|
||
//状态
|
||
function modifier_status($row){
|
||
switch ($row){
|
||
case "1":
|
||
$status = "未确认";
|
||
break;
|
||
case "2":
|
||
$status = "已确认";
|
||
break;
|
||
case "3":
|
||
$status = "作废";
|
||
break;
|
||
}
|
||
return $status;
|
||
}
|
||
|
||
|
||
//扩展字段先定义
|
||
function extra_cols(){
|
||
return array(
|
||
'column_store_name' => array('label'=>'门店名称','width'=>'150','func_suffix'=>'store_name',"order"=>"5"),
|
||
'column_op_name' => array('label'=>'申请人','width'=>'80','func_suffix'=>'op_name',"order"=>"15"),
|
||
'column_confirm_op_name' => array('label'=>'盘点人','width'=>'80','func_suffix'=>'confirm_op_name',"order"=>"20"),
|
||
);
|
||
}
|
||
|
||
function extra_store_name($rows){
|
||
return kernel::single('o2o_extracolumn_inventory_storename')->process($rows);
|
||
}
|
||
|
||
function extra_op_name($rows){
|
||
return kernel::single('o2o_extracolumn_inventory_opname')->process($rows);
|
||
}
|
||
|
||
function extra_confirm_op_name($rows){
|
||
return kernel::single('o2o_extracolumn_inventory_confirmopname')->process($rows);
|
||
}
|
||
|
||
} |