getFindField(['id' => $store_id], "supplier_type"); return $supplier_type; } /** * 获取指定门店的指定信息 * @param $param * [ * merchant_id * store_id_gather 门店id集合 * fields 指定字段 * ] * @return mixed */ public function getAppointStoreInfo($param) { $where = [ 'id' => ['in', $param['store_id_gather']] ]; $fields = $param['fields'] ? $param['fields'] : "*"; try { $StoreModel = new RetailStoreModel(); $list = $StoreModel->getSelect($where, $fields, 'id asc', ''); return $list ? $list : []; } catch (\Exception $e) { return []; } } /** * 门店列表信息(开启和关闭的门店) * @param $param * [ * fields 查询的字段 * merchant_id * state 0正常 1删除 2包含正常与删除 * ] * @return mixed */ public function storeListInfo($param) { $where = [ 'merchantid' => $param['merchant_id'], ]; if ($param['state'] != 2) { $where['state'] = isset($param['state']) ? $param['state'] : 0; } $fields = $param['fields'] ? $param['fields'] : "*"; try { $StoreModel = new RetailStoreModel(); $list = $StoreModel->getSelect($where, $fields, 'id desc', ''); return $list; } catch (\Exception $e) { return []; } } /** * 门店名称列表 * @param $param * [ * store_id_gather 门店id 集合 * ] * @return mixed */ public function storeNameList($param) { try { $StoreModel = new RetailStoreModel(); $list = $StoreModel->getFindField([ 'id' => ['in', $param['store_id_gather']] ], "storetag", true); return callBack(statusCode()['success'], "查询成功", ['list' => $list]); } catch (\Exception $e) { return callBack(statusCode()['success'], "查询成功", ['list' => []]); } } /** * 获取门店列表(开启和关闭的门店) * @param $parameter * [ * merchant_id * ] * @return mixed */ public function getStoreList($parameter) { try { $where = array( 'merchantid' => $parameter['merchant_id'], 'state' => 0, ); $storeModel = new RetailStoreModel(); $storeList = $storeModel->getSelect($where, "id,storetag"); return $storeList; } catch (\Exception $e) { return []; } } /** * 获取门店列表接口,仅获取ID和名称(门店开启关闭状态可筛选,可搜索) * @param $param * $param['merchant_id'] 商户ID * $param['industry_id'] 筛选的行业ID * $param['strict_industry']是否是严格模式筛选行业下的门店 1开启 0关闭 * $param['store_name'] 门店名称(模糊搜索) * $param['store_status'] 1开启的门店 2关闭的门店 3开启和关闭的门店 * $param['page'] 页码 * $param['limit'] 每页获取数量 * @return Array */ public function getStoreLimitList($param) { $param['page'] = is_numeric($param['page']) ? $param['page'] : 1; $param['limit'] = is_numeric($param['limit']) ? $param['limit'] : 10; $StoreModel = new RetailStoreModel(); $map = array( 'merchantid' => $param['merchant_id'], 'store_status' => $param['store_status'] == 1 ? 0 : ($param['store_status'] == 2 ? 1 : ['in', '0,1']), 'state' => 0, ); if (!empty($param['store_name'])) { $map['storetag'] = array('like', '%' . $param['store_name'] . '%'); } if (!empty($param['industry_id'])) { if ($param['strict_industry'] == 1) { $map['industry_id'] = $param['industry_id']; } else { $map['industry_id'] = ['in', [0, $param['industry_id']]]; } } $list = $StoreModel->getSelect($map, 'id,storetag as store_name,store_status,industry_id', 'store_status asc,id asc', $param['page'] . ',' . $param['limit']); return callBack(statusCode()['success'], empty($list) ? '暂无数据' : '获取成功', $list); } /** * 获取门店名称-针对商户大量列表数据读取门店 * @param $store_id 门店id * @param array $store_List 临时处理的门店名称列表 * @return mixed|string */ public function getStoreName($store_id = null, &$store_List = array()) { if (!$store_id) { return ''; } try { if (!$store_List[$store_id]) { $StoreModel = new RetailStoreModel(); $store_List[$store_id] = $StoreModel->getFindField(array('id' => $store_id), 'storetag'); } } catch (\Exception $e) { return '未知门店'; } return $store_List[$store_id] ? $store_List[$store_id] : '未知门店'; } /** * 获取门店配置-赊销配置 * @param $store_id 门店id * @return mixed|string */ public function getCreditConfig($store_id = null, $field = 'is_credit, credit_num, credit_quota') { if (!$store_id) { return ['status' => 0, 'msg' => '门店参数缺失!']; } $StoreModel = new StoreConfigModel(); $store = $StoreModel->getFind(['store_id' => $store_id], $field); if (!$store) { return ['status' => 0, 'msg' => '门店信息有误!']; } return $store; } /** * 门店新增/修改 2021年1月19日09:44:20 * @param $param * [ * merchant_id * platform_type 商户平台类型 1默认系统 2微礼平台 * third_code 对应的第三方平台的门店编码 * ] * @return array * @author GuYunQinFeng */ public function operateStoreInfo($param) { $FranchiseeModel = new RetailFranchiseeModel(); $StoreJurisdictionModel = new StoreJurisdictionModel(); $StoreModel = new RetailStoreModel(); $merchant_id = $param['merchant_id']; $platform_type = $param['platform_type'] ? $param['platform_type'] : 1; if ( empty($param['latitude']) || empty($param['longitude']) || empty($param['address']) || empty($param['dadastatus']) || empty($param['store_class']) || empty($param['province_id']) || empty($param['city_id']) || empty($param['area_id']) ) { return ['status' => 0, 'msg' => '请完善基本信息']; } // 判断是否存在门店id $storeItem = [ 'storetag' => $param['storetag'], 'shopimg_id' => $param['shopimg_id'], 'merchantid' => $merchant_id, 'longitude' => $param['longitude'], 'latitude' => $param['latitude'], 'address' => $param['address'], 'industry_id' => $param['industry_id'] ? $param['industry_id'] : 0, 'detail_address' => $param['detail_address'], 'dadastatus' => $param['dadastatus'] == 2 ? 2 : 1, 'attribute' => $param['attribute'], 'origin_shop_id' => $param['origin_shop_id'], 'username' => $param['username'], 'password' => $param['password'], ]; $CitysModel = new CitysModel(); $storeItem['province'] = $CitysModel->getFindField(['cityid' => $param['province_id']], 'city_name'); $storeItem['city'] = $CitysModel->getFindField(['cityid' => $param['city_id']], 'city_name'); $storeItem['area'] = $CitysModel->getFindField(['cityid' => $param['area_id']], 'city_name'); //达达商家信息判断 if ($param['dadastatus'] == 2) { if (empty($param['attribute']) || empty($param['origin_shop_id'])) { return ['status' => 0, 'msg' => '请完善达达门店类型与门店编码']; } if (empty($param['username']) || empty($param['password'])) { return ['status' => 0, 'msg' => '请完善达达商家账号和密码']; } } // 加盟店信息判断 if ($param['store_class'] == 2) { if (empty($param['account_number']) || empty($param['name'])) { return ['status' => 0, 'msg' => '加盟点收款账户不能为空']; } if (!in_array($param['clearing_form'], ['1', '2', '3'])) { return ['status' => 0, 'msg' => '加盟店结算类型有误']; } if ($param['clearing_form'] == 1 && empty($param['opening_bank'])) { return ['status' => 0, 'msg' => '请选择加盟店结算开户行']; } if (isset($param['rate'])) { if (is_numeric($param['rate']) && floatval($param['rate']) >= 0) { $rate = explode('.', $param['rate']); // 费率大小判断 if ($rate[0] >= 100) { return ['status' => 0, 'msg' => '费率不能大于100%']; } // 费率小数点位数判断 if (strlen($rate[1]) > 2) { return ['status' => 0, 'msg' => '费率的小数不能超过两位']; } } else { return ['status' => 0, 'msg' => '费率必须是大于等于0的数字']; } } else { return ['status' => 0, 'msg' => '费率不能为空']; } $franchiseItem['rate'] = $param['rate']; $franchiseItem['account_number'] = $param['account_number']; $franchiseItem['name'] = $param['name']; $franchiseItem['type'] = $param['period_radio']; $franchiseItem['clearing_form'] = $param['clearing_form']; if ($franchiseItem['clearing_form'] == 1) { $franchiseItem['opening_bank'] = $param['opening_bank']; } } //新增门店时微礼平台验证参数 if ($platform_type == 2 && empty($param['id'])) { if (empty($param['third_code'])) { return ['status' => 0, 'msg' => '请输入Q3 ERP门店编码']; } $id = $StoreModel->getFindField([ 'state' => 0, 'third_code' => $param['third_code'], 'merchantid' => $merchant_id ], 'id'); if (!empty($id)) { return ['status' => 0, 'msg' => '该门店编码已存在']; } $ThirdClass = new Third(); $thirdResult = $ThirdClass->storeCodeVerify([ 'merchant_id' => $merchant_id, 'platform_type' => $platform_type, 'type' => 2, 'third_code' => $param['third_code'] ]); if ($thirdResult['status'] == 0) { return ['status' => 0, 'msg' => 'Q3 ERP平台编码验证失败' . $thirdResult['message']]; } $storeItem['third_code'] = $param['third_code']; } else if ($param['third_code'] && empty($param['id'])) { $storeItem['third_code'] = $param['third_code']; } if (!empty($param['id'])) { // 编辑操作 $store_id = $param['id']; $store = $StoreModel->getFind(['id' => $store_id, 'merchantid' => $merchant_id]); if (empty($store)) { return ['status' => 0, 'msg' => '您的访问有误']; } // if ($store['industry_id'] && empty($param['industry_id'])) { // return ['status' => 0, 'msg' => '暂不支持取消行业']; // } // 行业id处理、存在旧行业且修改行业 if ($param['industry_id'] && $store['industry_id'] && $param['industry_id'] != $store['industry_id']) { // 是否存在商品标签使用 $LabelInventoryModel = new LabelInventoryModel(); $labelArrMap = [ 'status' => 1, 'industry_id' => $store['industry_id'], ]; // 查询门店+行业id下全部标签 $labelIdArr = $LabelInventoryModel->getFindField($labelArrMap, 'id', true); if ($labelIdArr) { //查询商品是否存在使用该行业的标签 $GoodsLabelLinkModel = new GoodsLabelLinkModel(); foreach ($labelIdArr as $val) { $inLinkUse = $GoodsLabelLinkModel->getFind(['label_id' => $val, 'store_id' => $store_id], 'id'); if ($inLinkUse) { return ['status' => 0, 'msg' => '当前门店存在商品使用了原行业的标签,暂不可修改行业']; } } } //判断该门店的商品是否有使用的分类属于该行业的 $RetailGoodsModel = new RetailGoodsModel(); $inUseMap = [ 'goods.store_id' => $store_id, 'goods.status' => ['in', '0,1'], //商品状态 0,正常,1,下架,2,删除。 'class.status' => 0, //商品分类状态 0,正常,1,删除。 'industry.status' => 1, //行业状态 1正常 2删除 ]; $inUseNum = $RetailGoodsModel->getStoreIsUseClassIndustry($inUseMap); if ($inUseNum > 0) { return ['status' => 0, 'msg' => '当前门店的商品有使用属于该行业的分类']; } } $res = $StoreModel->updateOrder(['id' => $store_id, 'merchantid' => $merchant_id], $storeItem); // 修改加盟店配置信息 if ($store['store_class'] == 2) { $result = $FranchiseeModel->updateOrder(array('store_id' => $store_id), $franchiseItem); } if ($res || $result) { //操作日志记录 $source = 0; //请求来源: 0pc系统 1小助手 $type = 3; //平台:1合伙人端 2代理商端 3商户端 4门店端 $request_data = json_encode($_POST); //请求参数 json数据 $desc = '编辑门店信息'; //操作行为描述 action_log($source, $type, $request_data, $desc); return ['status' => 1, 'msg' => '编辑成功']; } else { return ['status' => 0, 'msg' => '未更新']; } } else { // 新增操作 $storeNum = $StoreModel->getCount(['merchantid' => $merchant_id, 'state' => 0]); $MerchantModel = new RetailMerchantModel(); $mer_store_num = $MerchantModel->getFindField(['id' => $merchant_id], 'storenum'); if ($mer_store_num <= $storeNum) { return ['status' => 0, 'msg' => '添加失败:添加门店已超过可创建门店数']; } $one = $StoreModel->getCount(['merchantid' => $merchant_id, 'store_type' => 0]); $storeItem['store_type'] = $one ? 1 : 0; $storeItem['store_class'] = $param['store_class']; $storeItem['supplier_type'] = $param['supplier_type'] ? $param['supplier_type'] : 1; $Role = new Role(); $storeItem['jur_group_id'] = $Role->createSystemGroup([ 'type' => 4, 'merchant_id' => $merchant_id, ]); // 门店信息添加 $res = $StoreModel->addOrder($storeItem); if (!$res) { return ['status' => 0, 'msg' => '添加失败']; } // 加盟店关联信息 if ($storeItem['store_class'] == 2) { $franchiseItem['store_id'] = $res; $franchiseItem['merchant_id'] = $merchant_id; $franchiseItem['account_type'] = 1; //账号类型:1加盟商 2商户 $franchiseItem['add_time'] = strtotime(date('Y-m-d', time())); $FranchiseeModel->addOrder($franchiseItem); } //添加默认仓库 $content = [ 'name' => '默认采购仓', 'number' => 'A_001', 'province' => '北京', 'city' => '北京市', 'area' => '海淀区', 'address' => '北京市海淀区', 'measure_area' => 100, 'person_name' => '小李', 'person_phone' => '18888888888', 'merchant_id' => $merchant_id, 'store_id' => $res, ]; $WarehouseClass = new Warehouse(); $WarehouseClass->storePurchaseWarehouseOperation($content); $content['name'] = '默认供给仓'; $WarehouseClass->storeSaleWarehouseOperation($content); $StoreJurisdictionModel->add(['storeid' => $res]); $StoreConfigModel = new StoreConfigModel(); $StoreConfigModel->addOrder(['store_id' => $res]); $StoreXcxConfigModel = new RetailStoreXcxConfigModel(); $StoreXcxConfigModel->addOrder(['storeid' => $res]); //操作日志记录 $source = 0; //请求来源: 0pc系统 1小助手 $type = 3; //平台:1合伙人端 2代理商端 3商户端 4门店端 $request_data = json_encode($param); //请求参数 json数据 $desc = '添加门店'; //操作行为描述 action_log($source, $type, $request_data, $desc); return ['status' => 1, 'msg' => '添加成功']; } } /** * 保存门店商城设置 * @param $param * $param['merchant_id'] 商户ID * $param[''] * @return mixed */ public function storeXcxSet($param) { $business_time_verify = $this->handleTime($param['business_time']); if ($business_time_verify['status'] == 0) { return callBack(statusCode()['error'], '营业时间' . $business_time_verify['message']); } $business_verify = $this->handleTime($param['business']); if ($business_verify['status'] == 0) { return callBack(statusCode()['error'], '营业时间' . $business_verify['message']); } $item = [ 'merchantid' => $param['merchant_id'],//商户id 'status' => $param['status'],//是否开启商城0关闭1开启 'skip' => $param['skip'],//0仅支持商家配送 1不支持商家配送 'self_pick' => $param['self_pick'],//0支持到店自提 1不支持到店自提 'address' => $param['address'],//地址 'latitude' => $param['latitude'],//纬度 'longitude' => $param['longitude'],//经度 'smmoney' => $param['smmoney'],//起送价 'phone' => $param['phone'],//电话 'chek' => $param['chek'],//在配送半径职位是否允许下单 0:允许 1:不允许 'addtime' => time(),// 'math' => $param['math'],// 'tip' => $param['tip'],// 'business_time' => $business_time_verify['data'], 'business' => $business_verify['data'], 'open_freight_collect' => $param['open_freight_collect'], 'business_non_order' => $param['business_non_order'] ? $param['business_non_order'] : 2,//非营业时间下单 'delivery_status' => $param['delivery_status'],//免配送费 0关闭 1开启 'delivery_cost' => $param['delivery_cost'],//免配送费门槛 ]; $StoreModel = new RetailStoreModel(); $ret = $StoreModel->updateOrder(['id' => $param['store_id']], $item); // 处理电子围栏数据 if (isset($param['delivery_fences']) && !empty($param['delivery_fences'])) { $FenceModel = new \Common\Model\StoreDeliveryFenceModel(); $fenceData = is_string($param['delivery_fences']) ? json_decode($param['delivery_fences'], true) : $param['delivery_fences']; $FenceModel->saveFenceData($param['store_id'], $param['merchant_id'], $fenceData); } // 兼容旧的fence_data参数 elseif (isset($param['fence_data']) && !empty($param['fence_data'])) { $FenceModel = new \Common\Model\StoreDeliveryFenceModel(); $fenceData = is_string($param['fence_data']) ? json_decode($param['fence_data'], true) : $param['fence_data']; $FenceModel->saveFenceData($param['store_id'], $param['merchant_id'], $fenceData); } $express_status = $param['express_status'] ? $param['express_status'] : 0; $ConfigModel = new StoreConfigModel(); $ConfigModel->setConfig($param['store_id'], ['delivery_template_status' => $express_status]); //修改快递发货状态 $StoreXcxConfigModel = new RetailStoreXcxConfigModel(); $StoreXcxConfigModel->updateOrder(['storeid' => $param['store_id']], [ 'send_delayed_time' => $param['send_delayed_time'] ? $param['send_delayed_time'] : 0, 'pickup_delayed_time' => $param['pickup_delayed_time'] ? $param['pickup_delayed_time'] : 0, 'auto_set_time' => $param['auto_set_time'] ? $param['auto_set_time'] : 0, ]);//商城下单订单配送、自提延时的时间(单位:分钟) if ($ret !== false) { //操作日志记录 action_log($param['source'], $param['type'], json_encode($_POST), '门店设置-门店信息设置'); return callBack(statusCode()['success'], '保存成功'); } else { return callBack(statusCode()['error'], '保存失败'); } } /** * 门店设置的自提/配送时间段转换为字符串 * @param array $time_arr * @return string */ private function handleTime($time_arr = []) { if (empty($time_arr)) { return callBack(statusCode()['error'], '至少设置一个'); } // 检查每个时间段的有效性 foreach ($time_arr as $index => $time_period) { if (!empty($time_period) && !empty($time_period[0]) && !empty($time_period[1])) { // 验证时间格式 if (!$this->isValidTimeFormat($time_period[0]) || !$this->isValidTimeFormat($time_period[1])) { return callBack(statusCode()['error'], '时间格式错误'); } } } // 检查时间段之间的冲突 for ($i = 0; $i < count($time_arr); $i++) { if (empty($time_arr[$i]) || empty($time_arr[$i][0]) || empty($time_arr[$i][1])) { continue; } for ($j = $i + 1; $j < count($time_arr); $j++) { if (empty($time_arr[$j]) || empty($time_arr[$j][0]) || empty($time_arr[$j][1])) { continue; } if ($this->isTimeConflict($time_arr[$i], $time_arr[$j])) { return callBack(statusCode()['error'], '时间段存在冲突'); } } } $time1 = []; foreach ($time_arr as $key => $val) { if (!empty($val) && !empty($val[0]) && !empty($val[1])) { $time1[] = $val[0] . '-' . $val[1]; } } return callBack(statusCode()['success'], '成功', implode(',', $time1)); } /** * 验证时间格式是否正确 * @param string $time 时间字符串,格式为 HH:MM * @return bool */ private function isValidTimeFormat($time) { return preg_match('/^([01]?[0-9]|2[0-3]):[0-5][0-9]$/', $time); } /** * 检查两个时间段是否冲突(支持跨天时间段) * @param array $time1 时间段1 [开始时间, 结束时间] * @param array $time2 时间段2 [开始时间, 结束时间] * @return bool true表示冲突,false表示不冲突 */ private function isTimeConflict($time1, $time2) { $start1 = $time1[0]; $end1 = $time1[1]; $start2 = $time2[0]; $end2 = $time2[1]; // 判断是否为跨天时间段 $isCrossDay1 = $this->isCrossDay($start1, $end1); $isCrossDay2 = $this->isCrossDay($start2, $end2); if (!$isCrossDay1 && !$isCrossDay2) { // 两个都是同一天的时间段 return $this->isNormalTimeConflict($start1, $end1, $start2, $end2); } else if ($isCrossDay1 && !$isCrossDay2) { // time1跨天,time2不跨天 return $this->isCrossDayConflictWithNormal($start1, $end1, $start2, $end2); } else if (!$isCrossDay1 && $isCrossDay2) { // time1不跨天,time2跨天 return $this->isCrossDayConflictWithNormal($start2, $end2, $start1, $end1); } else { // 两个都是跨天时间段 return $this->isCrossDayConflictWithCrossDay($start1, $end1, $start2, $end2); } } /** * 判断时间段是否跨天 * @param string $start 开始时间 * @param string $end 结束时间 * @return bool */ private function isCrossDay($start, $end) { return strtotime($start) > strtotime($end); } /** * 检查两个同一天的时间段是否冲突 * @param string $start1 时间段1开始时间 * @param string $end1 时间段1结束时间 * @param string $start2 时间段2开始时间 * @param string $end2 时间段2结束时间 * @return bool */ private function isNormalTimeConflict($start1, $end1, $start2, $end2) { $startTime1 = strtotime($start1); $endTime1 = strtotime($end1); $startTime2 = strtotime($start2); $endTime2 = strtotime($end2); return !($endTime1 <= $startTime2 || $endTime2 <= $startTime1); } /** * 检查跨天时间段与普通时间段是否冲突 * @param string $crossStart 跨天时间段开始时间 * @param string $crossEnd 跨天时间段结束时间 * @param string $normalStart 普通时间段开始时间 * @param string $normalEnd 普通时间段结束时间 * @return bool */ private function isCrossDayConflictWithNormal($crossStart, $crossEnd, $normalStart, $normalEnd) { // 将时间转换为分钟数便于比较 $crossStartMinutes = $this->timeToMinutes($crossStart); $crossEndMinutes = $this->timeToMinutes($crossEnd); $normalStartMinutes = $this->timeToMinutes($normalStart); $normalEndMinutes = $this->timeToMinutes($normalEnd); // 跨天时间段覆盖两个区间: // 1. 当天的 crossStart 到 23:59 (crossStartMinutes 到 1439) // 2. 次日的 00:00 到 crossEnd (0 到 crossEndMinutes) // 检查普通时间段是否与当天后半部分冲突 $conflict1 = ($normalStartMinutes <= 1439) && ($normalEndMinutes > $crossStartMinutes); // 检查普通时间段是否与次日前半部分冲突 $conflict2 = ($normalStartMinutes < $crossEndMinutes) && ($normalEndMinutes >= 0); return $conflict1 || $conflict2; } /** * 检查两个跨天时间段是否冲突 * @param string $start1 时间段1开始时间 * @param string $end1 时间段1结束时间 * @param string $start2 时间段2开始时间 * @param string $end2 时间段2结束时间 * @return bool */ private function isCrossDayConflictWithCrossDay($start1, $end1, $start2, $end2) { // 将时间转换为分钟数 $start1Minutes = $this->timeToMinutes($start1); $end1Minutes = $this->timeToMinutes($end1); $start2Minutes = $this->timeToMinutes($start2); $end2Minutes = $this->timeToMinutes($end2); // 两个跨天时间段: // 时间段1: start1 ~ 23:59 + 00:00 ~ end1 // 时间段2: start2 ~ 23:59 + 00:00 ~ end2 // 检查当天后半部分是否冲突 (start1~23:59 与 start2~23:59) $conflict1 = !($start1Minutes >= 1439 || $start2Minutes >= 1439) && !(($start1Minutes >= $start2Minutes) || ($start2Minutes >= $start1Minutes)); // 检查次日前半部分是否冲突 (00:00~end1 与 00:00~end2) $conflict2 = !($end1Minutes <= 0 || $end2Minutes <= 0) && !(($end1Minutes <= $end2Minutes) || ($end2Minutes <= $end1Minutes)); // 如果两个跨天时间段的开始时间或结束时间有重叠,就认为冲突 return $conflict1 || $conflict2; } /** * 将时间字符串转换为分钟数 * @param string $time 时间字符串 HH:MM * @return int 从00:00开始的分钟数 */ private function timeToMinutes($time) { list($hour, $minute) = explode(':', $time); return intval($hour) * 60 + intval($minute); } }