validate()) { return $this->getErrorSummary(false)[0]; } $goods = Goods::findOne([ 'id' => $this->id, 'is_delete' => 0, 'status' => 1 ]); if (!empty($goods->verify_card_id)) { $ids = explode(',', $goods->verify_card_id); $verify_card = Tools::getVerifyList($ids); } else { $verify_card = []; } if (!$goods) { return [ 'code' => 1, 'msg' => '商品已下架' ]; } $mch = null; $pic_list = GoodsPic::find()->select('pic_url')->where(['goods_id' => $goods->id, 'is_delete' => 0])->asArray()->all(); $is_favorite = 0; $service_list = explode(',', $goods->service); // 默认商品服务 if (!$goods->service) { $option = Option::get('good_services', $goods->store_id, 'admin', []); foreach ($option as $item) { if (!empty($item['is_default'])) { $service_list = explode(',', $item['service']); break; } } } $new_service_list = []; if (is_array($service_list)) { foreach ($service_list as $item) { $item = trim($item); if ($item) { $new_service_list[] = $item; } } } //展示新人专享活动商品信息 $this->activity_new_user($this->activity_new_user_id, $goods, $md_goods); //展示砍价活动商品信息 $cutGoods = null; if($this->activity_cut_price_id){ $cutGoods = ActivityCutPriceGoods::findOne(['activity_id' => $this->activity_cut_price_id, 'goods_id' => $goods->id, 'is_delete' => 0]); } $new_price = $goods->price; $price_attr = Json::decode($goods->attr); $price = []; if (is_array($price_attr)) { foreach ($price_attr as $v) { if (is_object($v) && $v->price > 0) { $price[] = $v->price; } else { $price[] = floatval($new_price); } } } else { $price = [$goods->price]; } $res_url = GetInfo::getVideoInfo($goods->video_url); $goods->video_url = $res_url['url']; if ($goods->is_negotiable) { $min_price = Goods::GOODS_NEGOTIABLE; } else { $min_price = sprintf('%.2f', min($price)); } $res = CommonGoods::getMMPrice([ 'attr' => $goods->attr, 'attr_setting_type' => $goods->attr_setting_type, 'share_type' => $goods->share_type, 'share_commission_first' => $goods->share_commission_first, 'price' => $new_price, 'individual_share' => $goods->individual_share, 'mch_id' => $goods->mch_id, 'is_level' => $goods->is_level, 'use_attr' => $goods->use_attr, ]); $attr = $price_attr; $goodsPrice = $new_price; $isMemberPrice = false; if ($res['user_is_member'] === true && count($attr) === 1 && $attr[0]['attr_list'][0]['attr_name'] == '默认') { $goodsPrice = $res['min_member_price'] ? $res['min_member_price'] : $new_price; $isMemberPrice = true; } $GoodsFullMinus = GoodsFullMinus::find() ->select('*') ->where(['store_id' => $goods->store_id, 'goods_id' => $goods->id]) ->orderBy('full_minus_num ASC')->asArray()->all(); $seckill_activity_arr = null; $seckill_activity_goods = []; if ($this->is_seckill) { //秒杀活动 $seckill_activity_goods = SeckillActivityGoods::find()->alias('sag')->where(['sag.goods_id' => $goods->id]) ->leftJoin(['sa' => SeckillActivity::tableName()], 'sag.activity_id = sa.id') ->andWhere(['AND', ['sa.is_delete' => 0, 'sag.is_delete' => 0], ['>', 'sa.end_time', time()]]) ->andWhere(['OR', ['sa.is_platform' => 1, 'sa.is_platform_audit' => 1, 'sa.status' => 1], ['sa.is_platform' => 0]]) ->select('sa.id, sa.self_limit_num, sa.order_limit_num, sa.start_time, sa.end_time, sag.attr, sag.seckill_num, sag.seckill_price, sag.use_attr, sag.sale_num, sag.virtual_sales, sag.virtual_num')->asArray()->all(); } if (!empty($seckill_activity_goods) && empty($this->activity_new_user_id) && empty($this->activity_cut_price_id) && empty($this->is_pt)) { $last_names = array_column($seckill_activity_goods,'start_time'); array_multisort($last_names, SORT_ASC, $seckill_activity_goods); foreach ($seckill_activity_goods as $activity_good) { if (($activity_good['seckill_num'] + $activity_good['sale_num'] + $activity_good['virtual_sales']) > 0) { $activity_good['progress'] = sprintf('%.2f', (($activity_good['sale_num'] + $activity_good['virtual_sales']) / ($activity_good['seckill_num'] + $activity_good['sale_num'] + $activity_good['virtual_sales'])) * 100); } else { $activity_good['progress'] = 0; } $activity_good['seckill_num'] <= 0 && $activity_good['progress'] = 100; $activity_good['price'] = $new_price; $activity_good['seckill_price'] = sprintf('%.2f', $activity_good['seckill_price']); if ($activity_good['start_time'] < time()) { //活动进行中 前端展示距离结束 $activity_good['status'] = 1; $seckill_activity_arr = $activity_good; goto seckill_activity_arr; } if ($activity_good['start_time'] >= time()) {//活动进行中 前端展示距离开始 $activity_good['status'] = 2; $activity_good['progress'] = 0; $seckill_activity_arr = $activity_good; goto seckill_activity_arr; } } seckill_activity_arr: } if (!empty($seckill_activity_arr)) { $seckill_activity_arr['attr'] = json_decode($seckill_activity_arr['attr'], true); if (!empty($seckill_activity_arr['attr'])) { foreach ($seckill_activity_arr['attr'] as &$activity_attr) { $activity_attr['seckill_price'] = sprintf('%.2f', $activity_attr['seckill_price']); } } } //拼团活动信息 $ptGoodsActivity = PtActivityGoods::find()->alias('pag')->where(['pag.is_delete' => 0, 'pa.is_delete' => 0, 'pa.store_id' => $goods->store_id]) ->leftJoin(['pa' => PtActivity::tableName()], 'pag.activity_id = pa.id') ->andWhere(['OR', ['pag.goods_id' => $goods->id, 'pa.is_platform' => 1, 'pa.is_platform_audit' => 1, 'pa.status' => 1], ['pag.goods_id' => $goods->id, 'pa.is_platform' => 0]]) ->select('pag.pt_price, pag.sale_num, pag.virtual_sales, pag.attr, pa.party_size, pa.party_type, pa.party_goods_count, pa.split_time, pa.head_integral, pa.id, pa.head_is_free') ->andWhere(['AND', ['<', 'pa.start_time', time()], ['>', 'pa.end_time', time()]])->asArray()->one(); if ($ptGoodsActivity && !empty($this->is_pt)) { $split_time = $ptGoodsActivity['split_time']; $party_size = $ptGoodsActivity['party_size']; $party_type = $ptGoodsActivity['party_type']; $party_goods_count = $ptGoodsActivity['party_goods_count']; $party_id = $ptGoodsActivity['id']; //当前商品拼团数据 $pt_arr = PtActivityOrderDetail::find()->alias('pod') ->where(['store_id' => $goods->store_id, 'pod.goods_id' => $goods->id]) ->leftJoin(['po' => PtActivityOrder::tableName()], 'pod.order_id = po.id') ->andWhere(['po.pt_number' => 0, 'po.is_pay' => 1, 'po.is_pt_finish' => 0]) ->select('po.id, po.pay_time')->orderBy('po.created_at desc')->asArray()->all(); $arr = []; foreach ($pt_arr as $index => $item) { $arr[$index]['id'] = $item['id']; $end_time = ($item['pay_time'] + ($split_time * 60 * 60)) - time(); $arr[$index]['end_time'] = $end_time > 0 ? $end_time : 0; $arr[$index]['user_list'] = PtActivityOrder::find()->alias('o')->where(['o.is_pay' => 1]) ->leftJoin(['u' => User::tableName()], 'o.user_id = u.id') ->leftJoin(['su' => SaasUser::tableName()], 'u.binding = su.mobile') ->andWhere(['OR' , ['o.id' => $item['id']], ['o.pt_number' => $item['id']]]) ->select('su.avatar, su.name')->limit(2)->asArray()->all(); $arr[$index]['surplus_num'] = $party_size - count($arr[$index]['user_list']); $arr[$index]['party_type'] = $party_type; $arr[$index]['surplus_num_goods'] = 0; if($party_type == 1){ $goodsCountQuery = PtActivityOrderDetail::find()->alias('pod') ->leftJoin(['po' => PtActivityOrder::tableName()], 'pod.order_id = po.id') ->where(['po.is_pay' => 1, 'pod.is_delete' => 0]) ->andWhere(['OR' , ['po.id' => $item['id']], ['po.pt_number' => $item['id']]]); $goodsCount = $goodsCountQuery->sum('pod.num'); $arr[$index]['surplus_num_goods'] = $party_goods_count - (int)$goodsCount; } } //拼团商品拼团数据 $order_detail = PtActivityOrderDetail::find()->alias('pod')->where(['store_id' => $goods->store_id]) ->leftJoin(['po' => PtActivityOrder::tableName()], 'pod.order_id = po.id') ->andWhere(['po.pt_number' => 0, 'po.is_pay' => 1, 'po.is_pt_finish' => 0]) ->andWhere(['<>', 'pod.goods_id', $goods->id]) ->select('pod.goods_id, pod.goods_name, pod.pic, pod.total_price pt_price, po.pay_time, pod.activity_id, po.user_id, po.id, po.store_id') ->orderBy('num desc')->asArray()->all(); // $current_activity_num = count($order_detail); // $order_detail = $order_detail[0]; $goods_activity = null; if ($order_detail) { foreach ($order_detail as $index => $value) { $activity = PtActivity::findOne($value['activity_id']); $goods_activity[$index]['name'] = $value['goods_name']; $goods_activity[$index]['cover_pic'] = $value['pic']; $saas_user = User::find()->alias('u')->leftJoin(['su' => SaasUser::tableName()], 'u.binding = su.mobile') ->select('su.name, su.avatar')->where(['u.id' => $value['user_id']])->asArray()->one(); $goods_activity[$index]['avatar'] = $saas_user['avatar']; $goods_activity[$index]['end_time'] = 0; $goods_activity[$index]['pt_price'] = $value['pt_price']; if (($value['pay_time'] + ($activity->split_time * 60 * 60)) > time()) { $goods_activity[$index]['end_time'] = ($value['pay_time'] + ($activity->split_time * 60 * 60)) - time(); } $goods_activity[$index]['goods_id'] = $value['goods_id']; $goods_activity[$index]['pt_number'] = $value['id']; $goods_activity[$index]['store_id'] = $value['store_id']; } } //获取活动规则 $aboutArticle = AboutArticle::findOne(['store_id' => $goods->store_id, 'is_delete' => 0, 'type' => 1]); $pt_activity = [ 'party_type' => (int)$party_type, 'is_join_pt' => (bool)$ptGoodsActivity, 'current_activity' => $arr, 'pt_price' => (string)$ptGoodsActivity['pt_price'], 'sale_num' => ((int)$ptGoodsActivity['sale_num'] + (int)$ptGoodsActivity['virtual_sales']), 'current_activity_num' => count($arr), 'goods_activity' => $goods_activity, 'rule' => $aboutArticle->desc ?? '', 'head_integral' => (int)$ptGoodsActivity['head_integral'], 'id' => $party_id, 'head_is_free' => (int)$ptGoodsActivity['head_is_free'], ]; $goods->use_attr = 1; } else { $pt_activity = null; } $goods_attr = $goods->attr; if (!empty($ptGoodsActivity) && !empty($this->is_pt)) { $goods_attr = json_decode($goods_attr, true); $pt_attr = json_decode($ptGoodsActivity['attr'], true); if (!$goods->use_attr) { $goods_attr = [$goods_attr[0]]; $pt_attr = [$pt_attr[0]]; } foreach ($goods_attr as &$g_attr) { $g_attr_id = array_column($g_attr['attr_list'], 'attr_id'); sort($g_attr_id); foreach ($pt_attr as $p_attr) { $p_attr_id = array_column($p_attr['attr_list'], 'attr_id'); sort($p_attr_id); if (!array_diff($g_attr_id, $p_attr_id)) { $attr_name = $ptGoodsActivity['party_size'] . "人团"; if($ptGoodsActivity['party_type'] == 1){ $attr_name = $ptGoodsActivity['party_goods_count'] . "个商品成团"; } $g_attr['attr_list'] = array_merge([ [ "attr_id" => -1, "attr_name" => $attr_name, ] ], $g_attr['attr_list']); $g_attr['price'] = $p_attr['pt_price']; } } } $last_names = array_column($pt_attr,'pt_price'); array_multisort($last_names,SORT_DESC, $pt_attr); $pt_activity['pt_price'] = (string)($pt_attr[0]['pt_price']); $goods_attr = json_encode($goods_attr); } $storeInfo = Store::find()->where(['id'=> $goods->store_id,'is_delete'=>0])->select(['id', 'name', 'logo', 'coordinate', 'created_at', 'category_id', 'tags', 'sales', 'rank', 'per_spend','business_model','address','contact_tel'])->asArray()->one(); if($goods->goods_send_profit > 0 || $goods->goods_take_price > 0){ $is_league = 1; }else{ $is_league = 0; } // $send_profit_model = Option::findOne(['name' => 'store_send_profit']);//平台让利比例 // $this_store_send_profit_model= Option::findOne(['name' => 'store_this_profit','store_id' => $goods->store_id]); // if($this_store_send_profit_model->value > 0){ // $basic_send_profit = (float)$this_store_send_profit_model->value; // }else{ // $basic_send_profit = (float)$send_profit_model->value; // } $goods_send_profit = $goods->goods_send_profit * 0.01; $goods_take_profit = $goods->goods_take_price * 0.01; $data = [ 'cutGoods' => $cutGoods, 'activityPrice' => sprintf('%.2f', $goods->activityPrice), 'id' => $goods->id, 'is_league' => $is_league, 'goods_send_profit' => $goods_send_profit, 'goods_take_profit' => $goods_take_profit, 'status' => $goods->status, 'pic_list' => $pic_list, 'attr' => $goods_attr, 'cover_pic' => $goods->cover_pic, 'is_negotiable' => $goods->is_negotiable, 'max_price' => sprintf('%.2f', max($price)), 'min_price' => $min_price, 'name' => $goods->name, 'cat_id' => $goods->cat_id, 'price' => sprintf('%.2f', $goodsPrice), 'detail' => $goods->detail, 'sales' => $goods->getSalesVolume() + $goods->virtual_sales, 'attr_group_list' => $goods->getAttrGroupList($this->is_pt, $goods->use_attr), 'num' => $goods->getNum(), 'is_favorite' => $is_favorite, 'service_list' => $new_service_list, 'original_price' => sprintf('%.2f', $goods->original_price), 'video_url' => $goods->video_url, 'unit' => $goods->unit, 'use_attr' => intval($goods->use_attr), 'mch' => $mch, 'max_share_price' => sprintf('%.2f', $res['max_share_price']), 'min_member_price' => sprintf('%.2f', $res['min_member_price']), 'is_share' => $res['is_share'], 'is_level' => $res['is_level'], 'is_member_price' => $isMemberPrice, 'full_minus' => $GoodsFullMinus, 'verify_card_id' => $verify_card, 'goods_share_title' => $goods->goods_share_title, 'goods_share_desc' => $goods->goods_share_desc, 'goods_share_logo' => $goods->goods_share_logo, 'product_type' => $goods->product_type, 'confine_count' => $goods->confine_count ?: 0, 'integral' => json_decode($goods->integral, true) ?: ['give' => 0, 'forehead' => 0, 'forehead_integral' => 0], 'store_info'=>$storeInfo, 'integral_price' => $goods->integral_price, 'seckill_activity_arr' => $seckill_activity_arr ?: null, 'pt_activity' => $pt_activity, ]; $store_integral = Option::get(OptionSetting::STORE_INTEGRAL, $goods->store_id, 'gift', Option::get(OptionSetting::STORE_INTEGRAL, $goods->store_id, 'store')['value'])['value']; if ($goods->integral) { $goods_integral = Json::decode($goods->integral); if ($goods_integral['forehead'] > 0) { $data['integral'] = [ 'give' => $goods_integral['give'], 'forehead' => $goods_integral['forehead'], 'forehead_integral' => round($store_integral * $goods_integral['forehead']) ]; } } // 处理app上不显示没加协议的图片 $data['detail'] = str_replace('src="//', 'src="https://', $data['detail']); $now_date = strtotime(date('Y-m-d')); $goods_book = GoodsBook::findOne(['goods_id' => $goods->id]); // 预约参数配置 if ($data['product_type'] == Goods::GOODS_TYPE_DATE) { $data['num'] = Goods::getGoodsNum($goods)['data']; $data['date_book'] = [ 'date_book' => $data['num'] , 'date' => count($data['num']) ]; if ($goods_book && !empty($goods_book->date_book)) { $date_book = Json::decode($goods_book->date_book); $count = 0; foreach ($date_book as $value) { if (strtotime($value['date']) >= $now_date) { $count++; } } // if ($count <= 0) { // return [ // 'code' => 1, // 'msg' => '商品预约数据不存在' // ]; // } $data['date_book'] = [ 'date_book' => $date_book, 'date' => count($date_book) ]; } else { // return [ // 'code' => 1, // 'msg' => '该商品暂无可预约数据' // ]; } } if ($data['product_type'] == Goods::GOODS_TYPE_TIME) { if ($goods_book && !empty($goods_book->service_book)) { $new_arr = $this->goodsBookingTime($goods['id'], 7); $data['service_book'] = $new_arr; } else { return [ 'code' => 1, 'msg' => '商品服务预约配置有误' ]; } } // if ($data['product_type'] == Goods::GOODS_TYPE_TIME) { // if ($goods_book && !empty($goods_book->service_book)) { // $service_book = Json::decode($goods_book->service_book); // $count = 0; // foreach ($service_book['data'] as &$value) { // if (strtotime($value['date']) >= $now_date) { // foreach ($value['time'] as &$m) { // foreach ($m['times'] as &$n) { // $times = explode('-', $n['time']); // if (strtotime(date('Y-m-d H:i:s')) <= strtotime($value['date'] . $times[1])) { // $count++; // } // } // } // } // } // // if ($count <= 0) { // return [ // 'code' => 1, // 'msg' => '该商品暂无可预约数据' // ]; // } // $data['service_book'] = $service_book; // } else { // return [ // 'code' => 1, // 'msg' => '商品服务预约配置有误' // ]; // } // } return [ 'code' => 0, 'data' => $data ]; } public function activity_new_user($activity_new_user_id, &$goods, &$md_goods = null) { // $activityAt = ActivityNewUser::activityAt($goods->store_id); // $activityAt && $this->activity_new_user_id = $activityAt->id; //展示活动商品信息 $activityAt = ActivityNewUser::activityAt($goods->store_id); if ($activityAt) { $goods_ext = ActivityNewUserGoods::findOne(['activity_id' => $activityAt->id, 'goods_id' => $goods->id, 'is_delete' => 0]); //商品属于当前进行中活动 if($goods_ext){ if($goods_ext->price){ $goods->price = $goods_ext->price; $md_goods && $md_goods->price = $goods_ext->price; } $ext_attrs = json_decode($goods_ext->attr, true); $attrs = json_decode($goods->attr, true); if($md_goods){ $md_attrs = json_decode($md_goods->attr, true); } foreach($ext_attrs as $ext_attr){ $ext_attr_list = json_encode($ext_attr['attr_list']); foreach($attrs as &$attr){ $attr_list = json_encode($attr['attr_list']); if($attr_list == $ext_attr_list){ $attr['price'] = $ext_attr['price']; } } if($md_goods){ foreach($md_attrs as &$md_attr){ $md_attr_list = json_encode($md_attr['attr_list']); if($md_attr_list == $ext_attr_list){ $md_attr['price'] = $ext_attr['price']; } } } } $goods->attr = json_encode($attrs); $md_goods && $md_goods->attr = json_encode($md_attrs); } } } /** * @description: 获取商品收货地址 * @param {*} * @return {*} */ public function getAddress() { if ($this->address_id) { $query = Address::find()->where(['store_id' => get_store_id(), 'is_delete' => 0, 'id' => $this->address_id]); $address = $query->andWhere([ 'user_id' => get_saas_user_id() ])->one(); } else { $query = Address::find()->where(['store_id' => get_store_id(), 'is_delete' => 0]); $query->andWhere([ 'user_id' => get_saas_user_id() ]); $address = $query->orderBy(['is_default' => SORT_DESC])->one(); } $goods = Goods::findOne($this->id); // 计算运费 $express_price = $this->getExpressPrice($address, $goods); // 计算区域限制购买 $is_area = $this->getTerritorialLimitation($address, $goods); return [ 'code' => 0, 'data' => [ 'address' => $address, 'express_price' => $express_price, 'is_area' => $is_area ] ]; } /** * 计算单个商品是否区域限制购买 */ protected function getTerritorialLimitation($address, $goods) { $isArea = 0; if ($address) { $area = TerritorialLimitation::findOne([ 'store_id' => get_store_id(), 'is_delete' => 0, 'is_enable' => 1, ]); if ($area) { $city_id = []; //限制的地区ID $detail = json_decode($area->detail); if (!is_array($detail)) { $detail = []; } foreach ($detail as $key => $value) { foreach ($value->province_list as $key2 => $value2) { $city_id[] = $value2->id; } } $addressArr = [ $address['province_id'], $address['city_id'], $address['district_id'] ]; $addressArray = array_intersect($addressArr, $city_id); if (empty($addressArray)) { $isArea = 1; } } } return $isArea; } /** * 计算单个商品的运费 */ protected function getExpressPrice($address, $goods) { $expressPrice = 0; if ($address) { //再通过运费规则计算运费 $expressPrice = PostageRules::getExpressPrice($goods->store_id, $address->city_id, $goods, 1, $address->province_id); } return $expressPrice >= 0 ? $expressPrice : 0; } public function getDateByInterval(int $num) :array { //var_dump($st, $et);die; $returnData = []; $i = 0; do { $temp = date('Y-m-d', strtotime('+' . $i . ' day', strtotime(date('Y-m-d')))); $returnData[] = $temp; $i++; } while ($i < $num); return $returnData; } public function goodsBookingTime($goods_id, $dayCount = 7) { $now_date = strtotime(date('Y-m-d')); $goods_book = GoodsBook::findOne(['goods_id' => $goods_id]); $service_book = Json::decode($goods_book->service_book); $date_data = $this->getDateByInterval($dayCount); $new_arr = [ 'data' => [] ]; $order = \app\models\Order::find()->alias('o') ->leftJoin(['od' => \app\models\OrderDetail::tableName()], 'o.id = od.order_id') ->where(['o.trade_status' => [0, 2, 3], 'o.is_delete' => 0, 'o.order_type' => 2, 'goods_id' => $goods_id]) ->andWhere(['>', 'o.created_at', time() - 3600 - $dayCount * 86400]) ->select('od.attr, od.num')->asArray()->all(); foreach ($date_data as $index => $datum) { $new_arr['data'][$index]['date'] = $datum; $new_arr['data'][$index]['time'] = $service_book['data'][0]['time']; } foreach ($new_arr['data'] as &$value) { if (strtotime($value['date']) >= $now_date) { foreach ($value['time'] as &$m) { foreach ($m['times'] as &$n) { $times = explode('-', $n['time']); foreach ($order as $item) { if ($item['attr']) { $item['attr'] = json_decode($item['attr'], true); $order_time = explode('-', $item['attr']['time']); if ( strtotime($item['attr']['date'] . ' ' . $times[0]) === strtotime($value['date'] . ' ' . $order_time[0]) && strtotime($item['attr']['date'] . ' ' . $times[1]) === strtotime($value['date'] . ' ' . $order_time[1]) ) { $n['num'] = $n['num'] - $item['num']; } } } } } } } return $new_arr; } }