vd/app/Domains/Virtual/Services/OrderService.php
2019-04-17 19:12:52 +08:00

882 lines
33 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Domains\Virtual\Services;
use App\Dicts;
use Carbon\Carbon;
use App\Core\Service;
use App\Models\Card\Card;
use App\Models\Virtual\Order;
use Illuminate\Validation\Rule;
use App\Models\Virtual\OrderCard;
use Illuminate\Support\Facades\DB;
use App\Exceptions\ExistedException;
use App\Exceptions\NotExistException;
use App\Exceptions\NotAllowedException;
use Illuminate\Support\Facades\Validator;
use App\Domains\Card\Services\CardService;
use App\Models\Virtual\OrderCardPartition;
use App\Exceptions\InvalidArgumentException;
use Dipper\Foundation\Exceptions\HttpException;
use App\Domains\Virtual\Services\CompanyService;
use App\Domains\Virtual\Services\PackageService;
use App\Domains\Virtual\Services\ProductService;
use App\Domains\Virtual\Repositories\OrderRepository;
use App\Domains\Virtual\Repositories\ProductRepository;
use App\Models\Real\OrderCardPartition as RealOrderCardPartition;
use App\Domains\Virtual\Repositories\OrderCardPartitionRepository;
use App\Domains\Real\Repositories\OrderRepository as RealOrderRepository;
use App\Domains\Real\Repositories\OrderCardPartitionRepository as RealOrderCardPartitionRepository;
class OrderService extends Service
{
protected $orderRepository;
protected $orderCardPartitionRepository;
protected $tables = [
'virtual_order_cards',
'virtual_order_renewal_cards',
'virtual_order_renewal_package_cards',
'virtual_order_flows_package_cards',
];
/**
* 构造函数
*
* @return void
*/
public function __construct(OrderRepository $orderRepository, OrderCardPartitionRepository $orderCardPartitionRepository)
{
$this->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')
])->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->shipments = $orderShipments[$item->id]['counts'] ?? 0;
$item->refunds = $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('已存在其他类型订单,不能修改企业');
}
}
$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) {
$simArray = array_unique(array_pluck($attributes['selected'], 'sim'));
$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 (count($news)) {
// 按订单时间激活
$array = array_map(function ($item) use ($newOrderData) {
return ['sim' => $item, 'virtual_activated_at' => $newOrderData['order_at']];
}, $news);
Card::upsert($array, 'sim', ['virtual_activated_at']);
// 创建订单
$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);
// 创建订单卡关联
$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 (count($extras)) {
$attributes['package_id'] = $attributes['package_id'] ?? $product->package_id;
$having = "MAX(service_end_at) < '%s'";
$having = sprintf($having, Carbon::now()->subMonths(6)->endOfMonth());
$replacement = $this->orderCardPartitionRepository->select(['sim'])
->where('company_id', $attributes['company_id'])
->where('package_id', $attributes['package_id'])
->whereIn('type', [0, 1])
->groupBy('sim')
->havingRaw($having)
->get()->pluck('sim')->toArray();
if (count($replacement) !== count($extras)) {
throw new NotAllowedException('可替换的卡量不足,不能进行转销售操作');
}
$updates = [];
foreach ($extras as $key => $value) {
$updates[] = [
'sim' => $value,
'original_sim' => $replacement[$key],
];
}
$this->orderCardPartitionRepository->updateBatch($updates, 'sim');
}
}
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', 'deleted_at']);
} catch (\Exception $e) {
DB::rollback();
throw $e;
}
DB::commit();
app(OrderRepository::class)->forgetCached();
app(OrderCardPartitionRepository::class)->forgetCached();
return true;
}
/**
* 取消订单
*
* @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('订单中的卡已存在于其他类型订单中,不能进行重置');
}
// 转销售重置
$sql = 'UPDATE virtual_order_cards_partition SET sim=original_sim,original_sim=0
WHERE original_sim IN (
SELECT DISTINCT SIM FROM virtual_order_cards_partition WHERE type=0 AND order_id = ?
)';
DB::statement($sql, [$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;
}
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', 'deleted_at']);
$simArray = implode(',', array_pluck($value, 'sim'));
DB::statement("select fix_timelines('{{$simArray}}'::INT8[]);");
RealOrderCardPartition::whereIn('order_id', array_pluck($array, 'order_id'))
->whereIn('sim', array_pluck($value, 'sim'))->update(['virtual_order_id' => $node['id']]);
}
}
}