6
0
Fork 0

积分当钱花

base
Jing Li 2023-10-17 19:49:31 +08:00
parent 3448852885
commit 3b6a1e024e
15 changed files with 214 additions and 18 deletions

View File

@ -79,6 +79,7 @@ class AfterSaleController extends AdminController
}
return bcdiv($value, 100, 2);
})->prepend('¥');
$grid->column('points');
$grid->column('type')->using([
AfterSaleModel::TYPE_REFUND_AND_RETURN => '退款退货',
AfterSaleModel::TYPE_REFUND => '退款',
@ -158,6 +159,7 @@ class AfterSaleController extends AdminController
$show->field('amount', '售后金额')->as(function ($amount) {
return '¥'.bcdiv($amount, 100, 2);
});
$show->field('points', '售后积分');
}
$show->width(6)->field('user.user_info.nickname', '下单用户');
$show->field('user.phone');

View File

@ -66,13 +66,15 @@ class AfterSaleVerify extends Form implements LazyRenderable
}
//调整换货补货时amount问题
$amount = (int) Arr::get($input, 'amount', 0) ?: $afterSale->amount;
$points = (int) Arr::get($input, 'points', 0) ?: $afterSale->points;
if (in_array($afterSale->type, [Aftersale::TYPE_CHANGE, Aftersale::TYPE_FILL])) {
//如果调整数量, 则同时调整价格
if ($num != $afterSale->num) {
$amount = bcmul(bcdiv($afterSale->amount, $afterSale->num), $num);
$points = bcmul(bcdiv($afterSale->points, $afterSale->num), $num);
}
}
$afterSaleService->verify($afterSale, $input['remarks3'], $amount, $num);
$afterSaleService->verify($afterSale, $input['remarks3'], $amount, $points, $num);
} elseif ($input['state'] == 1) {//需要补充资料
$afterSaleService->backApply($afterSale, $input['remarks1']);
}
@ -103,6 +105,7 @@ class AfterSaleVerify extends Form implements LazyRenderable
})->saving(function ($amount) {
return bcmul($amount, 100);
})->symbol('¥');
$this->number('points')->default($afterSale->points);
}
$this->radio('state')

View File

@ -50,6 +50,7 @@ class OrderController extends Controller
'shipping_address_id' => ['bail', 'nullable', 'int'],
'coupon_id' => ['bail', 'nullable', 'int'],
'note' => ['bail', 'nullable', 'string', 'max:255'],
'points' => ['bail', 'nullable', 'int'],
], match (true) {
$request->filled('order_pre') => [
'order_pre' => ['bail','required', 'int'],
@ -72,8 +73,9 @@ class OrderController extends Controller
'shipping_address_id' => '收货地址',
'coupon_id' => '优惠券',
'note' => '订单备注',
'points' => '积分',
]);
$user = $request->user();
try {
@ -89,9 +91,16 @@ class OrderController extends Controller
'desk' => $request->input('desk'),
'note' => $request->input('note'),
'coupon_id' => $request->input('coupon_id'),
]
'points' => $request->input('points', 0),
],
),
$request->filled('order_pre') => $orderService->createOrderByPre(
$user,
OrderPre::findOrFail($request->input('order_pre')),
$request->input('coupon_id'),
$request->input('note'),
$request->input('points', 0),
),
$request->filled('order_pre') => $orderService->createOrderByPre($user, OrderPre::findOrFail($request->input('order_pre')), $request->input('coupon_id'), $request->input('note')),
$request->filled('product') => $orderService->createQuickOrder(
$user,
$validated['product']['sku_id'],
@ -99,6 +108,7 @@ class OrderController extends Controller
$validated['shipping_address_id'] ?? null,
$validated['coupon_id'] ?? null,
$validated['note'] ?? null,
$request->input('points', 0),
),
default => $orderService->createShoppingCartOrder(
$user,
@ -106,6 +116,7 @@ class OrderController extends Controller
$validated['shipping_address_id'] ?? null,
$validated['coupon_id'] ?? null,
$validated['note'] ?? null,
$request->input('points', 0),
),
};
});

