|
|
@@ -903,6 +903,429 @@ class OrderController extends BaseController
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 花束+花材合并结算下单
|
|
|
+ * 复用 OrderService::createHdOrder,不改动 buy-item / create-order
|
|
|
+ */
|
|
|
+ public function actionCreateMixOrder()
|
|
|
+ {
|
|
|
+ $post = Yii::$app->request->post();
|
|
|
+ $post['sjId'] = $this->sjId;
|
|
|
+ $post['shopId'] = $this->shopId;
|
|
|
+ $post['payWay'] = 0;
|
|
|
+ $post['mainId'] = $this->mainId ?? 0;
|
|
|
+ $post['userId'] = $this->userId ?? 0;
|
|
|
+
|
|
|
+ $userId = $this->userId;
|
|
|
+ util::checkRepeatCommit($userId, 3);
|
|
|
+
|
|
|
+ $shop = $this->shop;
|
|
|
+ $openShop = \bizHd\shop\classes\ShopClass::getOpenShop($shop);
|
|
|
+ if ($openShop == 0) {
|
|
|
+ util::fail('已休店');
|
|
|
+ }
|
|
|
+
|
|
|
+ $mainId = $this->mainId;
|
|
|
+ if (getenv('YII_ENV') == 'production') {
|
|
|
+ if (in_array($mainId, [40057, 7779, 42940, 26374, 10536, 65381])) {
|
|
|
+ util::fail('暂时无法访问');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $hdId = $post['hdId'] ?? 0;
|
|
|
+ $hd = HdClass::getById($hdId, true);
|
|
|
+ if (empty($hd)) {
|
|
|
+ util::fail('没有找到花店');
|
|
|
+ }
|
|
|
+ if ($hd->shopId != $this->shopId) {
|
|
|
+ util::fail('不是你的花店');
|
|
|
+ }
|
|
|
+ $post['hdName'] = $hd->name ?? '';
|
|
|
+ // 合并结算沿用花材购物车的客户身份(花店客户)
|
|
|
+ $hdCustomId = $hd->customId ?? 0;
|
|
|
+ $custom = CustomClass::getById($hdCustomId, true);
|
|
|
+ if (empty($custom)) {
|
|
|
+ util::fail('没有找到客户');
|
|
|
+ }
|
|
|
+ $customName = $custom->name ?? '';
|
|
|
+ $post['customId'] = $hdCustomId;
|
|
|
+ $post['customName'] = $customName;
|
|
|
+ $post['customNamePy'] = stringUtil::py($customName);
|
|
|
+
|
|
|
+ $productJson = $post['product'] ?? '';
|
|
|
+ if (empty($productJson)) {
|
|
|
+ util::fail('请选择商品');
|
|
|
+ }
|
|
|
+ $productList = json_decode($productJson, true);
|
|
|
+ if (empty($productList) || !is_array($productList)) {
|
|
|
+ util::fail('请选择商品');
|
|
|
+ }
|
|
|
+
|
|
|
+ $itemRows = [];
|
|
|
+ $goodsRows = [];
|
|
|
+ foreach ($productList as $idx => $row) {
|
|
|
+ $property = intval($row['property'] ?? -1);
|
|
|
+ if ($property === 1) {
|
|
|
+ $itemRows[$idx] = $row;
|
|
|
+ } elseif ($property === 0) {
|
|
|
+ $goodsRows[$idx] = $row;
|
|
|
+ } else {
|
|
|
+ util::fail('商品类型错误');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (empty($itemRows) && empty($goodsRows)) {
|
|
|
+ util::fail('请选择商品');
|
|
|
+ }
|
|
|
+
|
|
|
+ // ---- 花材校验与定价 ----
|
|
|
+ $productInfoList = [];
|
|
|
+ if (!empty($itemRows)) {
|
|
|
+ $ids = array_unique(array_filter(array_map(function ($r) {
|
|
|
+ return intval($r['productId'] ?? 0);
|
|
|
+ }, $itemRows)));
|
|
|
+ $productInfoList = ProductClass::getByIds($ids, null, 'id');
|
|
|
+ if (empty($productInfoList)) {
|
|
|
+ util::fail('花材不存在');
|
|
|
+ }
|
|
|
+ $presellData = [];
|
|
|
+ $nowTime = strtotime(date("Y-m-d"));
|
|
|
+ foreach ($productInfoList as $currentInfo) {
|
|
|
+ if (!isset($currentInfo['mainId']) || $currentInfo['mainId'] != $this->mainId) {
|
|
|
+ util::fail('只能选一家的商品,请清空重新选呢');
|
|
|
+ }
|
|
|
+ $presell = $currentInfo['presell'] ?? 0;
|
|
|
+ $presellData[] = $presell;
|
|
|
+ if ($presell == 1) {
|
|
|
+ if (empty($post['reachDate'])) {
|
|
|
+ util::fail('请选择配送或取货日期');
|
|
|
+ }
|
|
|
+ $sendTimeWant = $post['reachDate'];
|
|
|
+ if (strtotime($sendTimeWant) < $nowTime) {
|
|
|
+ util::fail('不能选择过去时间');
|
|
|
+ }
|
|
|
+ $hasDateStr = $currentInfo['presellDate'] ?? [];
|
|
|
+ $hasDate = explode(',', trim($hasDateStr));
|
|
|
+ if (empty($hasDate)) {
|
|
|
+ util::fail('预售日期有问题,请提醒门店');
|
|
|
+ }
|
|
|
+ if (!in_array(strtotime($sendTimeWant), $hasDate)) {
|
|
|
+ util::fail("有预售花材在{$sendTimeWant}没到货");
|
|
|
+ }
|
|
|
+ $post['presell'] = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (count($productInfoList) != count($ids)) {
|
|
|
+ util::fail('存在无效花材');
|
|
|
+ }
|
|
|
+ $presellData = array_unique($presellData);
|
|
|
+ if (count($presellData) > 1) {
|
|
|
+ util::fail('预售和非预售花材不能一起下单');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $connection = Yii::$app->db;
|
|
|
+ $transaction = $connection->beginTransaction();
|
|
|
+ $transactionFinished = false;
|
|
|
+ register_shutdown_function(function () use (&$transactionFinished, $transaction) {
|
|
|
+ if ($transactionFinished) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ \bizHd\product\classes\ProductClass::rollbackLimitBuySnapshot();
|
|
|
+ if ($transaction->isActive) {
|
|
|
+ $transaction->rollBack();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ try {
|
|
|
+ $orderValidTime = !getenv('ORDER_VALID_TIME') ? 600 : getenv('ORDER_VALID_TIME');
|
|
|
+ $post['deadline'] = time() + $orderValidTime;
|
|
|
+ $post['reachDate'] = !empty($post['reachDate']) ? $post['reachDate'] : date("Y-m-d");
|
|
|
+ $post['needPrint'] = dict::getDict('needPrint', 'need');
|
|
|
+ $post['fromType'] = dict::getDict('fromType', 'mall');
|
|
|
+ $post['store'] = 0;
|
|
|
+ $user = $this->user;
|
|
|
+ $post['bookMobile'] = $user->mobile ?? '';
|
|
|
+ $post['bookName'] = $user->name ?? '';
|
|
|
+ $hasPay = 0;
|
|
|
+
|
|
|
+ $modifyPrice = 0;
|
|
|
+ $totalWeight = 0;
|
|
|
+ $totalNum = 0;
|
|
|
+ $totalReachDiscount = 0;
|
|
|
+ $resolvedProduct = [];
|
|
|
+
|
|
|
+ $priceMap = \bizGhs\custom\classes\CustomClass::$levelPriceKeyMap;
|
|
|
+ $addPriceMap = \bizGhs\custom\classes\CustomClass::$levelAddPriceKeyMap;
|
|
|
+
|
|
|
+ foreach ($productList as $eleKey => $element) {
|
|
|
+ $property = intval($element['property'] ?? -1);
|
|
|
+ if ($property === 1) {
|
|
|
+ $level = 0;
|
|
|
+ $productId = $element['productId'];
|
|
|
+ $product = $productInfoList[$productId] ?? null;
|
|
|
+ if (empty($product)) {
|
|
|
+ util::fail('有花材信息没有找到');
|
|
|
+ }
|
|
|
+ $num = $element['num'] ?? 0;
|
|
|
+ $limitKey = \bizHd\product\classes\ProductClass::LIMIT_BUY_KEY . $productId;
|
|
|
+ $hasBuyNum = Yii::$app->redis->executeCommand('HGET', [$limitKey, $hdCustomId]);
|
|
|
+ $hasBuyNum = $num + ($hasBuyNum == null ? 0 : $hasBuyNum);
|
|
|
+ $price = \bizGhs\product\classes\ProductClass::getFinalPrice($product, $level, $priceMap, $addPriceMap, 0, $num, $hasBuyNum);
|
|
|
+ $reachNum = $product['reachNum'] ?? 0;
|
|
|
+ $reachNumDiscount = $product['reachNumDiscount'] ?? 0;
|
|
|
+ if ($reachNum > 0 && $num >= $reachNum && $reachNumDiscount > 0) {
|
|
|
+ $currentReachDiscount = bcmul($reachNumDiscount, $num, 2);
|
|
|
+ $totalReachDiscount = bcadd($totalReachDiscount, $currentReachDiscount, 2);
|
|
|
+ }
|
|
|
+ $currentTotal = bcmul($price, $num, 2);
|
|
|
+ $modifyPrice = bcadd($modifyPrice, $currentTotal, 2);
|
|
|
+ $weight = $product['weight'] ?? 0;
|
|
|
+ $currentWeight = bcmul($num, $weight, 2);
|
|
|
+ $totalWeight = bcadd($totalWeight, $currentWeight, 2);
|
|
|
+ $totalNum = bcadd($totalNum, $num);
|
|
|
+ if (($product['limitBuy'] ?? 0) > 0) {
|
|
|
+ $product['productId'] = $productId;
|
|
|
+ \bizHd\product\classes\ProductClass::handleLimitBuy($product, $hdCustomId, floatval($num));
|
|
|
+ }
|
|
|
+ $resolvedProduct[] = [
|
|
|
+ 'productId' => $productId,
|
|
|
+ 'num' => $num,
|
|
|
+ 'itemId' => $element['itemId'] ?? 0,
|
|
|
+ 'unitType' => $element['unitType'] ?? 0,
|
|
|
+ 'property' => 1,
|
|
|
+ 'unitPrice' => $price,
|
|
|
+ ];
|
|
|
+ } else {
|
|
|
+ $goodsId = intval($element['goodsId'] ?? 0);
|
|
|
+ $specGoodsId = intval($element['specGoodsId'] ?? 0);
|
|
|
+ $saleGoodsId = intval($element['productId'] ?? 0);
|
|
|
+ $goodsNum = isset($element['num']) && $element['num'] > 0 ? $element['num'] : 1;
|
|
|
+ if ($goodsId <= 0 && $saleGoodsId > 0) {
|
|
|
+ $probe = GoodsClass::getById($saleGoodsId, true);
|
|
|
+ if (!empty($probe)) {
|
|
|
+ $masterId = intval($probe->masterId ?? 0);
|
|
|
+ if ($masterId > 0) {
|
|
|
+ $goodsId = $masterId;
|
|
|
+ $specGoodsId = $saleGoodsId;
|
|
|
+ } else {
|
|
|
+ $goodsId = $saleGoodsId;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if ($goodsId <= 0) {
|
|
|
+ util::fail('请选择花束商品');
|
|
|
+ }
|
|
|
+ $goodsInfo = GoodsClass::getById($goodsId, true);
|
|
|
+ if (empty($goodsInfo)) {
|
|
|
+ util::fail('没有找到花束商品');
|
|
|
+ }
|
|
|
+ if ($goodsInfo->mainId != $mainId) {
|
|
|
+ util::fail('不是你的商品');
|
|
|
+ }
|
|
|
+ if ($specGoodsId > 0) {
|
|
|
+ $specGoods = GoodsClass::getById($specGoodsId, true);
|
|
|
+ if (empty($specGoods) || $specGoods->mainId != $mainId || $specGoods->masterId != $goodsId || $specGoods->delStatus != 0 || $specGoods->status != 1) {
|
|
|
+ util::fail('规格不可用');
|
|
|
+ }
|
|
|
+ $goodsInfo = $specGoods;
|
|
|
+ $saleGoodsId = $specGoodsId;
|
|
|
+ } else {
|
|
|
+ if ((int)($goodsInfo->masterId ?? 0) === 0) {
|
|
|
+ $hasSpecs = GoodsClass::getByCondition(['masterId' => $goodsId, 'delStatus' => 0], true);
|
|
|
+ if (!empty($hasSpecs)) {
|
|
|
+ util::fail('请选择规格');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ $saleGoodsId = $goodsId;
|
|
|
+ }
|
|
|
+ $stock = $goodsInfo->stock ?? 0;
|
|
|
+ $stockSet = $goodsInfo->stockSet ?? 0;
|
|
|
+ if ($stockSet == 1 && $stock <= 0) {
|
|
|
+ util::fail('花束库存不足');
|
|
|
+ }
|
|
|
+ $goodsData = $goodsInfo->attributes;
|
|
|
+ $ret = \bizHd\goods\classes\GoodsClass::getFinalPrice($goodsData, $shop, $custom, []);
|
|
|
+ $priceType = $ret['priceType'] ?? 0;
|
|
|
+ if ($priceType == 0) {
|
|
|
+ util::fail('花束没有价格,不能下单');
|
|
|
+ }
|
|
|
+ $unitPrice = $ret['price'] ?? 0;
|
|
|
+ if ($unitPrice <= 0) {
|
|
|
+ util::fail('花束没有价格,不能下单');
|
|
|
+ }
|
|
|
+ $currentTotal = bcmul($unitPrice, $goodsNum, 2);
|
|
|
+ $modifyPrice = bcadd($modifyPrice, $currentTotal, 2);
|
|
|
+ $weight = $goodsInfo->weight ?? 0;
|
|
|
+ if ($weight > 5) {
|
|
|
+ $weight = 5;
|
|
|
+ }
|
|
|
+ $currentWeight = bcmul($weight, $goodsNum, 2);
|
|
|
+ $totalWeight = bcadd($totalWeight, $currentWeight, 2);
|
|
|
+ $totalNum = bcadd($totalNum, $goodsNum);
|
|
|
+ $resolvedProduct[] = [
|
|
|
+ 'productId' => $saleGoodsId,
|
|
|
+ 'unitType' => 0,
|
|
|
+ 'property' => 0,
|
|
|
+ 'unitPrice' => $unitPrice,
|
|
|
+ 'num' => $goodsNum,
|
|
|
+ ];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $post['product'] = $resolvedProduct;
|
|
|
+ $post['reachDiscountPrice'] = $totalReachDiscount;
|
|
|
+ unset($post['sendCost']);
|
|
|
+
|
|
|
+ $mapSet = ShopClass::hasIntraCity($this->shop);
|
|
|
+ $openIntraCity = $mapSet['openIntraCity'] ?? 0;
|
|
|
+ $hasItem = !empty($itemRows);
|
|
|
+ // 含花材(含混合)按花材报价 goodsType=1;纯花束按 0
|
|
|
+ $quoteGoodsType = $hasItem ? 1 : 0;
|
|
|
+
|
|
|
+ if (isset($post['sendType']) && $post['sendType'] == 2 && $openIntraCity != 0) {
|
|
|
+ if ($openIntraCity == 2) {
|
|
|
+ util::fail('不能使用跑腿');
|
|
|
+ }
|
|
|
+ if (empty($post['long']) || empty($post['lat'])) {
|
|
|
+ util::fail('位置错误');
|
|
|
+ }
|
|
|
+ $shopLat = $shop->lat ?? '';
|
|
|
+ $shopLong = $shop->long ?? '';
|
|
|
+ if (empty($shopLat) || empty($shopLong)) {
|
|
|
+ util::fail('商家门店地址定位未设置,编号263');
|
|
|
+ }
|
|
|
+ $distance = 0;
|
|
|
+ $sendCost = 0;
|
|
|
+ $prefix = 'PT-MIX-' . $this->mainId . '-';
|
|
|
+ $orderSn = $prefix . round(microtime(true) * 1000);
|
|
|
+ $ghsInfo = ['mainId' => $this->mainId, 'shopId' => $this->shopId];
|
|
|
+ try {
|
|
|
+ if (empty($post['deliveryPlatform'])) {
|
|
|
+ util::fail('请选择跑腿');
|
|
|
+ }
|
|
|
+ $quoteCustom = $this->user;
|
|
|
+ if ($quoteGoodsType === 0) {
|
|
|
+ $quoteCustom = (object)[
|
|
|
+ 'name' => $post['receiveUserName'] ?? '',
|
|
|
+ 'mobile' => $post['receiveMobile'] ?? '',
|
|
|
+ 'fullAddress' => $post['address'] ?? '',
|
|
|
+ 'floor' => $post['floor'] ?? '',
|
|
|
+ 'dist' => '',
|
|
|
+ 'lat' => $post['lat'],
|
|
|
+ 'long' => $post['long'],
|
|
|
+ 'address' => $post['address'] ?? '',
|
|
|
+ 'city' => $post['city'] ?? '',
|
|
|
+ ];
|
|
|
+ }
|
|
|
+ $quoteResult = DeliveryQuoteUtil::getDeliveryQuote([
|
|
|
+ 'productList' => $resolvedProduct,
|
|
|
+ 'deliveryPlatform' => $post['deliveryPlatform'],
|
|
|
+ 'deliveryBracketContent' => $post['deliveryBracketContent'] ?? '',
|
|
|
+ 'ghsInfo' => $ghsInfo,
|
|
|
+ 'custom' => $quoteCustom,
|
|
|
+ 'order' => [
|
|
|
+ 'orderSn' => $orderSn,
|
|
|
+ 'goodsType' => $quoteGoodsType,
|
|
|
+ 'itemTotalAmount' => $modifyPrice,
|
|
|
+ 'remark' => $post['remark'] ?? '',
|
|
|
+ ],
|
|
|
+ 'mainId' => $this->mainId,
|
|
|
+ 'productCount' => $totalNum,
|
|
|
+ ]);
|
|
|
+ $sendCost = $quoteResult['sendCost'];
|
|
|
+ $distance = $quoteResult['sendDistance'];
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ util::fail($e->getMessage());
|
|
|
+ }
|
|
|
+ $post['sendCost'] = $sendCost;
|
|
|
+ $post['sendDistance'] = $distance;
|
|
|
+ $modifyPrice = bcadd($modifyPrice, $sendCost, 2);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 红包(归属花店客户,与 buy-item 一致)
|
|
|
+ $hbId = $post['hbId'] ?? 0;
|
|
|
+ $hb = null;
|
|
|
+ if ($hbId > 0) {
|
|
|
+ $hb = HbClass::getById($hbId, true);
|
|
|
+ if (!empty($hb)) {
|
|
|
+ if ($hb->customId != $hdCustomId) {
|
|
|
+ util::fail('不是你的红包');
|
|
|
+ }
|
|
|
+ if ($hb->amount != $post['hbAmount']) {
|
|
|
+ util::fail('红包金额不相等');
|
|
|
+ }
|
|
|
+ if ($hb->status == 1) {
|
|
|
+ util::fail('红包已使用');
|
|
|
+ }
|
|
|
+ if ($hb->status == -1) {
|
|
|
+ util::fail('红包已作废');
|
|
|
+ }
|
|
|
+ if ($hb->endTime < time()) {
|
|
|
+ $hb->status = -1;
|
|
|
+ $hb->save();
|
|
|
+ util::fail('红包已失效');
|
|
|
+ }
|
|
|
+ if ($hb->beginTime > time()) {
|
|
|
+ util::fail('红包可使用期未到');
|
|
|
+ }
|
|
|
+ if (bccomp($modifyPrice, $hb->minConsume) == -1) {
|
|
|
+ util::fail("不满足最低消费金额{$hb->minConsume}元");
|
|
|
+ }
|
|
|
+ $modifyPrice = bcsub($modifyPrice, $hb->amount, 2);
|
|
|
+ } else {
|
|
|
+ util::fail('红包无效');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $sendType = $post['sendType'] ?? 0;
|
|
|
+ if ($sendType != 1) {
|
|
|
+ if (empty($post['reachPeriod'])) {
|
|
|
+ util::fail('请选择配送时间哈');
|
|
|
+ }
|
|
|
+ $post['reachTime'] = strtotime($post['reachDate'] . ' ' . $post['reachPeriod']);
|
|
|
+ }
|
|
|
+
|
|
|
+ $post['bigNum'] = $totalNum;
|
|
|
+ $post['modifyPrice'] = $modifyPrice;
|
|
|
+ $return = \bizHd\order\services\OrderService::createHdOrder($post, $custom, $hasPay);
|
|
|
+
|
|
|
+ if (!empty($hb)) {
|
|
|
+ $hb->status = 1;
|
|
|
+ $hb->orderId = $return->id;
|
|
|
+ $hb->save();
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($return->sendType == 2) {
|
|
|
+ $ext = ShopExtClass::getByCondition(['shopId' => $return->shopId], true, null, 'id,shopId,thirdSend');
|
|
|
+ if (!empty($ext) && $ext->thirdSend == 1) {
|
|
|
+ util::fail('本店暂不能使用跑腿呢');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $transaction->commit();
|
|
|
+ $transactionFinished = true;
|
|
|
+ \bizHd\product\classes\ProductClass::clearLimitBuyRollbackSnapshot();
|
|
|
+
|
|
|
+ $orderSn = $return->orderSn ?? '';
|
|
|
+ $orderPrice = $return->orderPrice ?? ($return->actPrice ?? 0);
|
|
|
+ $id = $return->id ?? 0;
|
|
|
+ $getPayType = dict::getDict('getPayType');
|
|
|
+ util::success([
|
|
|
+ 'orderSn' => $orderSn,
|
|
|
+ 'totalPrice' => $orderPrice,
|
|
|
+ 'couponId' => 0,
|
|
|
+ 'id' => $id,
|
|
|
+ 'getPayType' => $getPayType,
|
|
|
+ ]);
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ $transaction->rollBack();
|
|
|
+ \bizHd\product\classes\ProductClass::rollbackLimitBuySnapshot();
|
|
|
+ $transactionFinished = true;
|
|
|
+ Yii::error("合并下单失败:" . $e->getMessage());
|
|
|
+ util::fail('下单失败');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
//下单要用到的相关信息 ssh 2019.12.6
|
|
|
public function actionOrderRelate()
|
|
|
{
|