6
0
Fork 0

添加活动管理,以及订单参与活动发券发赠品

release
vine_liutk 2022-03-17 16:09:31 +08:00
parent 6b7d6d6ba1
commit 831d49533e
12 changed files with 240 additions and 56 deletions

View File

@ -322,8 +322,8 @@ class OrderController extends AdminController
$builder = OrderProduct::withCount('afterSales')->where('order_id', $id);
$productGrid = Grid::make($builder, function (Grid $grid) {
$grid->column('name')->display(function ($value) {
if ($this->gift_for_sku_id) {
$value .= '-【赠品】';
if ($this->isGift()) {
$value = '【赠品】'.$value;
}
return $value;
});

View File

@ -110,7 +110,7 @@ class ProductSkuTable extends Grid
$grid->filter(function (Grid\Filter $filter) {
$filter->panel();
$filter->expand();
$filter->equal('name')->width(3);
$filter->like('name')->width(3);
});
});

View File

@ -3,6 +3,7 @@
namespace App\Admin\Services;
use App\Enums\PayWay;
use App\Events\OrderPaid;
use App\Exceptions\BizException;
use App\Models\Order;
use App\Models\OrderLog;
@ -44,7 +45,8 @@ class OrderService
//操作订单状态-需要调整为统一支付方法
$orderService = new EndpointOrderService();
$orderService->pay($order, PayWay::Offline);
//注册支付成功事件
OrderPaid::dispatch($order);
//记录操作日志
OrderLog::create([
'order_id'=> $order->id,

View File

@ -3,7 +3,11 @@
namespace App\Listeners;
use App\Events\OrderPaid;
use App\Models\ActivityProductPart;
use App\Models\ProductPartSku;
use App\Models\UserCoupon;
use App\Services\CouponService;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
use Throwable;
@ -34,26 +38,37 @@ class SendCoupons
// 处理购买分区商品送券
try {
DB::beginTransaction();
$products = $order->products()->with('sku.parts')->get();
// 整理订单商品的分区
$inValidParts = [];
foreach ($products->pluck('sku.parts') as $parts) {
foreach ($parts as $part) {
if ($part->is_show) {
// 分区去重
$inValidParts[$part->id] = $part;
$products = $order->products()->where('is_gift', false)->get()->toArray();
$_products = array_column($products, 'total_amount', 'sku_id');
$partSkus = ProductPartSku::with('part')->whereIn('sku_id', array_keys($_products))->get();
foreach ($partSkus as $partSku) {
if ($partSku->part?->is_show) {
if (isset($inValidParts[$partSku->part_id])) {
$inValidParts[$partSku->part_id] += $_products[$partSku->sku_id] ?? 0;
} else {
$inValidParts[$partSku->part_id] = $_products[$partSku->sku_id] ?? 0;
}
}
}
//根据分区整理参与的活动--todo
//根据活动规则计算发送券--todo
// foreach ($inValidParts as $inValidPart) {
// $this->couponService->receivePartCoupon($inValidPart, $order->user);
// }
//根据分区获取活动
$partActivities = ActivityProductPart::with(['activity', 'activity.gifts'])->whereHas('activity', function (Builder $query) {
return $query->where('is_use', true)->where('started_at', '<', now())->where('ended_at', '>=', now());
})->whereIn('part_id', array_keys($inValidParts))->get();
//根据活动规则计算发送券
foreach ($partActivities as $partActivity) {
//获取活动的赠送规则
$_giftsRule = $partActivity->activity?->gifts_rule;
//判断是否首单times=0为仅首单赠送, 1为不限
if ($_giftsRule['times'] == 0 && UserCoupon::where('activity_id', $partActivity->activity_id)->exists()) {
continue;//提前结束本次循环
}
//判断是否满足门槛
if (bcdiv($_giftsRule['value'], 100) > $inValidParts[$partActivity->part_id]) {
continue;//提前结束本次循环
}
//赠券
(new CouponService())->receiveActivityCoupons($partActivity->activity, $order->user, $order->id);
}
DB::commit();
} catch (Throwable $th) {

View File

@ -39,11 +39,11 @@ class Activity extends Model
public function coupons()
{
return $this->belongsToMany(Coupon::class, 'activity_coupons', 'activity_id', 'coupon_id');
return $this->belongsToMany(Coupon::class, 'activity_coupons', 'activity_id', 'coupon_id')->withPivot('qty');
}
public function gifts()
{
return $this->belongsToMany(ProductSku::class, 'activity_gifts', 'activity_id', 'sku_id');
return $this->belongsToMany(ProductSku::class, 'activity_gifts', 'activity_id', 'sku_id')->withPivot('qty');
}
}

View File

@ -12,4 +12,14 @@ class ActivityProductPart extends Model
protected $fillable = [
'activity_id', 'part_id',
];
public function part()
{
return $this->belongsTo(Part::class, 'part_id');
}
public function activity()
{
return $this->belongsTo(Activity::class, 'activity_id');
}
}

View File

@ -0,0 +1,14 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class OrderActivityInfo extends Model
{
use HasFactory;
public const TYPE_GIFT = 1;
public const TYPE_COUPON = 2;
}

View File

@ -11,6 +11,7 @@ class OrderProduct extends Model
*/
protected $casts = [
'specs' => 'json',
'is_gift'=>'boolean',
];
/**
@ -38,6 +39,8 @@ class OrderProduct extends Model
'after_sale_state',
'after_expire_at',
'remain_quantity',
'is_gift',
'activity_id',
];
public function packageProducts()
@ -97,7 +100,7 @@ class OrderProduct extends Model
*/
public function isGift()
{
return $this->gift_for_sku_id !== null;
return $this->gift_for_sku_id !== null || $this->is_gift == true;
}
/**

View File

@ -2,6 +2,7 @@
namespace App\Services;
use App\Models\Activity;
use App\Models\Coupon;
use App\Models\ProductPart;
use App\Models\ReceivePartCouponLog;
@ -84,6 +85,22 @@ class CouponService
ReceivePartCouponLog::create(['user_id'=>$user->id, 'part_id'=>$part->id]);
}
/**
* 根据活动领取优惠券
*
* @return void
*/
public function receiveActivityCoupons(Activity $activity, User $user)
{
foreach ($activity->coupons as $coupon) {
$someCoupons[] = [
'coupon'=>$coupon,
'num'=>$coupon->pivot->qty,
];
}
$this->receiveSomeCoupons($user, $someCoupons, $activity->id);
}
/**
* 领取一批券
*
@ -91,12 +108,12 @@ class CouponService
* @param array $coupons
* @return void
*/
protected function receiveSomeCoupons(User $user, array $coupons)
protected function receiveSomeCoupons(User $user, array $coupons, ?int $activityId = null)
{
$userCoupons = [];
foreach ($coupons as $coupon) {
for ($i = 0; $i < $coupon['num']; $i++) {
$userCoupons[] = self::createUserCouponData($user->id, $coupon['coupon']);
$userCoupons[] = self::createUserCouponData($user->id, $coupon['coupon'], $activityId ?? null);
}
//更新对应券发送量,余量;
$coupon['coupon']->increment('sent', $coupon['num']);
@ -126,7 +143,7 @@ class CouponService
*
* @return array
*/
public static function createUserCouponData(int $userId, Coupon $coupon)
public static function createUserCouponData(int $userId, Coupon $coupon, ?int $activityId = null)
{
//如果userId小于等于0直接退出
if ($userId <= 0) {
@ -150,6 +167,7 @@ class CouponService
'use_end_at' => $useEndAt,
'created_at' => now(),
'updated_at' => now(),
'activity_id' => $activityId ?? null,
];
}
}

View File

@ -10,16 +10,19 @@ use App\Enums\SocialiteType;
use App\Enums\WxpayTradeType;
use App\Exceptions\BizException;
use App\Exceptions\ShippingNotSupportedException;
use App\Models\ActivityProductPart;
use App\Models\DistributionPreIncomeJob;
use App\Models\Order;
use App\Models\OrderProduct;
use App\Models\ProductGift;
use App\Models\ProductPartSku;
use App\Models\ProductSku;
use App\Models\ShippingAddress;
use App\Models\SocialiteUser;
use App\Models\User;
use App\Models\UserCoupon;
use App\Services\Payment\WxpayService;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\DB;
@ -240,6 +243,7 @@ class OrderService
$orderProducts[] = [
'gift_for_sku_id' => null,
'is_gift'=> false,
'user_id' => $order->user_id,
'order_id' => $order->id,
'spu_id' => $sku->spu_id,
@ -263,35 +267,10 @@ class OrderService
// 扣除商品库存
$this->deductProduct($sku, $qty);
//根据订单参加的活动添加赠品 --todo
$gifts = [];
foreach ($gifts as $gift) {
$giftSku = $gift['sku'];
$orderProducts[] = [
'gift_for_sku_id' => $sku->id,
'user_id' => $order->user_id,
'order_id' => $order->id,
'spu_id' => $giftSku->spu_id,
'sku_id' => $giftSku->id,
'category_id' => $giftSku->category_id,
'name' => $giftSku->name,
'specs' => json_encode($giftSku->specs),
'cover' => $giftSku->cover,
'weight' => $giftSku->weight,
'sell_price' => $giftSku->sell_price,
'vip_price' => $giftSku->vip_price,
'sales_value' => 0, // 赠品不算销售值
'quantity' => $gift['num'],
'remain_quantity' => $gift['num'], // 剩余发货数量
'coupon_discount_amount' => 0,
'vip_discount_amount' => 0,
'total_amount' => 0,
'created_at' => $order->created_at,
'updated_at' => $order->updated_at,
];
}
}
//根据订单参加的活动添加赠品;
$gifts = $this->activityGifts($order, $orderProducts);
$orderProducts = array_merge($orderProducts, $gifts);
OrderProduct::insert($orderProducts);
}
@ -384,6 +363,80 @@ class OrderService
return $gifts;
}
/**
* Undocumented function
*
* @param Order $order
* @param [type] $products
* @return array $gifts
*/
protected function activityGifts(Order $order, $products)
{
$_products = array_column($products, 'total_amount', 'sku_id');
$inValidParts = [];
// 整理订单商品的分区
$partSkus = ProductPartSku::with('part')->whereIn('sku_id', array_keys($_products))->get();
foreach ($partSkus as $partSku) {
if ($partSku->part?->is_show) {
if (isset($inValidParts[$partSku->part_id])) {
$inValidParts[$partSku->part_id] += $_products[$partSku->sku_id] ?? 0;
} else {
$inValidParts[$partSku->part_id] = $_products[$partSku->sku_id] ?? 0;
}
}
}
//根据分区获取活动
$partActivities = ActivityProductPart::with(['activity', 'activity.gifts'])->whereHas('activity', function (Builder $query) {
return $query->where('is_use', true)->where('started_at', '<', now())->where('ended_at', '>=', now());
})->whereIn('part_id', array_keys($inValidParts))->get();
$giveGifts = [];
foreach ($partActivities as $partActivity) {
//获取活动的赠送规则
$_giftsRule = $partActivity->activity?->gifts_rule;
//判断是否首单times=0为仅首单赠送, 1为不限
if ($_giftsRule['times'] == 0 && OrderProduct::where('activity_id', $partActivity->activity_id)->exists()) {
continue;//提前结束本次循环
}
//判断是否满足门槛
if (bcdiv($_giftsRule['value'], 100) > $inValidParts[$partActivity->part_id]) {
continue;//提前结束本次循环
}
//返回赠品
$_gifts = $partActivity->activity->gifts;
foreach ($_gifts as $_gift) {
$giveGifts[] = [
'gift_for_sku_id'=> null,
'user_id' => $order->user_id,
'order_id' => $order->id,
'spu_id' => $_gift->spu_id,
'sku_id' => $_gift->id,
'category_id' => $_gift->category_id,
'name' => $_gift->name,
'specs' => json_encode($_gift->specs),
'cover' => $_gift->cover,
'weight' => $_gift->weight,
'sell_price' => $_gift->sell_price,
'vip_price' => $_gift->vip_price,
'sales_value' => 0, // 赠品不算销售值
'quantity' => $_gift->pivot->qty,
'remain_quantity' => $_gift->pivot->qty, // 剩余发货数量
'coupon_discount_amount' => 0,
'vip_discount_amount' => 0,
'total_amount' => 0,
'created_at' => $order->created_at,
'updated_at' => $order->updated_at,
'is_gift'=> true,
];
// 扣除商品库存
$this->deductProduct($_gift, $_gift->pivot->qty);
}
}
return $giveGifts;
}
/**
* 确认快速下单
*

View File

@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddIsGiftToOrderProductsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('order_products', function (Blueprint $table) {
//
$table->unsignedTinyInteger('is_gift')->nullable()->default(0)->comment('是否赠品');
$table->unsignedBigInteger('activity_id')->nullable()->comment('参与活动ID');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('order_products', function (Blueprint $table) {
//
$table->dropColumn(['is_gift', 'activity_id']);
});
}
}

View File

@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddActivityIdToUserCouponsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('user_coupons', function (Blueprint $table) {
//
$table->unsignedBigInteger('activity_id')->nullable()->comment('参与活动ID');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('user_coupons', function (Blueprint $table) {
//
$table->dropColumn(['activity_id']);
});
}
}