View File

@ -21,7 +21,7 @@ class AfterSaleResource extends JsonResource
'product'=>[
'name' => $this->orderProduct->name,
'cover' => $this->orderProduct->cover,
'sell_price' => bcdiv($this->orderProduct->total_amount, $this->orderProduct->quantity * 100, 2),
'sell_price' => bcdiv($this->orderProduct->sell_price, 100, 2),
'num'=> $this->num,
'is_gift' => $this->orderProduct->isGift(),
'total_amount' => $this->orderProduct->total_amount,
@ -33,6 +33,7 @@ class AfterSaleResource extends JsonResource
'remarks' => $this->remarks,
'created_at' => $this->created_at->toDateTimeString(),
'amount'=> $this->amount_format,
'points' => $this->points,
// 'logs' => AfterSaleLogResource::make($this->whenLoaded('logs')),
];
}

View File

@ -30,6 +30,7 @@ class OrderResource extends JsonResource
'bargain_amount' => $this->bargain_amount_format,
'shipping_fee' => $this->shipping_fee_format,
'products_total_amount' => $this->products_total_amount_format,
'point_discount_amount' => $this->point_discount_amount_format,
'total_amount' => $this->total_amount_format,
'status' => $this->order_status,
'note' => (string) $this->note,

View File

@ -8,6 +8,7 @@ enum PointLogAction: int {
case Recharge = 1;
case Deduction = 2;
case Consumption = 3;
case Refund = 4;
public function label(): string
{
@ -20,6 +21,7 @@ enum PointLogAction: int {
self::Recharge->value => '充值',
self::Deduction->value => '扣减',
self::Consumption->value => '消费',
self::Refund->value => '退还',
];
}
}

View File

