orderRepository = $orderRepository; $this->orderCardPartitionRepository = $orderCardPartitionRepository; } /** * 订单列表 * * @param array $conditions * @return mixed */ public function paginate(array $conditions = []) { $limit = $conditions['limit'] ?? 35; $res = $this->orderRepository->withConditions($conditions)->applyConditions()->orderBy('order_at', 'desc')->paginate($limit); $orderShipments = $this->orderCardPartitionRepository->select([ 'order_id', DB::raw('SUM(counts) as counts'), DB::raw('SUM(CASE WHEN refunded_at IS NULL THEN 0 ELSE 1 END) as refunds') ])->withRefunded()->withConditions([ 'order_id' => $res->pluck('id')->toArray(), ])->groupBy('order_id')->get()->keyBy('order_id'); $res->map(function ($item) use ($orderShipments) { $item->company = CompanyService::load($item->company_id); $item->package = PackageService::load($item->package_id); $item->unit_price = sprintf('%.02f', $item->unit_price / 100); $item->total_price = sprintf('%.02f', $item->total_price / 100); $item->custom_price = sprintf('%.02f', $item->custom_price / 100); $item->refunds = $orderShipments[$item->id]['refunds'] ?? 0; $item->shipments = isset($orderShipments[$item->id]) ? $orderShipments[$item->id]['counts'] - $orderShipments[$item->id]['refunds'] : 0; }); return $res; } /** * 订单计数 * * @param array $conditions * @return mixed */ public function count(array $conditions = []) { $select = [ DB::raw('COUNT(*) as total_count'), DB::raw('SUM(custom_price) as total_price'), DB::raw('SUM(CASE WHEN transaction_status=1 THEN custom_price ELSE 0 END) as transacted_price'), ]; $res = $this->orderRepository->select($select)->withConditions($conditions)->applyConditions()->first()->toArray(); $res['total_price'] = $res['total_price'] ?? 0; $res['total_price'] = sprintf('%.02f', $res['total_price'] / 100); $res['transacted_price'] = $res['transacted_price'] ?? 0; $res['transacted_price'] = sprintf('%.02f', $res['transacted_price'] / 100); unset($res['company']); unset($res['package']); return $res; } /** * 下单 * * @param array $attributes * @return Order */ public function store(array $attributes = []) { $rule = [ 'type' => ['in:0,1,2,3'], 'sign' => ['in:1,2'], // 转销售 1,改企业 2 'company_id' => ['exists:virtual_companies,id'], 'product_id' => [], 'counts' => [], 'pay_channel' => [Rule::in(array_collapse(app(Dicts::class)->get('pay_channel')))], 'order_status' => ['in:0,1,2,3,4,5'], 'transaction_status' => ['in:0,1,2'], 'extends' => ['array'], 'selected' => ['array'], ]; $message = [ 'company_id.required' => '请输入企业ID', 'company_id.exists' => '企业不存在或已删除', 'product_id.required' => '请选择套餐', 'counts.required' => '请输入订购数量', 'pay_channel.required' => '请选择支付方式', 'pay_channel.in' => '支付方式不合法', 'contacts.required' => '请选择收货地址', 'mobile.required' => '请选择收货地址', 'address.required' => '请选择收货地址', ]; if (isset($attributes['unit_price'])) { $attributes['unit_price'] = intval($attributes['unit_price'] * 100); $attributes['total_price'] = $attributes['unit_price'] * $attributes['counts']; $attributes['custom_price'] = $attributes['unit_price'] * $attributes['counts']; } DB::beginTransaction(); if (!$attributes['id']) { $attributes['sn'] = $attributes['sn'] ?: $this->generateSn(); $attributes['transaction_no'] = $attributes['transaction_no'] ?: $this->generateTransactionNo($attributes['pay_channel']); if ($attributes['company_id'] && $attributes['package_id'] && isset($attributes['unit_price'])) { $product = ProductService::getProduct($attributes['type'], $attributes['company_id'], $attributes['package_id'], $attributes['unit_price']); } elseif ($attributes['product_id']) { $product = app(ProductRepository::class)->find($attributes['product_id']); $attributes['unit_price'] = $attributes['type'] === 1 ? $product['renew_price'] : $product['price']; } if (!$product) { throw new NotExistException('套餐不存在或已删除'); } $rule['type'][] = 'required'; $rule['company_id'][] = 'required'; $rule['counts'][] = 'required'; $rule['pay_channel'][] = 'required'; if (!$attributes['source']) { $rule['contacts'][] = 'required'; $rule['mobile'][] = 'required'; $rule['address'][] = 'required'; } } Validator::validate($attributes, $rule, $message); if (isset($attributes['selected']) && empty('selected')) { throw new InvalidArgumentException('请选择卡'); } try { if ($attributes['id']) { if (!$node = $this->orderRepository->find($attributes['id'])) { throw new NotExistException('订单不存在或已删除'); } if (!empty($attributes['extends']) && is_array($attributes['extends'])) { $attributes['extends'] = array_merge($node->extends ?: [], $attributes['extends']); } if (isset($attributes['selected']) && count($attributes['selected']) === $node->counts) { $attributes['order_status'] = 5; $attributes['transaction_status'] = 1; } if ($attributes['order_status'] === 1) { $count = $this->orderCardPartitionRepository->where('type', $node['type'])->where('order_id', $node['id'])->count(); if ($count) { throw new ExistedException('订单已排单,不能取消'); } } // 改企业 if (isset($attributes['company_id']) && $attributes['company_id'] != $node->company_id) { if ($node->type !== 0) { throw new NotAllowedException('只允许修改销售订单'); } $subQuery = OrderCard::select('sim')->where('order_id', $node->id); $count = OrderCardPartition::where('type', '<>', 0)->whereIn('sim', $subQuery)->count(); if ($count) { throw new NotAllowedException('已存在其他类型订单,不能修改企业'); } } $updates = []; // 改订单时间 if (isset($attributes['order_at']) && $attributes['order_at'] != $node->order_at) { $updates['created_at'] = $attributes['order_at']; } // 改套餐 if (isset($attributes['package_id']) && $attributes['package_id'] != $node->package_id) { $updates['package_id'] = $attributes['package_id']; } // 改价格 if (isset($attributes['unit_price']) && $attributes['unit_price'] != $node->unit_price) { $updates['unit_price'] = $attributes['unit_price']; } if (isset($updates['package_id']) || isset($updates['unit_price'])) { $updates['package_id'] = $updates['package_id'] ?? $node->package_id; $updates['unit_price'] = $updates['unit_price'] ?? $node->unit_price; $product = ProductService::getProduct($node->type, $attributes['company_id'] ?? $node->company_id, $updates['package_id'], $updates['unit_price']); } if (!empty($updates)) { OrderCardPartition::where('type', $node->type)->where('order_id', $node->id)->update($updates); } $this->orderRepository->setModel($node)->update($attributes); if (isset($attributes['unit_price'])) { $this->orderCardPartitionRepository->where('type', $node->type)->where('order_id', $node->id)->update([ 'unit_price' => $attributes['unit_price'], ]); } } else { if ($product->company_id != $attributes['company_id']) { throw new NotAllowedException('非法操作'); } $maxId = Order::withTrashed()->max('id'); if ($attributes['type'] !== 0 && isset($attributes['selected']) && is_array($attributes['selected'])) { $simArray = array_unique(array_pluck($attributes['selected'], 'sim')); $simArray = array_map('intval', $simArray); $simCompany = $this->orderCardPartitionRepository->select(['sim', 'company_id']) ->where('type', 0)->whereIn('sim', $simArray) ->get()->pluck('company_id', 'sim')->toArray(); $news = []; $extras = []; foreach ($simArray as $value) { if (!in_array($value, array_keys($simCompany))) { array_push($news, $value); continue; } if ($simCompany[$value] !== $attributes['company_id']) { array_push($extras, $value); continue; } } // 续费转销售 if ($attributes['type'] == 1) { // 卡已在VD上(先把原有卡替换掉) if (count($extras)) { $simArray = implode(',', array_pluck($attributes['selected'], 'sim')); try { DB::statement("select change_cards('{{$simArray}}'::INT8[]);"); $news = array_merge($news, array_pluck($attributes['selected'], 'sim')); } catch (\Throwable $th) { DB::rollback(); throw $th; } } // 卡不在VD上的创建方式 if (count($news)) { // 创建订单 $newOrderData = array_except($attributes, ['selected', 'sign']); $newOrderData['id'] = ++$maxId; $newOrderData['sn'] = $this->generateSn(); $newOrderData['type'] = 0; $newOrderData['order_status'] = 5; $newOrderData['transaction_status'] = 1; $newOrderData['counts'] = count($news); $newOrderData['total_price'] = $attributes['unit_price'] * count($news); $newOrderData['custom_price'] = $attributes['unit_price'] * count($news); $newOrderData['order_at'] = $attributes['order_at'] ?? date('Y-m-d H:i:s'); $newOrderData['package_id'] = $attributes['package_id'] ?? $product->package_id; $newOrder = $this->orderRepository->create($newOrderData); // 按订单时间激活 $array = array_map(function ($item) use ($newOrderData) { return ['sim' => $item, 'virtual_activated_at' => $newOrderData['order_at']]; }, $news); Card::upsert($array, 'sim', ['virtual_activated_at']); // 创建订单卡关联 $this->upsertOrderCards(array_map(function ($item) { return ['sim' => $item, 'counts' => 1]; }, $news), $newOrder); // 剩下需要续费的卡 $selected = $attributes['selected']; $selectedNews = []; foreach ($selected as $key => $item) { if (isset($selectedNews[$item['sim']])) { $selectedNews[$item['sim']]['counts'] += $item['counts']; continue; } if (in_array($item['sim'], $news)) { $counts = $item['counts'] - 1; $selectedNews[$item['sim']] = [ 'sim' => $item['sim'], 'counts' => $counts ]; continue; } $selectedNews[$item['sim']] = [ 'sim' => $item['sim'], 'counts' => $item['counts'], ]; } $selectedNews = array_filter($selectedNews, function ($item) { return $item['counts'] > 0; }); $attributes['counts'] = array_sum(array_pluck($selectedNews, 'counts')); $attributes['selected'] = array_values($selectedNews); } } // 续费包\加油包 if ($attributes['type'] == 2) { if (count($extras)) { throw new NotAllowedException("暂不支持续费包及加油包转销售"); } if (count($news)) { throw new NotAllowedException("暂不支持续费包及加油包转销售"); } } } if ($attributes['counts'] !== 0) { $attributes['id'] = ++$maxId; if (isset($attributes['selected']) && count($attributes['selected']) === $attributes['counts']) { $attributes['order_status'] = 5; $attributes['transaction_status'] = 1; } $attributes['total_price'] = $attributes['unit_price'] * $attributes['counts']; $attributes['custom_price'] = $attributes['unit_price'] * $attributes['counts']; $attributes['order_at'] = $attributes['order_at'] ?? date('Y-m-d H:i:s'); $attributes['package_id'] = $attributes['package_id'] ?? $product->package_id; $node = $this->orderRepository->create($attributes); } } if (isset($attributes['selected']) && is_array($attributes['selected']) && count($attributes['selected'])) { if ($attributes['type'] === 0) { $exists = $this->orderCardPartitionRepository->withConditions([ 'type' => 0, 'sim' => array_pluck($attributes['selected'], 'sim') ])->count(); if ($exists) { DB::rollBack(); $simArray = implode(',', array_pluck($attributes['selected'], 'sim')); throw new NotAllowedException("存在已被其他订单使用的卡: ($simArray)"); } } try { $this->upsertOrderCards($attributes['selected'], $node); } catch (\Exception $e) { DB::rollBack(); throw $e; } } } catch (\Exception $e) { DB::rollBack(); throw $e; } DB::commit(); $this->orderRepository->forgetCached(); $this->orderCardPartitionRepository->forgetCached(); app(RealOrderCardPartitionRepository::class)->forgetCached(); return $node; } /** * 以卡续费/续费包/加油包 * * @param array $attributes * @return Order */ public function storeAdded(array $attributes = []) { $rule = [ 'type' => ['in:1,2,3'], 'pay_channel' => ['required'], 'cards' => ['array'], 'cards.*.sim' => ['required'], 'cards.*.counts' => ['required'], 'company_id' => ['required'] ]; $message = [ 'pay_channel.required' => '请选择支付方式', 'company_id.required' => '企业不能为空', 'cards.*.sim.required' => '卡号为必填项', 'cards.*.sim.counts' => '数量为必填项', ]; if ($attributes['type'] !== 1) { $rule['product_id'] = ['required']; $message['product_id.required'] = '请选择套餐'; } Validator::validate($attributes, $rule, $message); if (empty($attributes['cards'])) { throw new InvalidArgumentException('请至少选择一张卡'); } $simArray = array_map('intval', array_pluck($attributes['cards'], 'sim')); $conditions = [ 'type' => [0, 1], 'sim' => $simArray, ]; $res = $this->orderCardPartitionRepository->selectRaw('distinct on (sim) *') ->withConditions($conditions)->orderBy('sim')->orderBy('created_at', 'desc')->get(); $res->map(function ($item) { $item->groupKey = $item->company_id . '_' . $item->package_id; }); $errors = []; foreach ($res as $card) { if ($card->company_id !== $attributes['company_id']) { $errors[] = $card->sim; } } if (!empty($errors)) { $message = sprintf('卡(%s)不属于您的企业', implode(',', $errors)); throw new InvalidArgumentException($message); } $errors = array_diff($simArray, $res->pluck('sim')->toArray()); if (!empty($errors)) { $message = sprintf('卡(%s)未找到销售订单', implode(',', $errors)); throw new InvalidArgumentException($message); } $maxId = Order::withTrashed()->max('id'); $orders = []; $orderCards = []; $order_at = date('Y-m-d H:i:s'); if ($attributes['type'] == 1) { foreach ($res->groupBy('groupKey') as $key => $value) { $orderId = ++$maxId; $realCards = array_filter($attributes['cards'], function ($item) use ($value) { return !in_array($item->sim, array_pluck($value, 'sim')); }); $product = ProductService::load(0, $attributes['company_id'], $value[0]['package_id']); $counts = array_sum(array_pluck($realCards, 'counts')); $orders[$key] = [ 'id' => $orderId, 'sn' => $this->generateSn(), 'source' => 0, 'type' => $attributes['type'], 'company_id' => $attributes['company_id'], 'package_id' => $value[0]['package_id'], 'transaction_no' => $this->generateTransactionNo($attributes['pay_channel']), 'pay_channel' => $attributes['pay_channel'], 'unit_price' => $product['renew_price'], 'counts' => $counts, 'total_price' => $product['renew_price'] * $counts, 'custom_price' => $product['renew_price'] * $counts, 'order_at' => $order_at, 'created_at' => $order_at, 'updated_at' => $order_at, ]; $cardCounts = array_pluck($attributes['cards'], 'counts', 'sim'); foreach ($value as $card) { $orderCards[] = [ 'type' => $attributes['type'], 'sim' => $card->sim, 'order_id' => $orderId, 'company_id' => $attributes['company_id'], 'package_id' => $card['package_id'], 'counts' => $cardCounts[$card->sim], 'unit_price' => $card->unit_price, 'created_at' => $order_at, 'updated_at' => $order_at, ]; } }; } if ($attributes['type'] != 1) { if (!$product = app(ProductRepository::class)->find($attributes['product_id'])) { throw new NotExistException('定价未找到或已删除'); } if ($product->company_id !== $attributes['company_id']) { throw new InvalidArgumentException('定价不属于该企业'); } $orderId = $maxId + 1; $counts = array_sum(array_pluck($attributes['cards'], 'counts')); $orders[] = [ 'id' => $orderId, 'sn' => $this->generateSn(), 'source' => 0, 'type' => $attributes['type'], 'company_id' => $attributes['company_id'], 'package_id' => $product['package_id'], 'transaction_no' => $this->generateTransactionNo($attributes['pay_channel']), 'pay_channel' => $attributes['pay_channel'], 'unit_price' => $product['price'], 'counts' => $counts, 'total_price' => $product['price'] * $counts, 'custom_price' => $product['price'] * $counts, 'order_at' => $order_at, 'created_at' => $order_at, 'updated_at' => $order_at, ]; $cardCounts = array_pluck($attributes['cards'], 'counts', 'sim'); foreach ($res as $card) { $orderCards[] = [ 'type' => $attributes['type'], 'sim' => $card->sim, 'order_id' => $orderId, 'company_id' => $attributes['company_id'], 'package_id' => $product['package_id'], 'counts' => $cardCounts[$card->sim], 'unit_price' => $product['price'], 'created_at' => $order_at, 'updated_at' => $order_at, ]; }; } DB::beginTransaction(); try { Order::upsert($orders, 'id'); $table = $this->tables[$attributes['type']]; DB::table($table)->upsert($orderCards, ['sim', 'order_id', 'refunded_at', 'deleted_at']); $fixSimArray = implode(',', $simArray); DB::statement("select fix_timelines('{{$fixSimArray}}'::INT8[]);"); } catch (\Exception $e) { DB::rollback(); throw $e; } DB::commit(); app(OrderRepository::class)->forgetCached(); app(OrderCardPartitionRepository::class)->forgetCached(); return true; } /** * 对续费订单以卡的方式排单 * * @param integer $orderId * @param array $simArray * @return void */ public function storeByOrder(int $orderId, array $simArray): Order { if (!$order = $this->orderRepository->find($orderId)) { throw new NotExistException('订单不存在或已删除'); } if ($order->type == 0) { throw new NotAllowedException("不支持销售订单"); } $orderShipments = $this->orderCardPartitionRepository->select([ 'order_id', 'sim', 'counts', ])->withConditions(['order_id' => $orderId])->get(); $shipments = array_sum(array_pluck($orderShipments, 'counts')); if ($order->counts - $shipments != count($simArray)) { throw new NotAllowedException("排单数量不正确"); } $res = $this->orderCardPartitionRepository->selectRaw('distinct on (sim) *') ->withConditions(['sim' => array_unique($simArray)])->orderBy('sim')->orderBy('created_at', 'desc')->get(); $errors = []; foreach ($res as $card) { if ($card->company_id !== $order['company_id']) { $errors[] = $card->sim; } } if (!empty($errors)) { $message = sprintf('卡(%s)不属于您的企业', implode(',', $errors)); throw new InvalidArgumentException($message); } $errors = array_diff($simArray, $res->pluck('sim')->toArray()); if (!empty($errors)) { $message = sprintf('卡(%s)未找到销售订单', implode(',', $errors)); throw new InvalidArgumentException($message); } $cards = array_count_values($simArray); $orderShipments = $orderShipments->keyBy('sim'); $orderCards = []; foreach ($res as $card) { $orderCards[] = [ 'type' => $order['type'], 'sim' => $card->sim, 'order_id' => $orderId, 'company_id' => $order['company_id'], 'package_id' => $order['package_id'], 'counts' => isset($orderShipments[$card->sim]) ? $orderShipments[$card->sim] + $cards[$card->sim] : $cards[$card->sim], 'unit_price' => $order['unit_price'], 'created_at' => $order->order_at, 'updated_at' => date('Y-m-d H:i:s'), ]; }; $table = $this->tables[$order['type']]; DB::table($table)->upsert($orderCards, ['sim', 'order_id', 'refunded_at', 'deleted_at']); $fixSimArray = implode(',', $simArray); DB::statement("select fix_timelines('{{$fixSimArray}}'::INT8[]);"); app(OrderCardPartitionRepository::class)->forgetCached(); return $order; } /** * 不在 * * @param array $attributes * @return void */ public function storeWhenNotIn(array $attributes) { } /** * 取消订单 * * @return bool */ public function cancel($id) { if (!$node = $this->orderRepository->find($id)) { throw new NotExistException('订单不存在或已删除'); } if ($node->order_status !== 0) { throw new NotExistException('订单已出库,不能取消'); } if ($node->transaction_status !== 0) { throw new NotExistException('订单已付款,不能取消'); } $this->orderRepository->setModel($node)->update(['order_status' => 1]); return $node; } /** * 确认收货 * * @return bool */ public function received($id) { if (!$node = $this->orderRepository->find($id)) { throw new NotExistException('订单不存在或已删除'); } if ($node->order_status !== 4) { throw new NotExistException('订单未发货,不能修改'); } $this->orderRepository->setModel($node)->update(['order_status' => 5]); return $node; } /** * 重置 * * @return bool */ public function reset($ids) { DB::transaction(function () use ($ids) { foreach ($ids as $id) { $id = intval($id); if (!$node = $this->orderRepository->find($id)) { throw new NotExistException('订单不存在或已删除'); } if ($node->type === 0) { $sql = 'SELECT COUNT(*) as counts FROM virtual_order_cards_partition WHERE type != 0 AND sim In ( SELECT sim FROM virtual_order_cards_partition WHERE order_id = ? ) AND deleted_at IS NULL'; $counts = DB::select($sql, [$id])[0]->counts; if ($counts) { throw new NotAllowedException('订单中的卡已存在于其他类型订单中,不能进行重置'); } } else { // 替卡重置 $sql = 'UPDATE virtual_order_cards_partition SET sim=original_sim,original_sim=0 WHERE original_sim != 0 AND sim IN ( SELECT DISTINCT SIM FROM virtual_order_cards_partition WHERE type = ? AND order_id = ? ) '; DB::statement($sql, [$node->type, $id]); $node->order_status = 0; $node->save(); $this->orderRepository->forgetCached(); } } $this->orderCardPartitionRepository->whereIn('order_id', $ids)->delete(); app(RealOrderCardPartitionRepository::class)->whereIn('virtual_order_id', $ids)->update(['virtual_order_id' => 0]); }); app(RealOrderCardPartitionRepository::class)->forgetCached(); app(RealOrderRepository::class)->forgetCached(); return true; } /** * 删除 * * @return bool */ public function destroy($ids) { $ids = is_array($ids) ? $ids : [$ids]; foreach ($ids as $id) { if (!$node = $this->orderRepository->find($id)) { throw new NotExistException('订单不存在或已删除'); } } $this->orderRepository->destroy($ids); return true; } /** * 生成订单编号 * * @return void */ public function generateSn() { return date('YmdHis') . sprintf('%04d', explode('.', microtime(true))[1]) . sprintf('%02d', rand(0, 99)); } /** * 生成流水号 * * 4200000252201903085372480404 微信 * 2019030722001407831022090620 支付宝 * * @return void */ public function generateTransactionNo($payChannel) { switch ($payChannel) { case 'wx': case 'wx_pub': case 'wx_pub_qr': case 'wx_pub_scan': case 'wx_wap': case 'wx_lite': $transactionNo = '4200000' . sprintf('%03d', rand(0, 999)) . date('YmdHis') . sprintf('%04d', explode('.', microtime(true))[1]); break; case 'alipay': case 'alipay_wap': case 'alipay_qr': case 'alipay_scan': case 'alipay_pc_direct': $transactionNo = date('YmdHis') . sprintf('%04d', explode('.', microtime(true))[1]) . '1' . sprintf('%9d', rand(0, 999999999)); break; case 'bank': $transactionNo = date('YmdHis') . sprintf('%04d', explode('.', microtime(true))[1]) . '2' . sprintf('%9d', rand(0, 999999999)); break; case 'account': $transactionNo = date('YmdHis') . sprintf('%04d', explode('.', microtime(true))[1]) . '3' . sprintf('%9d', rand(0, 999999999)); break; case 'tmall': $transactionNo = date('YmdHis') . sprintf('%04d', explode('.', microtime(true))[1]) . '4' . sprintf('%9d', rand(0, 999999999)); break; default: $transactionNo = date('YmdHis') . sprintf('%04d', explode('.', microtime(true))[1]) . '0' . sprintf('%9d', rand(0, 999999999)); break; } return strval($transactionNo); } /** * 订单卡查询 * * @param array $conditions * @return void */ public function cards(array $conditions = []) { $conditions['limit'] = $conditions['limit'] ?? 20; $cards = $this->orderCardPartitionRepository->withRefunded()->select(['sim', 'counts', 'refunded_at']) ->withConditions($conditions)->orderBy('sim') ->paginate($conditions['limit']); return $cards; } /** * 排单 * * @param int $orderId * @param array $simArray * @return Order */ public function ship($orderId, array $simArray) { if (!$order = $this->orderRepository->find($orderId)) { throw new NotExistException('订单不存在或已删除'); } $orderShipments = $this->orderCardPartitionRepository->select([ DB::raw('SUM(counts) as shipments'), DB::raw('SUM(CASE WHEN refunded_at IS NULL THEN 0 ELSE 1 END) as refunds') ])->where('type', 0)->where('order_id', $orderId)->groupBy('order_id')->first(); $shipments = $orderShipments['shipments'] ?? 0; $refunds = $orderShipments['refunds'] ?? 0; if ($order->counts - ($shipments - $refunds) <= 0) { throw new NotAllowedException('订单已排满'); } if ($order->counts - ($shipments - $refunds) < count($simArray)) { throw new NotAllowedException('排单卡量大于订单卡量'); } $exists = $this->orderCardPartitionRepository->select('sim')->withConditions(['type' => 0, 'sim' => $simArray])->get()->pluck('sim')->toArray(); if (count($exists)) { $exists = implode(',', $exists); throw new NotAllowedException("存在已被其他订单使用的卡: ($exists)"); } $cards = CardService::getMongoCardsInfo($simArray); if (count($simArray) !== count($cards)) { $diff = array_diff($simArray, array_pluck($cards, 'sim')); $diff = implode(',', $diff); throw new NotExistException("存在未入库的卡: ($diff)"); } $array = array_map(function ($item) { return ['sim' => $item, 'counts' => 1]; }, $simArray); DB::beginTransaction(); try { if ($order->counts - ($shipments - $refunds) === count($simArray)) { $order->order_status = 2; $order->save(); } $this->upsertOrderCards($array, $order); $this->orderRepository->forgetCached(); $this->orderCardPartitionRepository->forgetCached(); app(RealOrderCardPartitionRepository::class)->forgetCached(); } catch (\Exception $e) { DB::rollBack(); throw new HttpException('操作失败'); } DB::commit(); return $order; } /** * 套餐升级 */ public function upgrade(array $attributes = []) { $rule = [ 'new_package_id' => ['required'], 'selected' => ['required', 'array'], ]; $message = [ 'new_package_id.required' => '请选择新的套餐', 'selected.required' => '请选择卡', ]; Validator::validate($attributes, $rule, $message); } protected function upsertOrderCards($array, $node) { $table = $this->tables[$node['type']]; $data = []; foreach ($array as $card) { $data[] = [ 'sim' => $card['sim'], 'counts' => $card['counts'], 'type' => $node['type'], 'order_id' => $node['id'], 'company_id' => $node['company_id'], 'package_id' => $node['package_id'], 'unit_price' => $node['unit_price'], 'created_at' => $node['order_at'], 'updated_at' => date('Y-m-d H:i:s'), ]; } if (empty($data)) { return; } foreach (array_chunk($data, 1000) as $value) { if ($table === 'virtual_order_cards' && DB::table($table)->whereIn('sim', array_pluck($value, 'sim'))->whereNull('deleted_at')->count()) { throw new ExistedException('出现重复销售卡'); } DB::table($table)->upsert($value, ['sim', 'order_id', 'refunded_at', 'deleted_at']); RealOrderCardPartition::whereIn('order_id', array_pluck($array, 'order_id')) ->whereIn('sim', array_pluck($value, 'sim'))->update(['virtual_order_id' => $node['id']]); } $simArray = array_pluck($data, 'sim'); MongoCardJob::dispatch($simArray)->onQueue('sync'); } }