Files
OMS/app/o2o/lib/store.php
2026-01-04 19:08:31 +08:00

1003 lines
38 KiB
PHP
Raw Permalink 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 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.
*/
/**
* 门店数据处理Lib类
*
* @access public
* @author wangbiao<wangbiao@shopex.cn>
* @version $Id: import.php 2016-07-26 15:00
*/
class o2o_store
{
/**
* create_store 门店创建
*
* @param $sdf
* @return sdf
*/
function create_store($sdf, &$errmsg)
{
$storeObj = app::get('o2o')->model('store');
$organizationObj = app::get('organization')->model('organization');
$serverObj = app::get('o2o')->model('server');
$regionObj = app::get('o2o')->model('store_regions');
$smsLib = kernel::single('taoexlib_request_sms');
$channelLib = kernel::single('channel_interface_channel');
$branchLib = kernel::single('ome_interface_branch');
$shopLib = kernel::single('ome_interface_shop');
$regionLib = kernel::single('o2o_store_regions');
//开启事务
$storeObj->db->beginTransaction();
// 如果状态为关闭(2),检查门店是否还有库存
if ($sdf['status'] == 2) {
$hasStock = $this->checkStoreHasStock($sdf['org_no']);
if ($hasStock) {
$storeObj->db->rollBack();
$errmsg .= '此门店下还有库存,关店失败,门店编码:' . $sdf['org_no'] . '。';
return false;
}
}
// 处理经销商层级逻辑
$dealerOrgId = null;
$finalParentId = $sdf['parent_id'];
$finalOrgLevelNum = $sdf['org_level_num'];
if (!empty($sdf['dealer_cos_id'])) {
// 查询经销商信息
$cosMdl = app::get('organization')->model('cos');
$dealerCos = $cosMdl->dump(['cos_id' => $sdf['dealer_cos_id']], 'cos_code,cos_name');
if ($dealerCos) {
// 检查经销商是否已经在organization表中存在
$dealerOrg = $organizationObj->dump(['org_no' => 'BS_' . $dealerCos['cos_code']]);
if (!$dealerOrg) {
// 创建经销商组织记录
$dealerOrgData = array(
'org_name' => $dealerCos['cos_name'],
'org_type' => 3, // 经销商类型
'org_no' => 'BS_' . $dealerCos['cos_code'], // 添加BS_前缀
'status' => 1,
'area' => $sdf['area'],
'org_parents_structure' => $sdf['org_parents_structure'],
'parent_id' => $finalParentId,
'org_level_num' => $finalOrgLevelNum,
);
if (!$organizationObj->save($dealerOrgData)) {
$storeObj->db->rollBack();
$errmsg .= '保存经销商组织信息失败,门店编码:' . $sdf['org_no'] . '。';
return false;
}
$dealerOrgId = $dealerOrgData['org_id'];
} else {
$dealerOrgId = $dealerOrg['org_id'];
}
// 如果有经销商门店的parent_id指向经销商层级+1
$finalParentId = $dealerOrgId;
$finalOrgLevelNum = $finalOrgLevelNum + 1;
}
}
//企业组织(注意:批量导入时必须填写所属组织)
$org_sdf = array(
'org_no' => $sdf['org_no'],
'org_name'=> $sdf['org_name'],
'org_type' => $sdf['org_type'],
'status' => $sdf['status'],
'area' => $sdf['area'],
'org_level_num' => $finalOrgLevelNum,
'org_parents_structure' => $sdf['org_parents_structure'],
'parent_id' => $finalParentId,
);
$is_save = $organizationObj->save($org_sdf);
if(!$is_save)
{
#事务回滚
$storeObj->db->rollBack();
$errmsg .= '保存企业组织出错,组织编码:'. $org_sdf['org_no'] .'。';
return false;
}
//发送短信签名注册
if (defined('APP_TOKEN') && defined('APP_SOURCE')) {
base_kvstore::instance('taoexlib')->fetch('account', $account);
if (unserialize($account)) {
$sms_sign = '【'.$org_sdf['org_name'].'】';
$smsLib->newoauth_request(array('sms_sign'=>$sms_sign));
}
}
//如果设定了门店服务端类型获取对应的虚拟仓储类型
$now_wms_id = 0;
if($sdf['server_id']){
$serverInfo = $serverObj->dump(array('server_id'=>$sdf['server_id']),'type');
if($serverInfo['type']){
$wms_type = $channelLib->dump(array('channel_type'=>'wms','node_type'=>$serverInfo['type']),'channel_id');
$now_wms_id = $wms_type['channel_id'];
}
}
//门店
$store_sdf = array(
'store_bn' => $sdf['org_no'],
'name' => $sdf['org_name'],
'server_id' => $sdf['server_id'],
'addr' => $sdf['addr'],
/*
'longitude' => $sdf['longitude'],
'latitude' => $sdf['latitude'],
*/
'area' => $sdf['area'],
'zip' => $sdf['zip'],
'contacter' => $sdf['contacter'],
'mobile' => $sdf['mobile'],
'tel' => $sdf['tel'],
'store_type' => $sdf['store_type'],
/*
'self_pick' => $sdf['self_pick'],
'distribution' => $sdf['distribution'],
'aftersales' => $sdf['aftersales'],
'confirm' => $sdf['confirm'],
*/
'status' => $sdf['status'],
);
$is_save = $storeObj->save($store_sdf);
if(!$is_save)
{
#事务回滚
$storeObj->db->rollBack();
$errmsg .= '保存门店信息出错,门店编码:'. $store_sdf['store_bn'] .'。';
return false;
}
//生成对应的虚拟仓
$new_branch = array(
'branch_bn' => $sdf['org_no'],
'name' => $sdf['org_name'],
'storage_code' => $sdf['org_no'],
'b_type' => 2,
'b_status' => $sdf['status'],
'wms_id' => $now_wms_id,
'area' => $sdf['area'],
'address' => $sdf['addr'],
'zip' => $sdf['zip'],
'phone' => $sdf['tel'],
'uname' => $sdf['contacter'],
'mobile' => $sdf['mobile'],
'store_id' => $store_sdf['store_id'],
);
$save_branch = $branchLib->save($new_branch);
if(!$save_branch)
{
#事务回滚
$storeObj->db->rollBack();
$errmsg .= '门店关联虚拟仓保存失败,门店编码:'. $store_sdf['store_bn'] .'。';
return false;
}
//生成对应的虚拟店铺
$new_shop = array(
'shop_bn' => $sdf['org_no'],
'name' => $sdf['org_name'],
's_type' => 2,
's_status' => $sdf['status'],
);
$save_shop = $shopLib->save($new_shop);
if(!$save_shop)
{
#事务回滚
$storeObj->db->rollBack();
$errmsg .= '门店关联线下店铺保存失败,门店编码:'. $store_sdf['store_bn'] .'。';
return false;
}
//更新相关的仓库和店铺
$update_data = array('branch_id'=>$new_branch['branch_id'], 'shop_id'=>$new_shop['shop_id']);
$update_store = $storeObj->update($update_data, array('store_id'=>$store_sdf['store_id']));
if(!$update_store)
{
#事务回滚
$storeObj->db->rollBack();
$errmsg .= '门店关联仓库、店铺信息更新失败,门店编码:'. $store_sdf['store_bn'] .'。';
return false;
}
#新增门店关联地区数据信息
list($temp_package, $temp_region_name, $region_id) = explode(':', $sdf['area']);
$region_data = $regionLib->getRegionById($region_id);
$save_data = array(
'store_id' => $store_sdf['store_id'],
'region_1' => intval($region_data[1]),
'region_2' => intval($region_data[2]),
'region_3' => intval($region_data[3]),
'region_4' => intval($region_data[4]),
'region_5' => intval($region_data[5]),
);
$save_region = $regionObj->save($save_data);
if(!$save_region)
{
#事务回滚
$storeObj->db->rollBack();
$errmsg .= '门店关联地区信息保存失败,门店编码:'. $store_sdf['store_bn'] .'。';
return false;
}
//如果最新保存的信息有父节点,更新父节点为有下级仓库或门店节点信息
if($finalParentId > 0)
{
$p_org_info = $organizationObj->dump(array('org_id'=>$finalParentId), 'haschild');
$child_arr = $organizationObj->getList('org_id', array('parent_id'=>$finalParentId, 'org_type'=>2), 0, -1);
if(count($child_arr) > 0){
$org_save_parent_data['haschild'] = $p_org_info['haschild'] | 2;
}else{
$org_save_parent_data['haschild'] = $p_org_info['haschild'] ^ 2;
}
$organizationObj->update($org_save_parent_data, array('org_id'=>$finalParentId));
}
//事务确认
$storeObj->db->commit();
return true;
}
/**
* 门店数据有效性检查Lib类
* @param unknown $params
* @param unknown $err_msg
* @return Array
*/
public function checkAddParams(&$params, &$err_msg)
{
$organizationObj = app::get('organization')->model('organization');
//拆分组织经纬度信息
if(isset($params['coordinate']))
{
$coordinate = explode(',',$params['coordinate']);
$params['longitude'] = $coordinate[0];
$params['latitude'] = $coordinate[1];
if(empty($params['longitude']) || empty($params['latitude']))
{
$err_msg = '门店经纬度填写错误';
return false;
}
}
//表单验证
if (strlen($params['zip']) <> '6') {
$err_msg = '请输入正确的邮编';
return false;
}
//固定电话与手机必填一项
$gd_tel = str_replace(" ", "", $params['tel']);
$mobile = str_replace(" ", "", $params['mobile']);
if (!$gd_tel && !$mobile) {
$err_msg = '固定电话与手机号码必需填写一项';
return false;
}
$pattern = "/^400\d{7}$/";
$pattern1 = "/^\d{1,4}-\d{7,8}(-\d{1,6})?$/i";
if ($gd_tel) {
$_rs = preg_match($pattern, $gd_tel);
$_rs1 = preg_match($pattern1, $gd_tel);
if ((!$_rs) && (!$_rs1)) {
$err_msg = '请填写正确的固定电话号码';
return false;
}
}
$pattern2 = "/^\d{8,15}$/i";
if ($mobile) {
if (!preg_match($pattern2, $mobile)) {
$err_msg = '请输入正确的手机号码';
return false;
}
if ($mobile[0] == '0') {
$err_msg = '手机号码前请不要加0';
return false;
}
}
//识别是新增还是编辑
$params['is_new_add'] = intval($params['org_id']) ? false : true;
if($params['is_new_add']){
$check_org_no_exist = $organizationObj->dump(array("org_no"=>$params["org_no"]),"org_id");
if($check_org_no_exist){
$err_msg = '新增的编码已经存在';
return false;
}
$check_org_name_exist = $organizationObj->dump(array("org_name"=>$params["org_name"]),"org_id");
if($check_org_name_exist){
$err_msg = '新增的名称已经存在';
return false;
}
}else{
$check_org_no_exist = $organizationObj->dump(array("org_no"=>$params["org_no"]),"org_id");
if($check_org_no_exist && $check_org_no_exist['org_id'] != $params['org_id']){
$err_msg = '编辑的编码已经存在';
return false;
}
$check_org_name_exist = $organizationObj->dump(array("org_name"=>$params["org_name"]),"org_id");
if($check_org_name_exist && $check_org_name_exist['org_id'] != $params['org_id']){
$err_msg = '编辑的名称已经存在';
return false;
}
//编辑的时候,取一下门店原有的信息
$old_org_info = $organizationObj->dump(array("org_id"=>$params['org_id']),"org_id,parent_id");
$params['old_org_info'] = $old_org_info;
}
return true;
}
//根据门店编码找到对应的仓库ID
/**
* 获取BranchIdByStoreBn
* @param mixed $store_bn store_bn
* @return mixed 返回结果
*/
public function getBranchIdByStoreBn($store_bn){
$storeObj = app::get('o2o')->model('store');
$storeInfo = $storeObj->getList('branch_id',array('store_bn'=>$store_bn), 0, 1);
if($storeInfo){
return $storeInfo[0]['branch_id'];
}
}
/**
* 根据订单扩展表上的门店编码查找到门店信息
*
* @param intval $order_id 订单号
* @return Array
*/
public function getOrderIdByStore($order_id)
{
$o2o_order = array();
$o2o_order['is_omnichannel'] = true;
//指定门店
$orderExtendObj = app::get('ome')->model('order_extend');
$ordExtRow = $orderExtendObj->dump(array('order_id'=>$order_id), 'order_id, store_dly_type, store_bn');
$store_bn = $ordExtRow['store_bn'];
$store_dly_type = $ordExtRow['store_dly_type'];
$dly_corp_type = ($store_dly_type == 1 ? 'o2o_ship' : 'o2o_pickup');
if($store_dly_type && $store_bn)
{
//默认选择的门店物流公司
$corpObj = app::get('ome')->model('dly_corp');
$corpRow = $corpObj->dump(array('type'=>$dly_corp_type, 'd_type'=>2), 'corp_id');
$o2o_order['select_corp_id'] = $corpRow['corp_id'];
//根据订单扩展表上的门店编码查找到门店信息
$o2oStoreObj = app::get('o2o')->model('store');
$storeRow = $o2oStoreObj->dump(array('store_bn'=>$store_bn), 'store_id, name, branch_id, area');
$o2o_order['store_bn'] = $store_bn;
$o2o_order['branch_id'] = $storeRow['branch_id'];
$o2o_order['store_area'] = $storeRow['area'];
$store_msg = array(1=>'客户要求指定【{store_name}】门店进行配送', '客户要求指定到【{store_name}】门店自提');
$o2o_order['store_recommend_msg'] = str_replace('{store_name}', $storeRow['name'], $store_msg[$store_dly_type]);
}
return $o2o_order;
}
/**
* undocumented function
*
* @return void
* @author
* */
public function create($post)
{
// 前后去空格
foreach ($post as $key => $value) {
if (is_string($value)) {
$post[$key] = trim($value);
}
}
// 手机号验证
$mobile = str_replace(" ", "", $post['mobile']);
if (!empty($mobile)) {
if (!kernel::single('ome_func')->isMobile($mobile)) {
return [false, '请输入正确的手机号码'];
}
}
$store_id = (int) $post['store_id'];
// 如果状态为关闭(2),检查门店是否还有库存
if ($post['status'] == 2) {
$hasStock = $this->checkStoreHasStock($post['store_bn']);
if ($hasStock) {
return [false, '此门店下还有库存,关店失败'];
}
}
// 更新企业结构
$orgMdl = app::get('organization')->model('organization');
$storeMdl = app::get('o2o')->model('store');
$org = $orgMdl->dump(['org_no' => $post['store_bn']]);
if (!$store_id && $org) {
$msg = $org['org_type'] == '2' ? '门店编码已经存在' : '此编码被企业组织占用';
return [false, $msg];
}
if($post['store_type'] == 'join' && empty($post['dealer_cos_id'])) {
return [false, '经营模式为加盟时,经销商信息不能为空'];
}
// 处理经销商层级逻辑
$dealerOrgId = null;
if (!empty($post['dealer_cos_id'])) {
// 查询经销商信息
$cosMdl = app::get('organization')->model('cos');
$dealerCos = $cosMdl->dump(['cos_id' => $post['dealer_cos_id']], 'cos_code,cos_name');
if ($dealerCos) {
// 检查经销商是否已经在organization表中存在
$dealerOrg = $orgMdl->dump(['org_no' => 'BS_' . $dealerCos['cos_code']]);
if (!$dealerOrg) {
// 创建经销商组织记录
list(, , $originalParentId) = explode(':', $post['org_parents_structure']);
$pOrg = $orgMdl->dump($originalParentId, 'org_level_num');
$dealerOrgData = array(
'org_name' => $dealerCos['cos_name'],
'org_type' => 3, // 经销商类型
'org_no' => 'BS_' . $dealerCos['cos_code'], // 添加BS_前缀
'status' => 1,
'area' => $post['area'],
'org_parents_structure' => $post['org_parents_structure'],
'parent_id' => $originalParentId,
'org_level_num' => $pOrg['org_level_num'] + 1,
);
if (!$orgMdl->save($dealerOrgData)) {
return [false, '保存经销商组织信息失败:' . $orgMdl->db->errorinfo()];
}
$dealerOrgId = $dealerOrgData['org_id'];
} else {
$dealerOrgId = $dealerOrg['org_id'];
}
}
}
$upOrgData = array(
'org_id' => (int) $org['org_id'],
'org_name' => $post["name"],
'org_type' => 2,
'org_no' => $post["store_bn"],
'status' => $post['status'],
'area' => $post['area'],
'org_parents_structure' => $post['org_parents_structure'],
);
// 如果有经销商门店的parent_id指向经销商否则指向原来的所属组织
if ($dealerOrgId) {
$upOrgData['parent_id'] = $dealerOrgId;
$pOrg = $orgMdl->dump($dealerOrgId, 'org_level_num');
$upOrgData['org_level_num'] = $pOrg['org_level_num'] + 1;
} else {
list(, , $upOrgData['parent_id']) = explode(':', $post['org_parents_structure']);
$pOrg = $orgMdl->dump($upOrgData['parent_id'], 'org_level_num');
$upOrgData['org_level_num'] = $pOrg['org_level_num'] + 1;
}
if (!$orgMdl->save($upOrgData)) {
return [false, $orgMdl->db->errorinfo()];
}
// 保存门店
$store = $storeMdl->dump(['store_bn' => $post['store_bn']]);
if (!$store_id && $store) {
return [false, '门店编码已经存在'];
}
$snapshoot = $store ?: [];
$post['store_id'] = $store_id;
if (!$store_id) {
$post['create_time'] = time();
}
$post['sync_status'] = '0';
if (!$storeMdl->save($post)) {
return [false, $storeMdl->db->errorinfo()];
}
$server = app::get('o2o')->model('server')->dump($post['server_id']);
// 保存店铺
$upShopData = array(
'shop_bn' => $post['store_bn'],
'name' => $post['name'],
's_type' => 2,
's_status' => $post['status'],
'node_type' => $server['node_type'],
'shop_type' => $server['node_type'],
'node_id' => $post['store_bn'],
);
$shop = app::get('ome')->model('shop')->dump([
'shop_bn' => $post['store_bn'],
's_type' => 2,
]);
$upShopData['shop_id'] = $shop['shop_id'];
$rs = kernel::single('ome_interface_shop')->save($upShopData);
if (!$rs) {
return [false, '门店关联线下店铺保存失败,编码可能被占用'];
}
// 验证仓库编号格式
if (!empty($post['store_bn'])) {
if (!preg_match('/^[a-zA-Z0-9_-]+$/', $post['store_bn'])) {
return [false, '仓库编号只允许输入英文字母、数字、下划线和横线'];
}
}
// 验证库内存放点编号格式
if (!empty($post['storage_codes']['main'])) {
if (!preg_match('/^[a-zA-Z0-9_-]+$/', $post['storage_codes']['main'])) {
return [false, '库内存放点编号只允许输入英文字母、数字、下划线和横线'];
}
}
// 主仓
$upBranchData = array(
'branch_bn' => $post['store_bn'],
'name' => $post['name'],
'storage_code' => $post['storage_codes']['main'],
'b_type' => 2,
'b_status' => $post['status'],
'weight' => $post['priority'],
'area' => $post['area'],
'address' => $post['addr'],
'zip' => $post['zip'],
'phone' => $post['tel'],
'uname' => $post['contacter'],
'mobile' => $post['mobile'],
'store_id' => $post['store_id'],
// 'is_ctrl_store' => $post['is_ctrl_store'],
);
$branch = app::get('ome')->model('branch')->dump([
'branch_bn' => $post['store_bn'],
'b_type' => 2,
'check_permission' => 'false',
]);
$upBranchData['branch_id'] = (int) $branch['branch_id'];
if ($upBranchData['branch_id']) {
// 更新
$rs = kernel::single('ome_interface_branch')->update($upBranchData,[
'branch_id' => $upBranchData['branch_id'],
]);
} else {
// 插入
$rs = kernel::single('ome_interface_branch')->save($upBranchData);
}
if (!$rs) {
return [false, sprintf('门店关联虚拟仓保存失败:%s', kernel::database()->errorinfo())];
}
kernel::single('console_map_branch')->getLocation($upBranchData['branch_id']);
kernel::single('ome_shop_onoffline')->doSave($upShopData['shop_id'], $post['online_id']);
//更新相关的仓库和店铺
$rs = $storeMdl->update([
'branch_id' => $upBranchData['branch_id'],
'shop_id' => $upShopData['shop_id'],
], ['store_id' => $post['store_id']]);
if (!$rs) {
return [false, '门店关联仓库、店铺信息更新失败'];
}
// 自动权限继承:当新门店添加到经销商时,自动继承权限
if (!$store_id && $dealerOrgId) { // 只在新建门店且有经销商的情况下执行
$this->autoInheritStorePermission($dealerOrgId, $upOrgData['org_id']);
}
// 记录操作日志
$log_id = app::get('ome')->model('operation_log')->write_log('store_upsert@o2o', $post['store_id'], ($store_id ? '编辑' : '创建') . '门店');
if ($log_id && $store_id && $snapshoot) {
$shootMdl = app::get('ome')->model('operation_log_snapshoot');
$snapshoot = json_encode($snapshoot, JSON_UNESCAPED_UNICODE);
$tmp = ['log_id' => $log_id, 'snapshoot' => $snapshoot];
$shootMdl->insert($tmp);
}
return [true, '保存成功'];
}
/**
* 获取BranchType
* @return mixed 返回结果
*/
public function getBranchType()
{
$typeMdl = app::get('ome')->model('branch_type');
$types = $typeMdl->getlist('*',array('source'=>'create'));
$branch_types = [];
foreach($types as $v){
$branch_types[$v['type_code']] = [
'text' => $v['type_name'],
'type_code' => $v['type_code'],
];
}
return $branch_types;
}
/**
* 保存BranchType
* @param mixed $store store
* @param mixed $branch_type branch_type
* @return mixed 返回操作结果
*/
public function saveBranchType($store, $branch_type)
{
$branch_types = $this->getBranchType();
if (!$branch_types[$branch_type]) {
return [false, '库存类型不支持'];
}
if (!$store['store_id']) {
return [false, '门店ID为空'];
}
if (!$store['store_bn']) {
return [false, '门店编码为空'];
}
$branch_bn = $store['store_bn'];
$prefix = strtolower($branch_types[$branch_type]['type_code']);
if ($prefix) {
$branch_bn = $store['store_bn'] . '_' . $prefix;
}
$branchList = kernel::single('ome_interface_branch')->getList('*', [
'store_id' => $store['store_id'],
'type' => $branch_type,
'branch_bn' => $branch_bn,
'b_type' => '2',
'check_permission' => 'false',
], 0, 1);
$branch = current($branchList);
// 验证仓库编号格式
if (!empty($branch_bn)) {
if (!preg_match('/^[a-zA-Z0-9_-]+$/', $branch_bn)) {
return [false, '仓库编号只允许输入英文字母、数字、下划线和横线'];
}
}
// 验证库内存放点编号格式
if (!empty($store['storage_code'])) {
if (!preg_match('/^[a-zA-Z0-9_-]+$/', $store['storage_code'])) {
return [false, '库内存放点编号只允许输入英文字母、数字、下划线和横线'];
}
}
$data = array(
'branch_bn' => $branch_bn,
'name' => sprintf('[%s]%s', $branch_types[$branch_type]['text'], $store['name']),
'storage_code' => $store['storage_code'] ?: $store['store_bn'],
'type' => $branch_type,
'b_type' => 2,
'b_status' => $store['status'],
'weight' => $store['priority'],
'area' => $store['area'],
'address' => $store['addr'],
'zip' => $store['zip'],
'phone' => $store['tel'],
'uname' => $store['contacter'],
'mobile' => $store['mobile'],
'store_id' => $store['store_id'],
'branch_id' => (int) $branch['branch_id'],
);
// 仓库名拼接上库位
if ($data['storage_code']) {
$data['name'] .= '-'.$data['storage_code'];
}
if ($branch['branch_id']) {
// 更新
$rs = kernel::single('ome_interface_branch')->update($data,[
'branch_id' => $branch['branch_id']
]);
} else {
// 插入
$rs = kernel::single('ome_interface_branch')->save($data);
}
if (!$rs) {
return [false, kernel::database()->errorinfo()];
}
return [true];
}
/**
* 自动权限继承:当新门店添加到经销商时,自动继承权限
* @param int $dealerOrgId 经销商组织ID
* @param int $newStoreOrgId 新门店组织ID
* @return bool 操作结果
*/
private function autoInheritStorePermission($dealerOrgId, $newStoreOrgId) {
if (empty($dealerOrgId) || empty($newStoreOrgId)) {
return false;
}
// 检查 organization 应用是否安装
if (!app::get('organization')->is_installed()) {
return true;
}
try {
// 使用权限继承服务类
$permissionService = kernel::single('organization_organization_permission');
$result = $permissionService->autoInheritPermissionForNewStore($dealerOrgId, $newStoreOrgId);
return $result;
} catch (Exception $e) {
return false;
}
}
/**
* 获取所有参与O2O的门店branch_id
* 用于仓库分配规则中bid=-1的特殊情况
*
* @return array 返回满足条件的门店branch_id数组
*/
public function getAllO2OStoreBranchIds()
{
// 从O2O_STORE表查询is_o2o=1的branch_id
$o2oStoreObj = app::get('o2o')->model('store');
$o2oStores = $o2oStoreObj->getList('branch_id', array('is_o2o' => '1'));
if (empty($o2oStores)) {
return array();
}
$o2oBranchIds = array_column($o2oStores, 'branch_id');
if (empty($o2oBranchIds)) {
return array();
}
// 根据branch_id查询ome_branch表获取满足条件的门店
$branchObj = app::get('ome')->model('branch');
$storeBranches = $branchObj->getList('branch_id', array(
'branch_id' => $o2oBranchIds,
'b_type' => '2',
'disabled' => 'false',
'is_deliv_branch' => 'true',
'check_permission' => 'false',
'b_status' => '1', // 门店仓状态为启用
));
if (empty($storeBranches)) {
return array();
}
return array_column($storeBranches, 'branch_id');
}
/**
* 更新经销商状态,同时更新其下所有门店状态
*
* @param string $status 状态 (active/close)
* @param string $bsBn 经销商编码
* @param array &$errorMsg 错误信息(引用传递)
* @return bool 操作结果
*/
public function updateBsStoreStatus($status, $bsBn, &$errorMsg = '')
{
try {
// 开启事务
$db = kernel::database();
$tran = $db->beginTransaction();
// 状态映射active=1(激活), close=2(关闭)
$statusValue = ($status === 'active') ? 1 : 2;
// 更新经销商下所有门店状态
$organizationObj = app::get('organization')->model('organization');
$orgNo = 'BS_' . $bsBn;
$dealerOrg = $organizationObj->dump(['org_no' => $orgNo, 'org_type' => 3], 'org_id');
if ($dealerOrg) {
// 查找经销商下的所有门店组织
$storeOrgs = $organizationObj->getList('org_id,org_no', [
'parent_id' => $dealerOrg['org_id'],
'org_type' => 2 // 门店类型
]);
if (!empty($storeOrgs)) {
$storeBns = array_column($storeOrgs, 'org_no');
$storeOrgIds = array_column($storeOrgs, 'org_id');
// 如果要关闭门店,先检查每个门店是否还有库存
if ($statusValue == 2) {
$storesWithStock = array();
foreach ($storeBns as $storeBn) {
if ($this->checkStoreHasStock($storeBn)) {
$storesWithStock[] = $storeBn;
}
}
if (!empty($storesWithStock)) {
$db->rollBack();
$errorMsg = '以下门店还有库存,无法关闭:' . implode('、', $storesWithStock);
return false;
}
}
// 更新门店组织状态
$organizationObj->update(
['status' => $statusValue],
['org_id|in' => $storeOrgIds]
);
// 更新O2O门店状态
$storeObj = app::get('o2o')->model('store');
$stores = $storeObj->getList('store_id,branch_id,shop_id,store_bn,status', ['store_bn|in' => $storeBns]);
if (!empty($stores)) {
// 为每个门店记录操作日志和快照
foreach ($stores as $store) {
// 获取门店更新前的快照
$snapshoot = $storeObj->dump(['store_bn' => $store['store_bn']]);
// 记录操作日志
$log_id = app::get('ome')->model('operation_log')->write_log('store_upsert@o2o', $store['store_id'], '经销商关闭,关闭下属门店');
// 记录快照
if ($log_id && $snapshoot) {
$shootMdl = app::get('ome')->model('operation_log_snapshoot');
$snapshoot = json_encode($snapshoot, JSON_UNESCAPED_UNICODE);
$tmp = ['log_id' => $log_id, 'snapshoot' => $snapshoot];
$shootMdl->insert($tmp);
}
}
// 更新门店状态
$storeObj->update(
['status' => $statusValue],
['store_bn|in' => $storeBns]
);
// 更新关联的仓库状态
$branchIds = array_column($stores, 'branch_id');
if (!empty($branchIds)) {
$branchObj = app::get('ome')->model('branch');
$branchObj->update(
['b_status' => $statusValue],
['branch_id|in' => $branchIds]
);
}
// 更新关联的店铺状态
$shopIds = array_column($stores, 'shop_id');
if (!empty($shopIds)) {
$shopObj = app::get('ome')->model('shop');
$shopObj->update(
['s_status' => $statusValue],
['shop_id|in' => $shopIds]
);
}
}
}
}
// 提交事务
$db->commit($tran);
return true;
} catch (Exception $e) {
// 回滚事务
$db->rollBack();
return false;
}
}
/**
* 检查门店是否还有库存
*
* @param string $store_bn 门店编码
* @return bool true表示有库存false表示无库存
*/
public function checkStoreHasStock($store_bn)
{
if (empty($store_bn)) {
return false;
}
// 根据门店编码获取branch_id
$branchId = $this->getBranchIdByStoreBn($store_bn);
if (!$branchId) {
return false;
}
// 查询库存表检查是否有store > 0的记录
$branchProductMdl = app::get('ome')->model('branch_product');
$stockRecord = $branchProductMdl->dump([
'branch_id' => $branchId,
'store|noequal' => 0
], 'id');
return !empty($stockRecord);
}
}