@ -30,6 +30,10 @@ class AfterSale extends Model
'images' => JsonArray::class,
];
protected $attributes = [
'points' => 0,
];
protected $fillable = [
'user_id',
'order_id',
@ -43,6 +47,7 @@ class AfterSale extends Model
'remarks',
'tracking_number',
'sales_value',
'points',
];
public static $stateText = [

View File

@ -4,10 +4,10 @@ namespace App\Models;
use App\Constants\OrderStatus;
use App\Enums\PayWay;
use App\Models\Store\Store;
use Dcat\Admin\Traits\HasDateTimeFormatter;
use EloquentFilter\Filterable;
use Illuminate\Database\Eloquent\Model;
use App\Models\Store\Store;
class Order extends Model
{
@ -45,6 +45,7 @@ class Order extends Model
'reduced_amount' => 0,
'is_change' => false,
'status' => self::STATUS_PENDING,
'point_discount_amount' => 0,
];
/**
@ -98,6 +99,7 @@ class Order extends Model
'market_price',
'cost_price',
'profit_paid',
'point_discount_amount',
];
/**
@ -459,4 +461,9 @@ class Order extends Model
{
return trim_trailing_zeros(bcdiv($this->attributes['bargain_amount'], 100, 2));
}
public function getPointDiscountAmountFormatAttribute()
{
return trim_trailing_zeros(bcdiv($this->attributes['point_discount_amount'], 100, 2));
}
}

View File

@ -9,6 +9,10 @@ class OrderProduct extends Model
/**
* @var array
*/
protected $attributes = [
'point_discount_amount' => 0,
];
protected $casts = [
'specs' => 'json',
'is_gift'=>'boolean',
@ -44,6 +48,8 @@ class OrderProduct extends Model
'bargain_amount',
'market_price',
'cost_price',
'spent_points',
'point_discount_amount',
];
public function packageProducts()

View File

@ -3,6 +3,7 @@
namespace App\Services;
use App\Admin\Services\OrderService;
use App\Enums\PointLogAction;
use App\Exceptions\BizException;
use App\Models\AfterSale;
use App\Models\AfterSaleLog;
@ -42,8 +43,9 @@ class AfterSaleService
}
$amount = ($num == $orderProduct->quantity) ? $orderProduct->total_amount : bcmul(bcdiv($orderProduct->total_amount, $orderProduct->quantity), $num);
$points = ($num == $orderProduct->quantity) ? $orderProduct->point_discount_amount : bcmul(bcdiv($orderProduct->point_discount_amount, $orderProduct->quantity), $num);
if ($amount == 0 && in_array($params['type'], [AfterSale::TYPE_REFUND])) {
if (($amount == 0 && $points == 0) && in_array($params['type'], [AfterSale::TYPE_REFUND])) {
throw new BizException('实际支付金额为0的商品无法发起退款售后');
}
@ -51,6 +53,7 @@ class AfterSaleService
'user_id' => $user->id,
'order_id' => $orderProduct->order_id,
'amount' => $amount,
'points' => $points,
'state' => AfterSale::STATE_VERIFY,
'sales_value' => $orderProduct->sales_value,
]));
@ -150,7 +153,7 @@ class AfterSaleService
* @param string $remarks
* @return void
*/
public function verify(AfterSale $afterSale, string $remarks, int $amount, ?int $num = null)
public function verify(AfterSale $afterSale, string $remarks, int $amount, int $points, ?int $num = null)
{
if ($this->isWaitVerify($afterSale)) {
switch ($afterSale->type) {
@ -158,6 +161,7 @@ class AfterSaleService
$afterSale->update([
'num' => $num,
'amount' => $amount,
'points' => $points,
'state' => $afterSale::STATE_AGREE,
'remarks' => $remarks,
]);
@ -171,6 +175,7 @@ class AfterSaleService
$afterSale->update([
'num' => $num,
'amount' => $amount,
'points' => $points,
'state' => $afterSale::STATE_AGREE,
'remarks' => $remarks,
]);
@ -184,6 +189,7 @@ class AfterSaleService
$afterSale->update([
'num' => $num,
'amount' => $amount,
'points' => $points,
'state' => $afterSale::STATE_AGREE,
'remarks' => $remarks,
]);
@ -197,6 +203,7 @@ class AfterSaleService
$afterSale->update([
'num' => $num,
'amount' => $amount,
'points' => $points,
'state' => $afterSale::STATE_AGREE,
'remarks' => $remarks,
]);
@ -390,6 +397,10 @@ class AfterSaleService
$salesValue = bcmul($afterSaleProduct->sales_value, $qty, 2);
}
if ($afterSale->points > 0) {
(new PointService())->change($order->user, $afterSale->points, PointLogAction::Refund, "售后单{$afterSale->sn}退还积分", $afterSale);
}
//执行实际退款操作;
if ($afterSale->amount > 0) {//退款金额大于0才做实际退款
$order->refundLogs()->create([

View File

@ -6,6 +6,7 @@ use App\Endpoint\Api\Http\Resources\ProductSkuSimpleResource;
use App\Endpoint\Api\Http\Resources\ShippingAddressResource;
use App\Endpoint\Api\Http\Resources\UserCouponResource;
use App\Enums\PayWay;
use App\Enums\PointLogAction;
use App\Enums\SocialiteType;
use App\Enums\WxpayTradeType;
use App\Exceptions\BizException;
@ -20,9 +21,9 @@ use App\Models\ProductPartSku;
use App\Models\ProductSku;
use App\Models\ShippingAddress;
use App\Models\SocialiteUser;
use App\Models\{User, OrderPre, Tag};
use App\Models\Store\{Store, Desk, DeviceRecord};
use App\Models\UserCoupon;
use App\Models\{User, OrderPre, Tag};
use App\Services\Payment\WxpayService;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\QueryException;
@ -49,6 +50,7 @@ class OrderService
?int $shippingAddressId,
?int $couponId = null,
?string $note = null,
?int $points = null,
?BargainOrder $bargainOrder = null,
): Order {
$sku = ProductSku::online()->findOrFail($skuId);
@ -58,7 +60,7 @@ class OrderService
'quantity' => $quantity,
];
return $this->createOrder($user, [$product], $shippingAddressId, $couponId, $note, $bargainOrder);
return $this->createOrder($user, [$product], $shippingAddressId, $couponId, $note, $points, $bargainOrder);
}
/**
@ -78,13 +80,15 @@ class OrderService
int $shippingAddressId,
?int $couponId = null,
?string $note = null,
?int $points = null,
): Order {
$order = $this->createOrder(
$user,
$this->getProductsByShoppingCart($user, $shoppingCartItemIds),
$shippingAddressId,
$couponId,
$note
$note,
$points,
);
$user->shoppingCartItems()->whereIn('id', $shoppingCartItemIds)->delete();
@ -109,6 +113,7 @@ class OrderService
?int $shippingAddressId,
?int $couponId = null,
?string $note = null,
?int $points = null,
?BargainOrder $bargainOrder = null,
): Order {
foreach ($products as $product) {
@ -148,12 +153,13 @@ class OrderService
$couponDiscountAmount,
$vipDiscountAmount,
$shippingFee,
$points,
$salesValue,
$shippingAddress,
$note,
$coupon,
$bargainOrder,//添加砍价订单逻辑
$mapProducts
$mapProducts,
);
$this->storeOrderProducts($order, $mapProducts);
@ -173,7 +179,7 @@ class OrderService
/**
* 预订单, 扫码下单
*/
public function createOrderByPre(User $user, OrderPre $order_pre, $coupon_id = null, $note = null)
public function createOrderByPre(User $user, OrderPre $order_pre, $coupon_id = null, $note = null, int $points = 0)
{
$products = [];
foreach($order_pre->products as $item) {
@ -208,6 +214,7 @@ class OrderService
$couponDiscountAmount,
$vipDiscountAmount,
0,
$points,
$salesValue,
null,
$note,
@ -303,6 +310,7 @@ class OrderService
$couponDiscountAmount,
$vipDiscountAmount,
0,
$params['points'] ?? 0,
$salesValue,
null,
$note,
@ -352,13 +360,17 @@ class OrderService
int $couponDiscountAmount,
int $vipDiscountAmount,
int $shippingFee,
int $points,
$salesValue,
?ShippingAddress $shippingAddress,
?string $note = null,
?UserCoupon $coupon = null,
?BargainOrder $bargainOrder = null,
?array $mapProducts = null
?array $mapProducts = null,
): Order {
// 积分抵扣金额(1积分等于1分钱)
$pointDiscountAmount = $points;
// 订单支付金额=商品总额-券折扣金额-会员折扣金额+邮费-砍价金额
$totalAmount = $productsTotalAmount - $couponDiscountAmount - $vipDiscountAmount;
@ -372,6 +384,7 @@ class OrderService
}
$totalAmount += $shippingFee;
$totalAmount -= $pointDiscountAmount;
// 生成不重复的订单号
do {
@ -406,9 +419,18 @@ class OrderService
'bargain_amount'=>$bargainOrder?->bargain_price ?? 0,
'market_price' => $market_price,
'cost_price' => $cost_price,
// 积分抵扣金额
'point_discount_amount' => $pointDiscountAmount,
];
return $user->orders()->create($attrs);
$order = $user->orders()->create($attrs);
// 扣除积分
if ($points > 0) {
(new PointService)->change($user, -$points, PointLogAction::Consumption, "订单{$order->sn}使用积分", $order);
}
return $order;
}
/**
@ -420,15 +442,24 @@ class OrderService
*/
public function storeOrderProducts(Order $order, array $mapProducts)
{
// 积分抵扣金额
$remainingPointDiscountAmount = $order->point_discount_amount;
$orderProducts = [];
foreach ($mapProducts as $product) {
$sku = $product['sku'];
$qty = $product['quantity'];
// 支付金额 = 商品总额 - 优惠券折扣金额- 会员折扣金额 - 砍价金额
// 支付金额 = 商品总额 - 优惠券折扣金额 - 会员折扣金额 - 砍价金额
$totalAmount = $product['total_amount'] - $product['coupon_discount_amount'] - $product['vip_discount_amount'] - $product['bargain_amount'];
// 积分抵扣金额
$pointDiscountAmount = $totalAmount > $remainingPointDiscountAmount ? $remainingPointDiscountAmount : $totalAmount;
$remainingPointDiscountAmount -= $pointDiscountAmount;
$totalAmount -= $pointDiscountAmount;
$orderProducts[] = [
'gift_for_sku_id' => null,
'activity_id'=>null,
@ -451,6 +482,7 @@ class OrderService
'remain_quantity' => $qty, // 剩余发货数量
'coupon_discount_amount' => $product['coupon_discount_amount'],
'vip_discount_amount' => $product['vip_discount_amount'],
'point_discount_amount' => $pointDiscountAmount,
'total_amount' => $totalAmount,
'bargain_amount'=> $product['bargain_amount'],
'created_at' => $order->created_at,
@ -746,8 +778,13 @@ class OrderService
* @param int|null $bargainOrderId
* @return array
*/
public function verifyOrder(User $user, array $products, ?int $shippingAddressId = null, ?int $couponId = null, ?int $bargainOrderId = null): array
{
public function verifyOrder(
User $user,
array $products,
?int $shippingAddressId = null,
?int $couponId = null,
?int $bargainOrderId = null,
): array {
// 获取收货地址
$shippingAddress = $this->getShippingAddress($user, $shippingAddressId);
@ -795,6 +832,12 @@ class OrderService
$totalAmount += $shippingFee;
//---------------------------------------
// 积分当钱花
//---------------------------------------
$remainingPoints = $user->userInfo->points; // 用户剩余积分
$availablePoints = $totalAmount > $remainingPoints ? $remainingPoints : $totalAmount; // 可用积分
return [
'products' => collect($mapProducts)->map(function ($item) {
return [
@ -811,6 +854,9 @@ class OrderService
'coupon_discount_amount' => trim_trailing_zeros(bcdiv($couponDiscountAmount, 100, 2)), // 优惠券折扣金额
'total_amount' => trim_trailing_zeros(bcdiv($totalAmount, 100, 2)), // 实付金额
'bargain_amount' => trim_trailing_zeros(bcdiv($bargainAmount, 100, 2)), //砍价金额
'remaining_points' => $remainingPoints, // 剩余积分
'available_points' => $availablePoints, // 可用积分
'point_discount_amount' => trim_trailing_zeros(bcdiv($availablePoints, 100, 2)), // 积分抵扣金额
];
}
@ -1355,6 +1401,10 @@ class OrderService
]);
}
if ($order->point_discount_amount > 0) {
(new PointService())->change($order->user, $order->point_discount_amount, PointLogAction::Refund, "订单{$order->sn}退还积分", $order);
}
$order->update([
'status' => Order::STATUS_CANCELLED,
]);

View File

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddPointDiscountAmountToOrdersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('orders', function (Blueprint $table) {
$table->unsignedBigInteger('point_discount_amount')->default(0)->comment('积分抵扣金额');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('orders', function (Blueprint $table) {
$table->dropColumn(['point_discount_amount']);
});
}
}

View File

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddPointDiscountAmountToOrderProductsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('order_products', function (Blueprint $table) {
$table->unsignedBigInteger('point_discount_amount')->default(0)->comment('积分抵扣金额');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('order_products', function (Blueprint $table) {
$table->dropColumn(['point_discount_amount']);
});
}
}

View File

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddPointsToAfterSalesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('after_sales', function (Blueprint $table) {
$table->unsignedBigInteger('points')->default(0)->comment('积分');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('after_sales', function (Blueprint $table) {
$table->dropColumn(['points']);
});
}
}

View File

@ -42,6 +42,7 @@ return [
'tracking_number' => '运单号',
'created_at'=>'申请时间',
'tags' => '标签',
'points' => '积分',
],
'options' => [
],