客户等级设置

This commit is contained in:
liu
2026-08-17 16:27:15 +08:00
parent 2eb27127c9
commit a06c45dc49
31 changed files with 548 additions and 1142 deletions
+7 -24
View File
@@ -5,8 +5,8 @@ namespace App\Http\Controllers\Mini;
use App\Exceptions\RepositoryException;
use App\Http\Requests\Mini\MiniCartRequest;
use App\Models\CartModel;
use App\Models\CustomerLevelModel;
use App\Models\ProductModel;
use App\Models\ProductPriceModel;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
@@ -36,7 +36,7 @@ class CartController extends BaseMiniController
{
$user = $this->currentUser($request);
$store = $this->ensureStoreBound($user);
if ($store->level_id <= 0) {
if ($store->level_id <= 0 || $store->level === null) {
return $this->error('门店未设置客户等级,无法加购,请联系客服');
}
@@ -45,14 +45,6 @@ class CartController extends BaseMiniController
if ($product === null) {
return $this->error('商品不存在或已下架,请刷新后重试');
}
// 存在性校验与计价类型无关(百分比行 price 可能为 0 也能加购)
$hasPrice = ProductPriceModel::query()
->where('product_id', $productId)
->where('level_id', $store->level_id)
->exists();
if (! $hasPrice) {
return $this->error('商品「' . $product->name . '」价格未设置,无法加购');
}
$quantity = (string) $request->validated('quantity');
@@ -115,11 +107,8 @@ class CartController extends BaseMiniController
->unique()->values()->all();
$products = ProductModel::withTrashed()->whereIn('id', $productIds)->get()->keyBy('id');
$priceRows = ProductPriceModel::query()
->where('level_id', $store->level_id)
->whereIn('product_id', $productIds)
->get(['product_id', 'price', 'price_type', 'percent'])
->keyBy('product_id');
// 门店等级(售价 = 成本价 × (100 + 等级上浮比例) / 100
$level = $store->level_id > 0 ? $store->level : null;
// 图片一次查回(避免 ProductModel::$appends images_arr 的 N+1)。
// 注意:image_ids 有 imageIds Attribute 访问器(get 返回数组),需取原始值
@@ -141,16 +130,10 @@ class CartController extends BaseMiniController
foreach ($rows as $row) {
$product = $products->get($row->product_id);
$productOn = $product !== null && $product->status === ProductModel::STATUS_ON;
// 实际价(百分比计价行按成本价上浮换算);未设等级为 null
$priceRow = $priceRows->get($row->product_id);
$price = $priceRow === null
// 实际价(按门店等级上浮比例换算);未设等级为 null
$price = $level === null
? null
: ProductPriceModel::calcActualPrice(
(int) $priceRow->price_type,
$priceRow->price,
$priceRow->percent,
(float) ($product?->cost_price ?? 0),
);
: CustomerLevelModel::calcLevelPrice((float) ($product?->cost_price ?? 0), $level->percent);
$buyable = $productOn && $price !== null;
$quantity = (string) $row->quantity;
+6 -20
View File
@@ -4,8 +4,8 @@ namespace App\Http\Controllers\Mini;
use App\Exceptions\RepositoryException;
use App\Http\Requests\Mini\MiniOrderRequest;
use App\Models\CustomerLevelModel;
use App\Models\ProductModel;
use App\Models\ProductPriceModel;
use App\Models\StoreOrderItemModel;
use App\Models\StoreOrderModel;
use App\Services\BillNumberService;
@@ -32,14 +32,15 @@ class OrderController extends BaseMiniController
{
$user = $this->currentUser($request);
$store = $this->ensureStoreBound($user);
if ($store->level_id <= 0) {
$level = $store->level_id > 0 ? $store->level : null;
if ($level === null) {
throw new RepositoryException('门店未设置客户等级,无法下单,请联系客服');
}
$items = $request->validated('items');
$remark = (string) ($request->validated('remark') ?? '');
$order = DB::transaction(function () use ($store, $items, $remark) {
$order = DB::transaction(function () use ($store, $level, $items, $remark) {
$productIds = array_map(static fn ($row) => (int) $row['product_id'], $items);
$products = ProductModel::query()
@@ -48,12 +49,6 @@ class OrderController extends BaseMiniController
->get()
->keyBy('id');
$priceRows = ProductPriceModel::query()
->where('level_id', $store->level_id)
->whereIn('product_id', $productIds)
->get(['product_id', 'price', 'price_type', 'percent'])
->keyBy('product_id');
$totalQuantity = '0';
$totalAmount = '0';
$now = now();
@@ -64,18 +59,9 @@ class OrderController extends BaseMiniController
if ($product === null) {
throw new RepositoryException('存在已下架或不存在的商品,请刷新后重试');
}
if (! isset($priceRows[$productId])) {
throw new RepositoryException('商品「' . $product->name . '」未设置您所在等级的价格,无法下单');
}
// 实际价(百分比计价行按成本价上浮换算,$products 已含 cost_price
$priceRow = $priceRows[$productId];
$price = ProductPriceModel::calcActualPrice(
(int) $priceRow->price_type,
$priceRow->price,
$priceRow->percent,
$product->cost_price,
);
// 实际价(按门店等级上浮比例换算,$products 已含 cost_price
$price = CustomerLevelModel::calcLevelPrice($product->cost_price, $level->percent);
$quantity = (string) $row['quantity'];
$amount = bcmul($price, $quantity, 2);
$totalQuantity = bcadd($totalQuantity, $quantity, 2);
+11 -33
View File
@@ -3,9 +3,9 @@
namespace App\Http\Controllers\Mini;
use App\Exceptions\RepositoryException;
use App\Models\CustomerLevelModel;
use App\Models\ProductCategoryModel;
use App\Models\ProductModel;
use App\Models\ProductPriceModel;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Modules\AnnoRoute\Attribute\GetRoute;
@@ -50,30 +50,17 @@ class ProductController extends BaseMiniController
->orderBy('id')
->paginate($pageSize);
// 当前门店的等级价格(一次性取出,避免逐行查询
// 当前门店的等级(售价 = 成本价 × (100 + 等级上浮比例) / 100
$user = $this->optionalUser($request);
$store = $user !== null ? $this->boundStore($user) : null;
$priceRows = collect();
if ($store !== null && $store->level_id > 0) {
$priceRows = ProductPriceModel::query()
->where('level_id', $store->level_id)
->whereIn('product_id', $paginator->getCollection()->pluck('id'))
->get(['product_id', 'price', 'price_type', 'percent'])
->keyBy('product_id');
}
$level = ($store !== null && $store->level_id > 0) ? $store->level : null;
$paginator->getCollection()->transform(
static function (ProductModel $product) use ($priceRows): array {
static function (ProductModel $product) use ($level): array {
$row = $product->toArray();
// 实际价(百分比计价行按成本价上浮换算;成本价不随序列化输出)
$priceRow = $priceRows->get($product->id);
$row['price'] = $priceRow !== null
? ProductPriceModel::calcActualPrice(
(int) $priceRow->price_type,
(string) $priceRow->price,
(string) $priceRow->percent,
(string) $product->cost_price,
)
// 实际价(按等级上浮比例换算;成本价不随序列化输出)
$row['price'] = $level !== null
? CustomerLevelModel::calcLevelPrice($product->cost_price, $level->percent)
: null;
return $row;
}
@@ -83,7 +70,7 @@ class ProductController extends BaseMiniController
}
/**
* 商品详情(免登录浏览;登录门店按等级显示换算价,未登录/未绑店/未设等级 price=null
* 商品详情(免登录浏览;登录门店按等级上浮比例显示换算价,未登录/未绑店/未设等级 price=null
*/
#[GetRoute('/product/{id}', authorize: false, where: ['id' => '[0-9]+'])]
public function detail(int $id, Request $request): JsonResponse
@@ -99,18 +86,9 @@ class ProductController extends BaseMiniController
$price = null;
$user = $this->optionalUser($request);
$store = $user !== null ? $this->boundStore($user) : null;
if ($store !== null && $store->level_id > 0) {
$priceRow = ProductPriceModel::query()
->forProductLevel($product->id, $store->level_id)
->first(['price', 'price_type', 'percent']);
if ($priceRow !== null) {
$price = ProductPriceModel::calcActualPrice(
(int) $priceRow->price_type,
(string) $priceRow->price,
(string) $priceRow->percent,
(string) $product->cost_price,
);
}
$level = ($store !== null && $store->level_id > 0) ? $store->level : null;
if ($level !== null) {
$price = CustomerLevelModel::calcLevelPrice($product->cost_price, $level->percent);
}
$data = $product->toArray();