mainId); if ($mainId <= 0) { util::fail('无效门店'); } $goodsId = intval(Yii::$app->request->get('goodsId', 0)); if ($goodsId <= 0) { util::fail('请选择商品'); } $row = GroupBuyActivityClass::getActiveGoodsRowByGoodsId($mainId, $goodsId); if (empty($row)) { util::fail('团购活动已结束或商品已下架'); } $goods = GoodsClass::getById($goodsId, true); $cover = strval($row['cover'] ?? ''); $coverUrl = $cover; if ($cover !== '' && strpos($cover, 'http') !== 0) { $formatted = business::formatUploadImg($cover); $coverUrl = $formatted['url'] ?? $cover; } $detailImages = []; if (!empty($goods)) { $pics = $goods->detail ?? ($goods->pic ?? ''); if (is_string($pics) && $pics !== '') { $decoded = json_decode($pics, true); if (is_array($decoded)) { foreach ($decoded as $p) { if (is_string($p) && $p !== '') { if (strpos($p, 'http') === 0) { $detailImages[] = $p; } else { $fmt = business::formatUploadImg($p); $detailImages[] = $fmt['url'] ?? $p; } } } } } } $openGroup = GroupBuyClass::getHottestOpenGroup( $mainId, $goodsId, intval($row['activityGoodsId'] ?? 0) ); util::success([ 'activityGoodsId' => intval($row['activityGoodsId']), 'activityId' => intval($row['activityId']), 'goodsId' => $goodsId, 'name' => strval($row['name']), 'cover' => $cover, 'coverUrl' => $coverUrl, 'price' => floatval($row['price']), 'originPrice' => floatval($row['originPrice']), 'groupSize' => intval($row['groupSize']), 'stock' => intval($row['stock']), 'limit' => intval($row['limit']), 'virtualGroup' => intval($row['virtualGroup']), 'virtualMinutes' => intval($row['virtualMinutes']), 'autoRefund' => 1, 'startTime' => intval($row['startTime']), 'endTime' => intval($row['endTime']), 'title' => strval($row['title']), 'subtitle' => strval($row['subtitle']), 'desc' => strval($row['desc']), 'showCountdown' => intval($row['showCountdown']), 'detailImages' => $detailImages, 'openGroup' => $openGroup, ]); } /** * 拼团详情 * GET id */ public function actionDetail() { $mainId = intval($this->mainId); if ($mainId <= 0) { util::fail('无效门店'); } $id = intval(Yii::$app->request->get('id', 0)); if ($id <= 0) { util::fail('请选择拼团'); } $detail = GroupBuyClass::getDetail($mainId, $id); // 附带活动商品落地信息,便于分享进入后完整展示 $landing = GroupBuyActivityClass::getActiveGoodsRowById($mainId, intval($detail['activityGoodsId'])); if (empty($landing)) { $landing = GroupBuyActivityClass::getActiveGoodsRowByGoodsId($mainId, intval($detail['goodsId'])); } $detail['activityGoods'] = $landing; $currentShopId = intval(Yii::$app->request->get('account', 0)); $hd = HdClass::getByCondition(['shopId' => $currentShopId, 'userId' => $this->userId], false, null, 'id, customId'); if (empty($hd)) { // util::error(errCode::GROUP_BUY_HD_NOT_BOUND, '客户暂无关联此店'); // 客户与当前门店无关系时,立即建立 if (empty($this->user)) { util::fail('请先登录'); } $shop = ShopClass::getById($currentShopId, true); if (empty($shop)) { util::fail('门店不存在'); } $respond = CustomClass::buildRelation($shop, $this->user); if (empty($respond) || empty($respond['hd'])) { util::fail('关联门店失败'); } $hdId = intval($respond['hd']->id); } else { $hdId = intval($hd['id']); } $detail['hdId'] = $hdId; util::success($detail); } /** * 我要开团:创建团 + 创建待支付订单 + 挂接团长成员 */ public function actionCreate() { $form = new CreateGroupBuyForm(); $form->loadAndValidate(); $mainId = intval($this->mainId); $custom = $this->custom; if (empty($custom)) { util::fail('请先登录'); } $customId = intval($custom->id); $activityGoodsId = intval($form->activityGoodsId); $goodsNum = max(1, intval($form->goodsNum)); $row = GroupBuyActivityClass::getActiveGoodsRowById($mainId, $activityGoodsId); if (empty($row)) { util::fail('团购活动已结束或商品已下架'); } if ($goodsNum > intval($row['limit'])) { util::fail('超出单人限购数量'); } $connection = Yii::$app->db; $transaction = $connection->beginTransaction(); try { $group = GroupBuyClass::createGroup($mainId, intval($this->shopId), $customId, $row); $groupBuyId = intval($group['id']); $order = $this->createGroupBuyOrder($form, $row, $groupBuyId, $goodsNum); GroupBuyMemberClass::bindOrderMember( $groupBuyId, $mainId, $customId, intval($order->id), strval($order->orderSn), GroupBuyMemberClass::ROLE_LEADER ); $transaction->commit(); util::success([ 'groupBuyId' => $groupBuyId, 'orderSn' => $order->orderSn, 'totalPrice' => $order->actPrice, 'id' => $order->id, ]); } catch (\Exception $e) { $transaction->rollBack(); Yii::error('开团失败:' . $e->getMessage(), __METHOD__); $msg = $e->getMessage(); if ($msg !== '' && mb_strlen($msg) < 80 && strpos($msg, 'SQLSTATE') === false) { util::fail($msg); } util::fail('开团失败'); } } /** * 我要参团:加入已有团 + 创建待支付订单 */ public function actionJoin() { $form = new JoinGroupBuyForm(); $form->loadAndValidate(); $mainId = intval($this->mainId); $custom = $this->custom; $currentShopId = intval(Yii::$app->request->get('account', 0)); if (empty($custom)) { $hd = HdClass::getByCondition(['shopId' => $currentShopId, 'userId' => $this->userId], false, null, 'id, customId'); if (empty($hd)) { // 客户与当前门店无关系时,立即建立 if (empty($this->user) || empty($this->shop)) { util::fail('请先登录'); } $respond = CustomClass::buildRelation($this->shop, $this->user); if (empty($respond) || empty($respond['custom'])) { util::fail('关联门店失败'); } $custom = $respond['custom']; } else { $customId = $hd['customId']; $custom = CustomClass::getById($customId, true); } } $customId = intval($custom->id); $groupBuyId = intval($form->groupBuyId); $goodsNum = max(1, intval($form->goodsNum)); $connection = Yii::$app->db; $transaction = $connection->beginTransaction(); try { $group = GroupBuyClass::assertCanJoin($mainId, $groupBuyId, $customId); $row = GroupBuyActivityClass::getActiveGoodsRowById($mainId, intval($group->activityGoodsId)); if (empty($row)) { // 活动结束后仍允许在截止前参团:用团上快照价 $row = [ 'activityId' => intval($group->activityId), 'activityGoodsId' => intval($group->activityGoodsId), 'goodsId' => intval($group->goodsId), 'price' => floatval($group->price), 'limit' => 1, 'endTime' => intval($group->deadline), 'groupSize' => intval($group->needNum), 'virtualGroup' => intval($group->virtualGroup), 'virtualMinutes' => 0, ]; } if ($goodsNum > intval($row['limit'] ?? 1)) { util::fail('超出单人限购数量'); } $order = $this->createGroupBuyOrder($form, $row, $groupBuyId, $goodsNum, $custom); GroupBuyMemberClass::bindOrderMember( $groupBuyId, $mainId, $customId, intval($order->id), strval($order->orderSn), GroupBuyMemberClass::ROLE_MEMBER ); $transaction->commit(); util::success([ 'groupBuyId' => $groupBuyId, 'orderSn' => $order->orderSn, 'totalPrice' => $order->actPrice, 'id' => $order->id, ]); } catch (\Exception $e) { $transaction->rollBack(); Yii::error('参团失败:' . $e->getMessage(), __METHOD__); $msg = $e->getMessage(); if ($msg !== '' && mb_strlen($msg) < 80 && strpos($msg, 'SQLSTATE') === false) { util::fail($msg); } util::fail('参团失败'); } } /** * 我的拼团列表 */ public function actionMyList() { $mainId = intval($this->mainId); $custom = $this->custom; if (empty($custom)) { util::fail('请先登录'); } util::success([ 'list' => GroupBuyClass::getMyList($mainId, intval($custom->id)), ]); } /** * 组装并创建拼团订单(核价以后端活动商品为准) * * @param object $form * @param array $row * @param int $groupBuyId * @param int $goodsNum * @return object */ private function createGroupBuyOrder($form, $row, $groupBuyId, $goodsNum, $currenCustom = []) { $shop = $this->shop; $openShop = ShopClass::getOpenShop($shop); if ($openShop == 0) { util::fail('已休店'); } $mainId = intval($this->mainId); $custom = $this->custom; if (empty($custom) && !empty($currenCustom)) { $custom = $currenCustom; } $hd = $this->hd; $user = $this->user; $saleGoodsId = intval($row['goodsId']); $goodsInfo = GoodsClass::getById($saleGoodsId, true); if (empty($goodsInfo) || intval($goodsInfo->mainId) !== $mainId) { util::fail('没有找到商品'); } $stock = intval($goodsInfo->stock ?? 0); if ($stock < $goodsNum) { util::fail('库存不足'); } $unitPrice = floatval($row['price'] ?? 0); if ($unitPrice <= 0) { util::fail('团购价格异常'); } $goodsPrice = bcmul($unitPrice, $goodsNum, 2); $sendType = intval($form->sendType ?? dict::getDict('sendType', 'shopGet')); $sendCost = 0; // 跑腿配送暂不在拼团链路单独报价,统一引导自取或送货上门(运费0,与花店协商) if ($sendType == dict::getDict('sendType', 'thirdSend')) { util::fail('拼团暂不支持跑腿,请选择自取或送货上门'); } if ($sendType == dict::getDict('sendType', 'carGet')) { if (empty($form->receiveUserName)) { util::fail('请填写收花人名字'); } if (empty($form->receiveMobile) || !stringUtil::isMobile($form->receiveMobile)) { util::fail('请填写正确的收花人手机号'); } } $post = [ 'sendType' => $sendType, 'receiveUserName' => strval($form->receiveUserName ?? ''), 'receiveMobile' => strval($form->receiveMobile ?? ''), 'address' => strval($form->address ?? ''), 'floor' => strval($form->floor ?? ''), 'city' => strval($form->city ?? ''), 'long' => strval($form->long ?? ''), 'lat' => strval($form->lat ?? ''), 'showAddress' => strval($form->showAddress ?? ''), 'remark' => strval($form->remark ?? ''), 'reachDate' => !empty($form->reachDate) ? $form->reachDate : date('Y-m-d'), 'reachPeriod' => strval($form->reachPeriod ?? ''), 'sendCost' => $sendCost, 'sendDistance' => 0, 'sjId' => intval($this->sjId ?: ($shop->sjId ?? 0)), 'shopId' => $this->shopId, 'mainId' => $mainId, 'userId' => $this->userId, 'customId' => intval($custom->id), 'customName' => strval($custom->name ?? ''), 'customNamePy' => stringUtil::py(strval($custom->name ?? '')), 'hdId' => intval($hd->id ?? 0), 'hdName' => strval($hd->name ?? ''), 'bookName' => strval($user->name ?? ''), 'bookMobile' => !empty($form->bookMobile) && stringUtil::isMobile($form->bookMobile) ? $form->bookMobile : strval($user->mobile ?? ''), 'payWay' => 0, 'store' => 0, 'modifyPrice' => stringUtil::calcAdd($sendCost, $goodsPrice), 'deadline' => time() + 1800, 'orderSn' => orderSn::getOrderSn(), 'fromType' => dict::getDict('fromType', 'mall'), 'cash' => 0, 'needPrint' => dict::getDict('needPrint', 'need'), 'groupBuyId' => intval($groupBuyId), 'product' => [[ 'productId' => $saleGoodsId, 'unitType' => 0, 'property' => 0, 'unitPrice' => $unitPrice, 'num' => $goodsNum, ]], ]; if ($sendType != 1 && empty($post['reachPeriod'])) { util::fail('请选择配送时间'); } return OrderService::createHdOrder($post, $custom, 0); } }