*/
class inventorydepth_ctl_shop_adjustment extends desktop_controller {
var $workground = 'resource_center';
var $defaultWorkground = 'resource_center';
function __construct($app)
{
parent::__construct($app);
}
/**
* 调整 列表
*
* @return void
* @author
**/
public function index($source = '')
{
$base_filter = array();
if($_POST['shop_id']) {
$shop_id = $_POST['shop_id'];
}elseif($_GET['shop_id']) {
$shop_id = $_GET['shop_id'];
} elseif($_GET['filter']['shop_id']) {
$shop_id = $_GET['filter']['shop_id'];
} elseif($_COOKIE['adj_shop_id']) {
$shop_id = $_COOKIE['adj_shop_id'];
}
$shopdata = app::get('ome')->model('shop')->getList('shop_id,name', ['node_id|noequal'=>'','delivery_mode'=>'self']);
if(empty($shop_id) && $shopdata) {
$shop_id = $shopdata[0]['shop_id'];
}
if(empty($shop_id)) {
$shop_id = 0;
}
$base_filter['shop_id'] = $shop_id;
$shop = $this->app->model('shop')->getList('name', array('shop_id'=>$shop_id));
$title = "" .$shop[0]['name']."在售库存管理";
if ($source != 'stock') {
$back = '返回列表';
$title = $back . $title;
}
$extra_view = array(
'inventorydepth' => 'admin/show.html',
);
$this->pagedata['shopdata']= $shopdata;
$this->pagedata['shop_id']= $shop_id;
$params = array(
'title' => $title,
'actions' => array(
0 => array('label'=>$this->app->_('批量开启回写库存'),'submit'=>'index.php?app=inventorydepth&ctl=shop_skus&act=set_request&p[0]=true','target'=>'refresh'),
1 => array('label'=>$this->app->_('批量关闭回写库存'),'submit'=>'index.php?app=inventorydepth&ctl=shop_skus&act=set_request&p[0]=false','target'=>'refresh'),
2 => array('label'=>$this->app->_('发布库存'),'submit'=>'index.php?app=inventorydepth&ctl=shop_adjustment&act=releasePage','target'=>'dialog::{title:\'批量发布\'}'),//弃用
//3 => array('label'=>$this->app->_('导出发布库存模板'),'submit'=>'index.php?app=inventorydepth&ctl=shop_adjustment&act=export_data&view='.$_GET["view"].'&p[0]=release_stock','target'=>'_blank'),
//4 => array('label'=>$this->app->_('导入发布库存'),'href'=>'index.php?app=inventorydepth&ctl=shop_adjustment&act=index&action=import','target' => 'dialog::{width:400,height:150,title:\'导入发布库存\'}'),
//6 => array('label'=>$this->app->_('批量发布'),'submit'=>'index.php?app=inventorydepth&ctl=shop_adjustment&act=displayBatchRelease','target'=>'dialog::{width:690,height:200,title:\'批量发布 (只处理已匹配SKU)\'}'),
),
'use_buildin_recycle' => false,
'use_buildin_filter' => true,
'use_buildin_export' => true,
'base_filter' => $base_filter,
'top_extra_view' => $extra_view,
'orderBy' => 'request asc',
'object_method' => array(
'count'=>'count',
'getlist'=>'getFinderList',
),
);
if($_GET['view'] == 2){
$params['actions'][5] = array('label' => '批量转换生成物料', 'submit'=>'index.php?app=inventorydepth&ctl=shop_adjustment&act=batchGenMaterial','target'=>'dialog::{width:690,height:200,title:\'批量恢复\'}');
}
if (kernel::single('desktop_user')->has_permission('shop_adjustment_delete')) {
$params['actions'][6] = array(
'label' => app::get('ome')->_('批量删除'),
'submit' => 'index.php?app=inventorydepth&ctl=shop_adjustment&act=batch_delete&finder_id='.$_GET['finder_id'],
'target' => "dialog::{width:500,height:200,title:'批量删除'}",
);
}
$this->pagedata['benchobj'] = kernel::single('inventorydepth_stock')->get_benchmark();
$this->pagedata['calculation'] = kernel::single('inventorydepth_math')->get_calculation();
$this->pagedata['res_full_url'] = $this->app->res_full_url;
$this->finder('inventorydepth_mdl_shop_adjustment',$params);
}
/**
* 列表TAB页
*
* @return void
* @author
**/
public function _views()
{
$lib_inventorydepth_shop_skus = kernel::single("inventorydepth_shop_skus");
$views = $lib_inventorydepth_shop_skus->get_shop_adjustment_views_arr();
$skusModel = $this->app->model('shop_adjustment');
foreach ($views as $key=>&$view) {
$view['filter']['shop_id'] = $_POST['shop_id'] ? $_POST['shop_id']: ($_GET['shop_id'] ?: $_SESSION['shop_id']);
$view['addon'] = $skusModel->count($view['filter']);
$view['href'] = 'index.php?app=inventorydepth&ctl=shop_adjustment&act=index&view='.$key.'&shop_id='.$view['filter']['shop_id'];
}
return $views;
}
/**
* 保存公式
*
* @return void
* @author
**/
public function saveFormula()
{
$this->begin();
if ($_POST['heading'] == ''){
$this->end(false,$this->app->_('编号或者中文标识不能为空'));
}
$formulaModel = $this->app->model('formula');
$is_exist = $formulaModel->select()->columns('formula_id')
->where('heading=?',$_POST['heading'])
->instance()->fetch_row();
if ($is_exist) {
$this->end(false,$this->app->_('公式名已经存在!'));
}
$data['style'] = 'stock';
// $data['bn'] = $_POST['bn'];
$data['heading'] = $_POST['heading'];
$data['content'] = array(
// 'benchmark' => $_POST['benchmark'],
// 'calculation' => $_POST['calculation'],
// 'increment' => $_POST['increment'],
'result' => $_POST['result']
);
$data['operator'] = $this->user->get_id();
$data['operator_ip'] = kernel::single('base_component_request')->get_remote_ip();
$result = $this->app->model('formula')->insert($data);
$this->end($result);
}
/**
* 执行公式 弃用
*
* @return void
* @author
**/
public function execFormula()
{
$this->begin();
if (!$_POST['id']) {
$this->end(false,$this->app->_('请选择店铺商品'));
}
$result = $_POST['result'];unset($_POST['result']);
if (!$result) {
$this->end(false,$this->app->_('先填写公式'));
}
# 验证公式
$errormsg = array();
$rs = kernel::single('inventorydepth_stock')->formulaRun($result, array(), $errormsg);
if ($rs === false) {
$this->end(false, $errormsg);
}
# 执行公式
kernel::single('inventorydepth_stock')->updateReleaseByformula($_POST,$result,$errormsg);
$msg = $errormsg ? 'javascript:alert("修改失败:'.implode("\n", $errormsg).'");' : '修改成功';
$result = $errormsg ? false : true;
$this->end($result,$msg);
}
/**
* 公式列表
*
* @return void
* @author
**/
public function listFormula($pageno = 1)
{
$pagelimit = 10;
$formulaModel = $this->app->model('formula');
$PG['list'] = $formulaModel->getList('*',array('style'=>'stock'),($pageno-1)*$pagelimit,$pagelimit);
$count = $formulaModel->count(array('style'=>'stock'));
$total_page = ceil($count/$pagelimit);
$pager = $this->ui()->pager(array(
'current'=>$pageno,
'total'=>$total_page,
'link'=>'index.php?app=inventorydepth&ctl=shop_adjustment&act=listFormula&p[0]=%d',
));
$this->pagedata = $PG;
$this->pagedata['pager'] = $pager;
$this->pagedata['count'] = $count;
$this->pagedata['pagelimit'] = $pagelimit;
$this->display('shop/adjustment/stock/list_formula.html');
}
/**
* 删除公式
*
* @return void
* @author
**/
public function delFormula()
{
$this->begin();
if (!$_POST) {
$this->end(false,$this->app->_('请选择公式'));
}
$result = $this->app->model('formula')->delete($_POST);
$this->end($result);
}
/**
* 更新发布库存
*
* @return void
* @author
**/
public function update_release_stock()
{
$this->begin();
if (!$_POST['id'] || !isset($_POST['release_stock'])) {
$this->end(false,$this->app->_('参数错误!'));
}
if (!(is_numeric($_POST['release_stock']) && $_POST['release_stock']>=0)) {
$this->end(false,'发布库存必须是非负数值型!');
}
$mdl = $this->app->model('shop_adjustment');
$filter = ['id'=>$_POST['id']];
$info = $mdl->db_dump($filter);
$result = $mdl->update(array('release_stock'=>(int)$_POST['release_stock'],'release_status'=>'sleep'),$filter);
$operInfo = kernel::single('inventorydepth_func')->getDesktopUser();
$optLogModel = app::get('inventorydepth')->model('operation_log');
$optLogModel->write_log('sku',$_POST['id'],'edit','更新发布库存:'.$info['release_stock'].'->'.$_POST['release_stock'],$operInfo);
$this->end($result);
}
/**
* 发布页
*
* @return void
* @author
**/
public function releasePage($id = null,$release_stock = null)
{
if ($_POST['isSelectedAll'] == '_ALL_') {
echo '
不支持全部货品发布!!!
';exit;
} elseif ( $_POST['id'] ) {
$way = 'batch';
}elseif($id){
$way = 'single';
$_POST['id'] = $id;
# 发布库存超出可售库存提示
$sku = $this->app->model('shop_adjustment')->select()->columns('shop_product_bn,shop_id,shop_bn,release_stock')
->where('id=?',$id)->instance()->fetch_row();
$delivery_mode = app::get('ome')->model('shop')->db_dump(['shop_id'=>$sku['shop_id']], 'delivery_mode')['delivery_mode'];
if($delivery_mode == 'shopyjdf') {
$products = app::get('dealer')->model('sales_material')->getList('sm_id,sales_material_name,sales_material_bn,sales_material_type,shop_id',array('sales_material_bn'=>$sku['shop_product_bn'], 'shop_id'=>$sku['shop_id']));
} else {
$products = app::get('material')->model('sales_material')->getList('sm_id,sales_material_name,sales_material_bn,sales_material_type,shop_id',array('sales_material_bn'=>$sku['shop_product_bn']));
}
kernel::single('inventorydepth_calculation_basicmaterial')->init($products);
kernel::single('inventorydepth_calculation_salesmaterial')->init($products);
# 可售库存
$stockCalLib = kernel::single('inventorydepth_calculation_salesmaterial');
list($actual_stock, ) = $stockCalLib->get_actual_stock($sku);
if ( is_numeric($release_stock) && $release_stock>=0 ) {
$sku['release_stock'] = $release_stock;
}
$_POST['release_stock'] = $sku['release_stock'];
$this->pagedata['warning'] = ($sku['release_stock'] > $actual_stock) ? true : false;
}
if ($_POST) {
$post = http_build_query($_POST);
$this->pagedata['post'] = $post;
}
# 发布库存覆盖店铺库存
//$this->app->model('shop_adjustment')->convert_shop_stock($_POST);
$this->pagedata['way'] = $way;
$this->display('shop/adjustment/release/show.html');
}
/**
* 单个发布
*
* @return void
* @author
**/
public function singleRelease()
{
$this->begin();
$id = $_POST['id'];
if (!$id) {
$this->end(false,$this->app->_('参数错误!'));
}
$sku = $this->app->model('shop_adjustment')
->select()->columns('id,shop_id,release_stock,shop_product_bn,mapping,request,shop_type,shop_sku_id,shop_iid')
->where('id=?',$id)
->instance()->fetch_row();
if(!$sku) $this->end(false,$this->app->_('货品不存在!'));
// 获取商品条码
// $barcode = kernel::single('material_codebase')->getBarcodeBySmbn($sku['shop_product_bn'], $sku['shop_id'], 1);
$memo = array('last_modified'=>time());
$stocks[$sku['id']] = array(
'bn' => $sku['shop_product_bn'],
'quantity' => (is_numeric($_POST['release_stock']) && $_POST['release_stock']>=0) ? $_POST['release_stock'] : $sku['release_stock'],
'memo' => json_encode($memo),
'sku_id' => $sku['shop_sku_id'],
'num_iid' => $sku['shop_iid'],
'barcode' => $sku['shop_sku_id'],
);
// 查询增量库存
if (kernel::single('inventorydepth_sync_set')->isModeSupportInc($sku['shop_type'])) {
$stockLogMdl = app::get('ome')->model('api_stock_log');
$last_quantity = $stockLogMdl->getLastStockLog($sku['shop_id'], $sku['shop_product_bn']);
if ($last_quantity) {
$stocks[$sku['id']]['inc_quantity'] = $stocks[$sku['id']]['quantity'] - $last_quantity['store'];
}
}
$res = kernel::single('inventorydepth_shop')->doStockRequest($stocks,$sku['shop_id'],true);
// 记录操作日志
$optLogModel = app::get('inventorydepth')->model('operation_log');
$optLogModel->write_log('sku',$id,'stockup','单个发布库存:'.$stocks[$sku['id']]['quantity']);
$this->end(true,$this->app->_('发布中'), null, $res);
}
/**
* 批量发布
*
* @return void
* @author
**/
public function batchRelease()
{
$this->begin();
if (!$_POST) {
$this->end(false,$this->app->_('请选择店铺商品!'));
}
$adjustmentModel = $this->app->model('shop_adjustment');
/*
$_POST['request'] = 'false';
$row = $adjustmentModel->getList('id',$_POST,0,1);
if ($row) {
$this->end(false,$this->app->_('存在不允许回写的货品!'));
}
unset($_POST['request']);*/
$_POST['mapping'] = '0';
$row = $adjustmentModel->getList('id',$_POST,0,1);
if ($row) {
$this->end(false,$this->app->_('存在未匹配的货品!'));
}
unset($_POST['mapping']);
$adjustmentModel->appendCols = '';
$shops = $adjustmentModel->getList('distinct shop_id,shop_name',$_POST);
foreach ($shops as $key => $shop) {
$offset = 0; $limit = 50; $_POST['shop_id'] = $shop['shop_id'];
$params = $_POST; $params['limit'] = $limit;
// 操作员信息
$params['operInfo'] = kernel::single('inventorydepth_func')->getDesktopUser();
$count = $adjustmentModel->count($_POST);
if($count<=0) continue;
$title = "批量店铺【{$shop['shop_name']}】库存回写";
$total = floor($count/$limit);
for ($i=$total; $i>=0 ; $i--) {
$params['offset'] = $i*$limit;
# 插入队列
kernel::single('inventorydepth_queue')->insert_release_queue($title,$params);
}
}
$this->end(true,$this->app->_('成功插入队列!'));
}
/**
* @description 更新店铺所有货品库存
* @access public
* @param void
* @return void
*/
public function uploadPage($shop_id)
{
if ( !$shop_id ) {
$this->pagedata['error'] = '请先选择店铺!!!';
} else {
$shop = $this->app->model('shop')->select()->columns('*')->where('shop_id=?',$shop_id)->instance()->fetch_row();
if ( !$shop ) {
$this->pagedata['error'] = '店铺不存在!!!';
} elseif (!$shop['node_id']) {
$this->pagedata['error'] = '店铺【'.$shop['shop_bn'].'】未绑定';
}
//判断店铺当前是否有队列任务在执行
$queue_title = '批量店铺【' . $shop['name'] . '】库存回写';
$queueRow = app::get('base')->model('queue')->getList('queue_id,params', array('queue_title'=>$queue_title), 0, 1);
if($queueRow){
$this->pagedata['error'] = '该店铺【'.$shop['name'].'】有库存回写队列任务在执行,请稍后更新商品库存。';
}
}
$this->pagedata['shop'] = $shop;
$this->display('shop/adjustment/stock/upload.html');
}
/**
* @description
* @access public
* @param void
* @return void
*/
public function batchUpload($shop_id)
{
$salesMaterialObj = app::get('material')->model('sales_material');
set_time_limit(0);
$this->begin();
if ( !$shop_id ) {
$this->end(false,'请先选择店铺!!!');
}
$shop = $this->app->model('shop')->select()->columns('*')->where('shop_id=?',$shop_id)->instance()->fetch_row();
if ( !$shop ) {
$this->end(false,'店铺不存在!!!');
} elseif (!$shop['node_id']) {
$this->end(false,'店铺【'.$shop['shop_bn'].'】未绑定');
}
$skutype = $_POST['skutype'];
//skutype==2是仅店铺销售物料
if ($skutype == '2') {
$shopSkuMdl = app::get('inventorydepth')->model('shop_skus');
$count = $shopSkuMdl->count(array('shop_id' => $shop_id, 'mapping' => '1'));
} else {
$count = $salesMaterialObj->count(array('is_bind' => 1, 'shop_id' => array($shop_id, '_ALL_')));
}
if($count<=0) {
$this->end(false,'无商品,请先在淘管中添加商品!!!');
}
$title = "批量店铺【{$shop['name']}】库存回写";
$offset = 0; $limit = 50; $total = floor($count/$limit);
$params = array('shop_id'=>$shop_id,'limit'=>$limit, 'skutype' => $skutype);
for ($i=$total; $i>=0 ; $i--) {
$params['offset'] = $i*$limit;
# 插入队列
kernel::single('inventorydepth_queue')->insert_stock_update_queue($title,$params);
}
// 记录操作日志
$optLogModel = $this->app->model('operation_log');
$optLogModel->write_log('shop',$shop_id,'stockup','批量全局库存回写');
$this->end(true,$this->app->_('成功插入队列!'));
}
public function exportTemplate(){
$filename = "店铺商品分配模板".date('Y-m-d').".csv";
$encoded_filename = urlencode($filename);
$encoded_filename = str_replace("+", "%20", $encoded_filename);
$ua = $_SERVER["HTTP_USER_AGENT"];
header("Content-Type: text/csv");
if (preg_match("/MSIE/", $ua)) {
header('Content-Disposition: attachment; filename="' . $encoded_filename . '"');
} else if (preg_match("/Firefox$/", $ua)) {
header('Content-Disposition: attachment; filename*="utf8\'\'' . $filename . '"');
} else {
header('Content-Disposition: attachment; filename="' . $filename . '"');
}
header('Cache-Control:must-revalidate,post-check=0,pre-check=0');
header('Expires:0');
header('Pragma:public');
$pObj = $this->app->model('shop_adjustment');
$title = $pObj->exportTemplate('title');
echo '"'.implode('","',$title).'"';
}
/**
* 读取发布后的状态
*
* @return void
* @author
**/
public function getResult()
{
$id = $_POST['id'];
if(!$id) $this->splash('error',null,$this->app->_('数据为空!'));
$adjustmentModel = $this->app->model('shop_adjustment');
$release_status = $adjustmentModel->select()->columns('release_status')
->where('id=?',$id)->instance()->fetch_one();
if ($release_status == 'success') {
$this->splash('finish',null,$this->app->_('发布成功'));
}elseif($release_status == 'fail'){
$this->splash('finish',null,$this->app->_('发布失败'));
}else{
$this->splash('running',null,$this->app->_('运行中'));
}
}
/**
* @description 获取货品的应用规则
* @access public
* @param String $id
* @return void
*/
public function getApplyRegu($id)
{
if(!$id){ echo '';exit;}
$sku = $this->app->model('shop_adjustment')->getList('shop_product_bn,bind,shop_id,shop_bn',array('id'=>$id),0,1);
if(!$sku){ echo ''; exit;}
$sku = $sku[0];
if ($sku['bind'] == '1') { //促销
$rr = [];
}elseif($sku['bind'] == '2'){ //多选一
$rr = [];
}else{ //普通
$rr = kernel::single('inventorydepth_logic_stock')->getExecRegu($sku['shop_product_bn'],$sku['shop_id'],$sku['shop_bn']);
}
echo <<{$rr['heading']}
EOF;
}
/**
* @description 获取前端店铺库存
* @access public
* @param void
* @return void
*/
public function getShopStock()
{
$iids = $_POST['iid'];$shop_id = $_POST['shop_id']; $shop_bn = $_POST['shop_bn'];$shop_type=$_POST['shop_type'];
if( !$iids || !$shop_id || !$shop_bn) {
$result = array('status'=>'fail','msg'=>'参数为空!');
echo json_encode($result);exit;
}
$shop = $this->app->model('shop')->dump(array('shop_id'=>$shop_id));
$shopfactory = inventorydepth_service_shop_factory::createFactory($shop['shop_type'],$shop['business_type']);
if ($shopfactory === false) {
$result = array('status'=>'fail','msg'=>'店铺类型有误!');
echo json_encode($result);exit;
}
$result = $shopfactory->downloadByIIds($iids,$shop_id,$errormsg);
if (empty($result)) {
$result = array('status'=>'fail','msg'=>$errormsg);
echo json_encode($result);exit;
}
foreach ($result as $r) {
if ($r['skus']) {
foreach ($r['skus']['sku'] as $sku) {
$items[] = array(
'iid' => strval($r['iid']),
'sku_id' => $sku['sku_id'],
'num' => $sku['quantity'],
'id' => md5($shop_id.$r['iid'].$sku['sku_id']),
);
}
} else {
$items[] = array(
'iid' => strval($r['iid']),
'num' => $r['num'],
'id' => md5($shop_id.$r['iid']),
);
}
}
$result = array('status'=>'succ','data'=>$items);
echo json_encode($result);exit;
}
/**
* @description 获取发布库存
* @access public
* @param void
* @return void
*/
public function getReleaseStock()
{
$salesMaterialObj = app::get('material')->model('sales_material');
$salesMLib = kernel::single('material_sales_material');
$ids = $_POST['ids'];$shop_id = $_POST['shop_id']; $shop_bn = $_POST['shop_bn'];
if( !$ids || !$shop_id || !$shop_bn) {
$result = array('status'=>'fail','msg'=>'参数为空!');
echo json_encode($result);exit;
}
$adjustmentModel = $this->app->model('shop_adjustment');
$skus = $adjustmentModel->getList('shop_product_bn,bind,shop_id,shop_bn,id,mapping',array('id'=>$ids));
$pbns = [];
foreach ($skus as $sku) {
$pbns[] = $sku['shop_product_bn'];
}
//[普通]销售物料
$delivery_mode = app::get('ome')->model('shop')->db_dump(['shop_id'=>$shop_id], 'delivery_mode')['delivery_mode'];
if($delivery_mode == 'shopyjdf') {
$products = app::get('dealer')->model('sales_material')->getList('sm_id,sales_material_name,sales_material_bn,sales_material_type,shop_id',array('sales_material_bn'=>$pbns, 'shop_id'=>$shop_id));
} else {
$products = $salesMaterialObj->getList('sm_id,sales_material_name,sales_material_bn,sales_material_type,shop_id,class_id',array('sales_material_bn'=>$pbns));
$products = array_column($products, null, 'sales_material_bn');
}
if(!$products){
$result = array('status'=>'fail','msg'=>'无关联货号!');
echo json_encode($result);exit;
}
kernel::single('inventorydepth_calculation_basicmaterial')->init($products);
kernel::single('inventorydepth_calculation_salesmaterial')->init($products);
$data = array();
foreach ($skus as $sku) {
// 发布库存
$stock = kernel::single('inventorydepth_logic_stock')->getStock($products[$sku['shop_product_bn']],$sku['shop_id'],$sku['shop_bn']);
$quantity = $stock['quantity'];
$actual_stock = $stock['actual_stock'];
$asRs = $stock['regulation']['detail']['可售库存']['info'];
if ($actual_stock === false) continue;
// 详情
$actual_product_stock = array();
foreach ($asRs['basic'] as $bn => $bcRs) {
$actual_product_stock[] = array(
'bn'=>$bn,
'stock'=>$bcRs['quantity'],
'detail'=>json_encode($bcRs['info'], JSON_UNESCAPED_UNICODE),
);
}
if ($quantity !== false) {
$adjustmentModel->update(array('release_stock'=>$quantity),array('id'=>$sku['id']));
}
if ($sku['mapping'] =='1') {
$reguhtml = <<{$stock['regulation']['规则名称']}
EOF;
} else {
$reguhtml = '-';
}
$data[] = array(
'id' => $sku['id'],
'quantity' => $quantity,
'actual_stock' => $sku['mapping']=='1' ? $actual_stock : '-',
'actual_product_stock'=>$actual_product_stock,
'reguhtml' => $reguhtml,
);
}
$result = array('status'=>'succ','data'=>$data);
echo json_encode($result);exit;
}
function trans(){
$sku_id = $_GET['sku_id'];
$shop_id = $_GET['shop_id'];
$sku_info = $this->app->model('shop_skus')->dump(array('shop_sku_id'=>$sku_id,'shop_id'=>$shop_id),'*');
#默认基础物料条码
$sku_info['shop_barcode'] = ($sku_info['shop_barcode'] ? $sku_info['shop_barcode'] : $sku_info['shop_product_bn']);
$this->pagedata['shop_sku_info'] = $sku_info;
$shopObj = app::get('ome')->model('shop');
$shopList = $shopObj->getList('shop_id,name', array(), 0, -1);
array_unshift($shopList,array('shop_id'=>'_ALL_','name'=>'全部店铺'));
$this->pagedata['shops'] = $shopList;
#获取物料品牌
$brand_obj = app::get('ome')->model('brand');
$brands = $brand_obj->getList('brand_id,brand_name', array());
$this->pagedata['material_brand'] = $brands;
#获取物料分类
$goods_type_obj = app::get('ome')->model('goods_type');
$goods_types = $goods_type_obj->getList('type_id,name', array());
$this->pagedata['goods_types'] = $goods_types;
$this->display('shop/adjustment/trans_material.html');
}
/**
* 基础物料新增提交方法
*
* @param Post
* @return Boolean
*/
function toAdd($single=true){
if($single){
$this->begin('index.php?app=inventorydepth&ctl=shop_adjustment&act=index&filter[shop_id]='.$_POST['shop_id']);
}
//根据类型判断如果是自动的就自动生成基础物料,失败则提示
if($_POST['sales_material_type'] != 2 && $_POST['sales_material_type'] != 5 && $_POST['gen_mode'] == 1){
if(!($bm_id = $this->autoGenBasicMaterial($_POST, $err_msg))){
if($single){
$this->end(false, $err_msg);
}else{
return false;
}
}else{
$_POST['bm_id'] = $bm_id;
}
}
if(!$this->checkAddParams($_POST, $err_msg)){
if($single){
$this->end(false, $err_msg);
}else{
return false;
}
}
$salesMaterialObj = app::get('material')->model('sales_material');
$salesMaterialExtObj = app::get('material')->model('sales_material_ext');
$salesMaterialShopFreezeObj = app::get('material')->model('sales_material_shop_freeze');
//保存物料主表信息
$addData = array(
'sales_material_name' => $_POST['sales_material_name'],
'sales_material_bn' => $_POST['sales_material_bn'],
'sales_material_bn_crc32' => $_POST['sales_material_bn_crc32'],
'sales_material_type' => $_POST['sales_material_type'],
'shop_id' => $_POST['shop_id'],
'create_time' => time(),
);
$is_save = $salesMaterialObj->save($addData);
if($is_save){
$is_bind = false;
//如果有关联物料就做绑定操作
$salesBasicMaterialObj = app::get('material')->model('sales_basic_material');
//普通销售物料关联
if(($_POST['sales_material_type'] == 1 || $_POST['sales_material_type'] == 3) && !empty($_POST['bm_id'])){
$addBindData = array(
'sm_id' => $addData['sm_id'],
'bm_id' => $_POST['bm_id'],
'number' => 1,
);
$salesBasicMaterialObj->insert($addBindData);
$is_bind = true;
}elseif($_POST['sales_material_type'] == 2 && !empty($_POST['at'])){
//促销销售物料关联
foreach($_POST['at'] as $k=>$v){
$addBindData = array(
'sm_id' => $addData['sm_id'],
'bm_id' => $k,
'number' => $v,
'rate' => $_POST['pr'][$k],
);
$salesBasicMaterialObj->insert($addBindData);
$addBindData = null;
}
$is_bind = true;
}elseif($_POST['sales_material_type'] == 5 && !empty($_POST['sort'])){ //多选一
$mdl_ma_pickone_ru = app::get('material')->model('pickone_rules');
$select_type = $_POST["pickone_select_type"] ? $_POST["pickone_select_type"] : 1; //默认“随机”
foreach($_POST['sort'] as $key_bm_id => $val_sort){
$current_insert_arr = array(
"sm_id" => $addData['sm_id'],
"bm_id" => $key_bm_id,
"sort" => $val_sort ? $val_sort: 0,
"select_type" => $select_type,
);
$mdl_ma_pickone_ru->insert($current_insert_arr);
}
$is_bind = true;
}
//如果有绑定物料数据,设定销售物料为绑定状态
if($is_bind){
$salesMaterialObj->update(array('is_bind'=>1),array('sm_id'=>$addData['sm_id']));
}
//保存销售物料扩展信息
$addExtData = array(
'sm_id' => $addData['sm_id'],
'cost' => $_POST['cost'] ? $_POST['cost'] : 0.00,
'retail_price' => $_POST['retail_price'] ? $_POST['retail_price'] : 0.00,
'weight' => $_POST['weight'] ? $_POST['weight'] : 0.00,
'unit' => $_POST['unit'],
);
$salesMaterialExtObj->insert($addExtData);
//保存销售物料店铺级冻结
if($_POST['shop_id'] != '_ALL_'){
$addStockData = array(
'sm_id' => $addData['sm_id'],
'shop_id' => $_POST['shop_id'],
'shop_freeze' => 0,
);
$salesMaterialShopFreezeObj->insert($addStockData);
}
//更新当前店铺商品与erp本地关联
if($_POST['sales_material_type'] == 2){ //捆绑
$bind = 1;
}elseif($_POST['sales_material_type'] == 5){ //多选一
$bind = 2;
}else{
$bind = 0;
}
$this->app->model('shop_skus')->update(array('mapping'=>'1', 'bind'=>$bind),array('shop_sku_id'=>$_POST['shop_sku_id'],'shop_id'=>$_POST['shop_id']));
if($single){
$this->end(true, '操作成功');
}else{
return true;
}
}else{
if($single){
$this->end(false, '保存失败');
}else{
return false;
}
}
}
/**
* 销售物料新增时的参数检查方法
*
* @param Array $params
* @param String $err_msg
* @return Boolean
*/
function checkAddParams(&$params, &$err_msg){
if(empty($params['sales_material_name']) || empty($params['sales_material_bn'])){
$err_msg ="必填信息不能为空";
return false;
}
$salesMaterialObj = app::get('material')->model('sales_material');
$salesMaterialInfo = $salesMaterialObj->getList('sales_material_bn',array('sales_material_bn'=>$params['sales_material_bn']));
if($salesMaterialInfo){
$err_msg ="当前新增的物料编码已被使用,不能重复";
return false;
}
$params['sales_material_bn_crc32'] = sprintf('%u',crc32($params['sales_material_bn']));
if($params['sales_material_type'] == 2){
if(!isset($params['at'])){
$err_msg ="促销物料请至少设置一个物料明细内容";
return false;
}
foreach ($params['at'] as $val){
if (count($params['at']) == 1){
if ($val <2){
$err_msg ="只有一种物料时,数量必须大于1";
return false;
}
}else {
if ($val < 1){
$err_msg ="数量必须大于0";
return false;
}
}
}
foreach ($params['pr'] as $val){
$tmp_rate +=$val;
}
if($tmp_rate > 100){
$err_msg ="分摊销售价合计百分比:".$tmp_rate.",已超100%";
return false;
}elseif($tmp_rate < 100){
$err_msg ="分摊销售价合计百分比:".$tmp_rate.",不足100%";
return false;
}
}
//多选一
if($params['sales_material_type'] == 5){
if(!$params['pickone_select_type']){
$err_msg = "缺少多选一的选择方式";
return false;
}
if(!isset($params['sort']) || count($params['sort']) < 2){
$err_msg ="多选一物料请至少设置二个基础物料明细内容";
return false;
}
$reg_number = "/^[1-9][0-9]*$/"; //正整数
foreach($params['sort'] as $key_bm_id => $var_w){
if($var_w){
if(!preg_match($reg_number,$var_w)){
$err_msg = "权重必须是数值";
return false;
}
}else{ //0和空 数据库默认给0
}
}
}
return true;
}
function autoGenBasicMaterial($params, &$err_msg){
$_POST = $params;
$_POST['material_name'] = $params['sales_material_name'];
$_POST['material_bn'] = $params['sales_material_bn'];
$_POST['material_code'] = (trim($params['material_code']) ? $params['material_code'] : $params['sales_material_bn']);#基础物料条码必填项
$_POST['retail_price'] = floatval($params['retail_price']);
$_POST['serial_number'] = $params['serial_number'];#基础物料唯一码
$_POST['type'] = 1;
$_POST['visibled'] = 1;
$_POST['specifications'] = $params['material_specification'];#物料规格
$_POST['cost'] = floatval($params['cost']);#成本 价
$_POST['weight'] = intval($params['weight']);#重量
$_POST['cat_id'] = intval($params['goods_type']);#类型
$_POST['brand'] = intval($params['brand_id']);#品牌
if(!$this->checkAddBasicMParams($_POST, $err_msg)){
return false;
}
$basicMaterialObj = app::get('material')->model('basic_material');
$basicMaterialExtObj = app::get('material')->model('basic_material_ext');
$basicMaterialFeatureGrpObj = app::get('material')->model('basic_material_feature_group');
$basicMaterialStockObj = app::get('material')->model('basic_material_stock');
$basicMaterialConfObj = app::get('material')->model('basic_material_conf');
$barocdeObj = app::get('material')->model('barcode');
#检验保质期监控配置
$use_expire = intval($_POST['use_expire']);
$warn_day = intval($_POST['warn_day']);
$quit_day = intval($_POST['quit_day']);
if($use_expire == 1 && ($warn_day <= $quit_day))
{
$this->end(false, '预警天数必须大于自动退出库存天数');
}
//保存物料主表信息
$addData = array(
'material_name' => $_POST['material_name'],
'material_bn' => $_POST['material_bn'],
'material_bn_crc32' => $_POST['material_bn_crc32'],
'type' => $_POST['type'],
'serial_number' => $_POST['serial_number'],
'visibled' => $_POST['visibled'],
'create_time' => time(),
);
$is_save = $basicMaterialObj->save($addData);
if($is_save){
//保存条码信息
$sdf = array(
'bm_id' => $addData['bm_id'],
'type' => material_codebase::getBarcodeType(),
'code' => $_POST['material_code'],
);
$barocdeObj->insert($sdf);
//保存保质期配置
$useExpireConfData = array(
'bm_id' => $addData['bm_id'],
'use_expire' => $_POST['use_expire'] == 1 ? 1 : 2,
'warn_day' => $_POST['warn_day'] ? $_POST['warn_day'] : 0,
'quit_day' => $_POST['quit_day'] ? $_POST['quit_day'] : 0,
'create_time' => time(),
);
$basicMaterialConfObj->save($useExpireConfData);
//如果关联半成品数据
if($addData['type'] == 1){
$basicMaterialCombinationItemsObj = app::get('material')->model('basic_material_combination_items');
if(isset($_POST['at'])){
foreach($_POST['at'] as $k=>$v){
$tmpChildMaterialInfo = $basicMaterialObj->dump($k, 'material_name,material_bn');
$addCombinationData = array(
'pbm_id' => $addData['bm_id'],
'bm_id' => $k,
'material_num' => $v,
'material_name' => $tmpChildMaterialInfo['material_name'],
'material_bn' => $tmpChildMaterialInfo['material_bn'],
'material_bn_crc32' => sprintf('%u',crc32($tmpChildMaterialInfo['material_bn'])),
);
$basicMaterialCombinationItemsObj->insert($addCombinationData);
$addCombinationData = null;
}
}
}
//保存基础物料的关联的特性
if($_POST['ftgp_id']){
$addBindFeatureData = array(
'bm_id' => $addData['bm_id'],
'feature_group_id' => $_POST['ftgp_id'],
);
$basicMaterialFeatureGrpObj->insert($addBindFeatureData);
$addBindFeatureData = null;
}
//保存物料扩展信息
$addExtData = array(
'bm_id' => $addData['bm_id'],
'cost' => $_POST['cost'] ? $_POST['cost'] : 0.00,
'retail_price' => $_POST['retail_price'] ? $_POST['retail_price'] : 0.00,
'weight' => $_POST['weight'] ? $_POST['weight'] : 0.00,
'unit' => $_POST['unit'],
'specifications' => $_POST['specifications'],
'brand_id' => $_POST['brand_id'],
'cat_id' => $_POST['cat_id'],
);
$basicMaterialExtObj->insert($addExtData);
//保存物料库存信息
// * redis库存高可用,废弃掉直接修改db库存、冻结的方法
$addStockData = array(
'bm_id' => $addData['bm_id'],
// 'store' => $_POST['store'] ? $_POST['store'] : 0,
// 'store_freeze' => $_POST['store_freeze'] ? $_POST['store_freeze'] : 0,
'store' => 0,
'store_freeze' => 0,
);
$basicMaterialStockObj->insert($addStockData);
return $addData['bm_id'];
}else{
$err_msg = '保存失败';
return false;
}
}
function checkAddBasicMParams(&$params, &$err_msg){
//检查物料名称
if(empty($params['material_name']) || empty($params['material_bn'])){
$err_msg ="必填信息不能为空";
return false;
}
//检查物料编号
$basicMaterialObj = app::get('material')->model('basic_material');
$basicMaterialInfo = $basicMaterialObj->getList('material_bn',array('material_bn'=>$params['material_bn']));
if($basicMaterialInfo){
$err_msg ="当前新增的物料编码已存在,不能重复创建";
return false;
}
//检查物料条码
$barcode = app::get('material')->model('barcode')->getList('bm_id',array('code'=>$params['material_code'], 'type' => material_codebase::getBarcodeType()));
if($basicMaterialInfo){
$err_msg ="当前新增的物料条码已被使用,不能重复使用";
return false;
}
$params['material_bn_crc32'] = sprintf('%u',crc32($params['material_bn']));
if($params['type'] == 1){
if(isset($params['at'])){
foreach ($params['at'] as $val){
if ($val < 1){
$err_msg ="数量必须大于0";
return false;
}
}
}
}
return true;
}
public function batchGenMaterial()
{
$sub_menu = $this->_views();
foreach ($sub_menu as $key => $value) {
if($key == 2){
$base_filter = $value['filter'];
}
}
$filter = array_merge((array)$_POST,(array)$base_filter);
$skuObj = app::get('inventorydepth')->model('shop_adjustment');
$skuObj->filter_use_like = true;
$count = $skuObj->count($filter);
$this->pagedata['total'] = $count;
$this->pagedata['filter'] = http_build_query($filter);
$this->display('shop/adjustment/batch_trans_material.html');
}
public function dobatchGenMaterial(){
$page_no = intval($_GET['page_no']) ? intval($_GET['page_no']) : 1;
$page_size = 10;
$offset = 0;
$total = intval($_GET['total']);
parse_str($_POST['filter'],$filter);
$skuObj = app::get('inventorydepth')->model('shop_adjustment');
$skuObj->filter_use_like = true;
$skuList = $skuObj->getList('*',$filter,$offset,$page_size);
$succ_num = $fail_num = 0;
if ($skuList) {
foreach ((array) $skuList as $sku_info) {
unset($_POST);
$_POST['sales_material_name'] = $sku_info['shop_title'];
$_POST['sales_material_bn'] = $sku_info['shop_product_bn'];
$_POST['sales_material_type'] = 1;
$_POST['shop_id'] = $sku_info['shop_id'];
$_POST['gen_mode'] = 1;
$_POST['retail_price'] = $sku_info['shop_price'];
$_POST['shop_sku_id'] = $sku_info['shop_sku_id'];
$rs = $this->toAdd(false);
if ($rs) $succ_num++; else $fail_num++;
}
}
$result = array('status'=>'running','data'=>array('succ_num'=>$succ_num,'fail_num'=>$fail_num));
if ( ($page_size * $page_no) >= $total) {
$result['status'] = 'complete';
$result['data']['rate'] = '100';
} else {
$result['data']['rate'] = $page_no * $page_size / $total * 100;
}
echo json_encode($result);exit;
}
//导出数据
public function export_data($type){
@ini_set('memory_limit','64M');
$lib_inventorydepth_shop_skus = kernel::single("inventorydepth_shop_skus");
$filter_arr = array();
if(!empty($_POST['id'])){ //勾选的项
$filter_arr['id'] = $_POST['id'];
}
if($_POST["isSelectedAll"] == "_ALL_" && empty($_POST['id'])){ //全选
$views = $lib_inventorydepth_shop_skus->get_shop_adjustment_views_arr();
if(intval($_GET["view"])>0){
$filter_arr = $views[$_GET["view"]]["filter"];
}
$filter_arr['shop_id'] = $_SESSION['shop_id'];
}
$mdl_ome_shop = app::get('ome')->model('shop');
$rs_ome_shop = $mdl_ome_shop->dump(array("shop_id"=>$_SESSION['shop_id']),"name");
switch($type){
case "release_stock":
$part_shop_name = '发布库存模版'.date('Ymd');
$content_arr = $lib_inventorydepth_shop_skus->get_release_stock_export_content($filter_arr);
break;
}
$filename = $rs_ome_shop["name"].$part_shop_name;
header("Content-Type: text/csv");
header("Content-Disposition: attachment; filename=".$filename.".csv");
header('Cache-Control:must-revalidate,post-check=0,pre-check=0');
header('Expires:0');
header('Pragma:public');
$title_arr = $lib_inventorydepth_shop_skus->get_title_arr($type);
echo '"'.implode('","',$title_arr).'"';
echo "\n";
if(!empty($content_arr)){
foreach($content_arr as $var_ca){
echo '"'.implode('","',$var_ca).'"';echo "\n";
}
}
}
public function displayAssignUpload()
{
// $shopList = app::get('ome')->model('shop')->getList('shop_id,name', [
// 's_type' => '1',
// 'filter_sql' => 'node_id is not null and node_id !=""',
// ]);
// $this->pagedata['shopList'] = $shopList;
$this->display('shop/adjustment/assign_upload.html');
}
public function ajaxAssignUpload($shop_id)
{
$this->begin();
$bn = $_POST['bn'];
$bn = array_filter(array_unique(explode("\n", $bn)));
if (!$bn){
$this->end(false, '请填写货号');
}
if (!$shop_id) {
$this->end(false, '请选择店铺');
}
// 判断店铺
$shop = app::get('ome')->model('shop')->dump($shop_id);
if ($shop['s_type'] != '1'){
$this->end(false, '非线上店铺不能同步');
}
if (!$shop['node_id']) {
$this->end(false, '未绑定店铺不能同步');
}
$list = app::get('material')->model('sales_material')->getList('sales_material_bn', ['sales_material_bn' => $bn]);
if (!$list) {
$this->end(false, '销售物料不存在');
}
foreach ($list as $v) {
$params = [
'sales_material_bn' => trim($v['sales_material_bn']),
'offset' => '0',
'limit' => '10',
'shop_id' => $shop_id,
];
kernel::single('inventorydepth_queue')->insert_stock_update_queue($v['sales_material_bn'],$params);
}
$this->end(true);
}
public function showActualStock() {
$id = $_GET['id'];
$sku = app::get('inventorydepth')->model('shop_adjustment')->db_dump(['id'=>$id], 'shop_product_bn,shop_id,shop_bn,shop_type');
# [普通]销售物料
$products = app::get('material')->model('sales_material')->getList('sm_id,sales_material_name,sales_material_bn,sales_material_type,shop_id,class_id',array('sales_material_bn'=>$sku['shop_product_bn']));
if(!$products){
echo '无关联货号!';exit;
}
kernel::single('inventorydepth_calculation_basicmaterial')->init($products);
kernel::single('inventorydepth_calculation_salesmaterial')->init($products);
$stock = kernel::single('inventorydepth_logic_stock')->getStock($products[0],$sku['shop_id'],$sku['shop_bn']);
$quantity = $stock['quantity'];
$actual_stock = $stock['actual_stock'];
$asRs = $stock['regulation']['detail']['可售库存']['info'];
if($actual_stock === false) {
echo '获取可售库存失败!';exit;
}
//format福袋组合信息
if(isset($asRs['luckybag'])){
$combineMdl = app::get('material')->model('fukubukuro_combine');
//combine_bn
$combineBns = array_keys($asRs['luckybag']);
//福袋组合列表
$filter = array('combine_bn'=>$combineBns);
$combineList = $combineMdl->getList('combine_id,combine_bn,selected_number,include_number', $filter, 0, -1);
$combineList = array_column($combineList, null, 'combine_bn');
//luckbag
foreach ($asRs['luckybag'] as $combine_bn => $luckyVal)
{
$combineInfo = $combineList[$combine_bn];
$luckyVal = array_merge($luckyVal, $combineInfo);
$asRs['luckybag'][$combine_bn] = $luckyVal;
}
}
$this->pagedata['quantity'] = $quantity;
$this->pagedata['rr'] = [
'heading' => $stock['regulation']['规则名称'],
'content' => $stock['regulation']['规则内容']['result'],
];
$this->pagedata['asRs'] = $asRs;
$this->display('shop/adjustment/actual_stock.html');
}
/**
* 批量发布库存弹窗页面
* @date 2024-12-31 2:44 下午
*/
public function displayBatchRelease()
{
$_POST['mapping'] = '1';//只处理已匹配的SKU
$this->pagedata['request_url'] = $this->url.'&act=addBatchRelease';
parent::dialog_batch('inventorydepth_mdl_shop_adjustment',true,100,'incr');
}
/**
* 批量发布库存
* 走队列
* @date 2024-12-31 2:54 下午
*/
public function addBatchRelease()
{
parse_str($_POST['primary_id'], $postdata);
if (!$postdata['f']) { echo 'Error: 请先选择在售商品';exit;}
$retArr = array(
'itotal' => 0,
'isucc' => 0,
'ifail' => 0,
'err_msg' => array(),
);
$adjustmentMdl = app::get('inventorydepth')->model('shop_adjustment');
$postdata['f']['mapping'] = '1';//只处理已匹配的SKU
$adjustmentList = $adjustmentMdl->getList('id,shop_id,shop_name', $postdata['f'], $postdata['f']['offset'], $postdata['f']['limit'],'shop_id DESC');
if (!$adjustmentList) {echo 'Error: 未查询到已关联在售商品';exit;}
$retArr['itotal'] = count($adjustmentList);
$shopAdjustment = [];
$shop = [];
foreach($adjustmentList as $info){
$shopAdjustment[$info['shop_id']][] = $info;
$shop[$info['shop_id']] = $info['shop_name'];
}
foreach ($shopAdjustment as $shop_id => $adjustment) {
$offset = 0; $limit = 20; $_POST['shop_id'] =$shop_id;
$params = $_POST; $params['limit'] = $limit;
$params['id'] = array_column($adjustment,'id');
// 操作员信息
$params['operInfo'] = kernel::single('inventorydepth_func')->getDesktopUser();
$count = count($adjustment);
if($count<=0) continue;
$title = "批量店铺【{$shop[$shop_id]}】库存回写";
$total = floor($count/$limit);
for ($i=$total; $i>=0 ; $i--) {
$params['offset'] = $i*$limit;
//插入队列
kernel::single('inventorydepth_queue')->insert_release_queue($title,$params);
}
$retArr['isucc'] += $count;
}
echo json_encode($retArr),'ok.';exit;
}
/**
* 批量删除
* @date 2025-04-30 下午2:34
*/
public function batch_delete()
{
@ini_set('memory_limit', '512M');
set_time_limit(0);
if (isset($_POST['isSelectedAll']) && $_POST['isSelectedAll'] == '_ALL_') {
if (!isset($_POST['shop_id']) || empty($_POST['shop_id'])) {
die('缺少具体店铺查询条件!');
}
}
$filter = array(
'request' => 'false',
);
$_POST = array_merge($filter, $_POST);
$this->pagedata['request_url'] = $this->url . '&act=ajaxBatchDelete';
//调用desktop公用进度条(第4个参数是增量传offset,否则默认一直为0)
parent::dialog_batch('inventorydepth_mdl_shop_adjustment', false, 100);
}
public function ajaxBatchDelete()
{
$retArr = array(
'itotal' => 0,
'isucc' => 0,
'ifail' => 0,
'err_msg' => [],
);
//获取发货单号
parse_str($_POST['primary_id'], $postdata);
if (!$postdata) {
echo 'Error: 请先选择数据';
exit;
}
//filter
$filter = $postdata['f'];
$offset = intval($postdata['f']['offset']);
$limit = intval($postdata['f']['limit']);
if (empty($filter)) {
echo 'Error: 没有找到查询条件';
exit;
}
if (isset($_POST['isSelectedAll']) && $_POST['isSelectedAll'] == '_ALL_') {
if (!isset($filter['shop_id']) || empty($filter['shop_id'])) {
echo 'Error: 缺少具体店铺查询条件';
exit;
}
}
$shopAdjustmentMdl = $this->app->model('shop_adjustment');
//data
$dataList = $shopAdjustmentMdl->getFinderList('id', $filter, $offset, $limit);
//check
if (empty($dataList)) {
echo 'Error: 没有获取到在售库存数据';
exit;
}
$ids = array_column($dataList, 'id');
//count
$count = count($dataList);
$retArr['itotal'] = $count;
$shopAdjustmentMdl->delete(['id' => $ids]);
$retArr['isucc'] = $count;
echo json_encode($retArr), 'ok.';
exit;
}
}