caipan_shop_admin/app/traits/order/ShoppingCartTrait.php

268 lines
8.7 KiB
PHP
Executable File

<?php
namespace app\traits\order;
use app\exception\RepositoryException;
use app\model\mall\SpuLimitTime;
use app\model\OrderSku;
use app\model\ShoppingCart;
use app\model\Sku;
use app\model\Spu;
use app\repository\OrderRepository;
use app\repository\SpuRepository;
use Exception;
use think\Collection;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Db;
/**
* 购物车相关
*
* Trait ShoppingCartTrait
* @package app\traits\order
*/
trait ShoppingCartTrait
{
/**
* 获取购物车列表
*
* @param int $accountId
* @param string $type
* @param int $page
* @param int $size
* @return array
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public function shoppingCart(int $accountId, string $type = '', int $page = 1, int $size = 20): array
{
$isScore = $type == 'score' ? 1 : 0;
$res = [
'total' => 0,
'current' => $page,
'size' => $size,
'list' => new Collection(),
];
$query = ShoppingCart::where('account_id', $accountId)
->where('is_score', $isScore)
->with([
'spu' => function ($query) {
$query->field('id,name as spu_name,cover as spu_cover,original_price,unit');
},
'sku' => function ($query) {
$query->field('id,title as sku_name,main_image as sku_cover,price as sku_price,coding,spec_text,type as activity_type');
}
]);
$res['total'] = $query->count();
if ($res['total'] > 0) {
$list = $query->order('updated_at', 'desc')
->page($page)
->limit($size)
->select();
$res['list'] = $list->each(function ($item) {
if (!isset($item->sku) || !isset($item->sku->activity_type)) {
unset($item);
} else {
if (!isset($item->sku->spec_text)) {
$item->sku->spec_text = [];
} else {
$specArr = json_decode($item->sku->spec_text, true);
$item->sku->spec_text = $specArr;
$item->sku->spec_info = SpuRepository::getInstance()->convertSpecInfo($specArr);
}
}
unset($item->spu_activity);
unset($item->activity_skus);
});
}
return $res;
}
/**
* 购物车保存
*
* @param int $accountId
* @param int $skuId
* @param int $num 最终购物车数量 注意 不是新增的数量 而是最终保存的数量。若=0 则删除
* @return bool
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @throws RepositoryException
*/
public function shoppingCartAdd(int $accountId, int $skuId, int $num = 1): bool
{
if (!$skuInfo = SpuRepository::getInstance()->infoBySkuId($skuId)) {
throw new RepositoryException('商品不存在或已下架');
}
if ($item = ShoppingCart::where('account_id', $accountId)->where('sku_id', $skuId)->find()) {
$update['updated_at'] = date('Y-m-d H:i:s');
$update['spu_name'] = $skuInfo['spu_name'] ?? ($skuInfo['spu_activity_name'] ?? '');
$update['sku_price'] = $skuInfo['sku_price'];
$update['score'] = $skuInfo['sku_score'];
$update['sku_name'] = $skuInfo['sku_name'];
$update['sku_cover'] = $skuInfo['sku_cover'];
$item->inc('num', $num)->update($update);
return true;
}
ShoppingCart::create([
'account_id' => $accountId,
'spu_activity_id' => $skuInfo['spu_activity_id'] ?? 0,
'spu_id' => $skuInfo['spu_id'],
'sku_id' => $skuInfo['id'],
'original_price' => $skuInfo['original_price'],
'price' => $skuInfo['price'],
'score' => $skuInfo['sku_score'],
'num' => $num,
'created_at' => date('Y-m-d H:i:s'),
'spu_name' => $skuInfo['spu_name'] ?? ($skuInfo['spu_activity_name'] ?? ''),
'sku_price' => $skuInfo['price'],
'sku_name' => $skuInfo['sku_name'],
'sku_cover' => $skuInfo['main_image'],
'is_score' => $skuInfo['is_score'] ?? 0,
]);
return true;
}
/**
* 购物车数量变更
*
* @param int $id
* @param int $num
* @return bool
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @throws RepositoryException
*/
public function shoppingCartChangeNum(int $id, int $num = 1): bool
{
if (!$item = ShoppingCart::where('id', $id)->find()) {
throw new RepositoryException('记录不存在');
}
return $item->save(['num' => $num]);
}
/**
* 购物车删除
*
* @param int $accountId
* @param int $id
* @return bool
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @throws RepositoryException
*/
public function shoppingCartDel(int $accountId, int $id): bool
{
if (!$item = ShoppingCart::where('id', $id)->find()) {
return true;
}
if ($item['account_id'] != $accountId) {
throw new RepositoryException('这不是您的购物车商品');
}
return $item->delete();
}
/**
* 删除指定订单相关的购物车数据
*
* @param int $accountId
* @param string $orderId
* @return bool
*/
public function delShoppingCartByOrder(int $accountId, string $orderId): bool
{
Db::startTrans();
try {
$orderSkus = OrderSku::where('coding', $orderId)->field('id,coding,sku_id,num')->select();
$sku2Num = $orderSkus->column('num', 'sku_id');
if (empty($orderSkus)) {
return true;
}
$list = ShoppingCart::where('account_id', $accountId)
->field('id,sku_id,num')
->whereIn('sku_id', $orderSkus->column('sku_id'))
->lock(true)->select();
$update = [];
foreach ($list as $v) {
$arr = [];
$arr['num'] = $v['num'] - ($sku2Num[$v['sku_id']] ?? 1);
$arr['num'] = $arr['num'] < 0 ? 0 : $arr['num'];
$arr['id'] = $v['id'];
$update[] = $arr;
}
(new ShoppingCart())->saveAll($update);
ShoppingCart::where('account_id', $accountId)->where('num', '<=', 0)->delete();
Db::commit();
return true;
} catch (Exception $e) {
Db::rollback();
OrderRepository::log('清理购物车数据失败', $e);
return false;
}
}
/**
* 检查并清理购物车不存在的商品和sku
* @param int $accountId
* @return bool
*/
public function checkShoppingCart(int $accountId = 0): bool
{
$where = [];
if ($accountId > 0) {
$where[] = ['account_id', '=', $accountId];
}
$items = ShoppingCart::where($where)->column('spu_id,sku_id');
$spuIds = array_unique(array_column($items, 'spu_id'));
$skuIds = array_unique(array_column($items, 'sku_id'));
$notExistSpu = [];
if ($spuIds) {
$existSpu = Spu::whereIn('id', $spuIds)->whereNull('deleted_at')->column('id');
$notExistSpu = array_diff($spuIds, $existSpu);
}
$notExistSku = [];
if ($skuIds) {
$existSku = Sku::whereIn('id', $skuIds)->whereNull('deleted_at')->column('id');
$notExistSku = array_diff($skuIds, $existSku);
}
if (!empty($notExistSku) || !empty($notExistSpu)) {
ShoppingCart::where($where)
->where(function ($q) use ($notExistSku, $notExistSpu) {
if (!empty($notExistSpu)) {
$q->whereOr('spu_id', 'in', $notExistSpu);
}
if (!empty($notExistSku)) {
$q->whereOr('sku_id', 'in', $notExistSku);
}
})
->delete();
}
return true;
// return ['noteSpu' => $notExistSpu, 'notSku' => $notExistSku, 'needDel' => $needDel, 'count' => count($needDel)];
}
}