268 lines
8.7 KiB
PHP
Executable File
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)];
|
|
}
|
|
} |