admin/app/frontend/modules/coupon/services/CouponService.php

305 lines
11 KiB
PHP

<?php
namespace app\frontend\modules\coupon\services;
use app\common\helpers\ArrayHelper;
use app\common\models\coupon\OrderGoodsCoupon;
use app\common\models\goods\GoodsCoupon;
use app\frontend\modules\coupon\services\models\Coupon;
use app\frontend\modules\order\models\PreOrder;
use app\Jobs\addGoodsCouponQueueJob;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Support\Collection;
class CouponService
{
use DispatchesJobs;
/**
* @var PreOrder
*/
private $order;
private $orderGoods;
private $coupon_method;
private $selectedMemberCoupon;
public function __construct($order, $coupon_method = null, $orderGoods = [])
{
$this->order = $order;
$this->orderGoods = $orderGoods;
$this->coupon_method = $coupon_method;
}
/**
* 获取订单优惠金额
* @return float
*/
public function getOrderDiscountPrice()
{
return $this->getAllValidCoupons()->sum(function (Coupon $coupon) {
if (!$coupon->valid()) {
return 0;
}
/**
* @var $coupon Coupon
*/
$coupon->activate();
return $coupon->getDiscountAmount();
});
}
/**
* 获取订单可算的优惠券
* @return Collection
*/
public function getOptionalCoupons()
{
//用户所有优惠券
$coupons = $this->getMemberCoupon()->map(function ($memberCoupon) {
return new Coupon($memberCoupon, $this->order);
});
//其他优惠组合后可选的优惠券(未选中)
$coupons = $coupons->filter(function ($coupon) {
/**
* @var $coupon Coupon
*/
//不可选
if (!$coupon->isOptional()) {
trace_log()->coupon("优惠券{$coupon->getMemberCoupon()->id}", '不可选');
return false;
}
//商城开启了多张优惠券 并且当前优惠券组合可以继续添加这张
$coupon->getMemberCoupon()->valid = (!\Setting::get('coupon.is_singleton') || $this->order->orderCoupons->isEmpty()) && $coupon->valid();//界面标蓝(是否可选)
$coupon->getMemberCoupon()->checked = false;//界面选中
return true;
})->values();
//已选的优惠券
$coupons = collect($this->order->orderCoupons)->map(function ($orderCoupon) {
// 已参与订单价格计算的优惠券
$orderCoupon->coupon->getMemberCoupon()->valid = true;
$orderCoupon->coupon->getMemberCoupon()->checked = true;
return $orderCoupon->coupon;
})->merge($coupons); //合并已选中和可用未选中优惠券
if ($this->order->orderCoupons->isNotEmpty() && !\Setting::get('shop.order.order_apart')) {
//商品里设置的可使用优惠券数量
$sum_goods = $this->order->orderGoods->sum(function ($orderGoods) {
if ($orderGoods->goods->hasOneGoodsCoupon->is_use_num == 0) {
return 0;
}
return $orderGoods->goods->hasOneGoodsCoupon->use_num * $orderGoods->total;
});
if (count($this->order->orderCoupons) > 0 && $sum_goods > 0 && count($this->order->orderCoupons) >= $sum_goods) {
//如果选中优惠券大于商品里设置的优惠券总和
$coupons = $coupons->map(function ($coupon, $key) use ($sum_goods) {
if ($sum_goods == 0) {
return $coupon;
}
if ($key >= $sum_goods) {
$coupon->getMemberCoupon()->valid = false;
$coupon->getMemberCoupon()->checked = false;
}
return $coupon;
});
}
}
//按member_coupon的id倒序
$coupons = $coupons->sortByDesc(function ($coupon) {
return $coupon->getMemberCoupon()->id;
})->values();
return $coupons;
}
/**
* 获取所有选中并有效的优惠券
* @return Collection
*/
public function getAllValidCoupons()
{
$coupon = $this->getSelectedMemberCoupon()->map(function ($memberCoupon) {
return new Coupon($memberCoupon, $this->order);
});
$result = $coupon->filter(function ($coupon) {
/**
* @var $coupon Coupon
*/
return $coupon->valid();
});
return $result;
}
/**
* 用户拥有的优惠券
* @return Collection
*/
private function getMemberCoupon()
{
$coupon_method = $this->coupon_method;
$result = MemberCouponService::getCurrentMemberCouponCache($this->order->belongsToMember);
if (isset($coupon_method)) {// 折扣/立减
$result = $result->filter(function ($memberCoupon) use ($coupon_method) {
return $memberCoupon->belongsToCoupon->coupon_method == $coupon_method;
});
}
return $result;
}
/**
* 用户拥有并选中的优惠券
* @return Collection
*/
private function getSelectedMemberCoupon()
{
if (!isset($this->selectedMemberCoupon)) {
$member_coupon_ids = ArrayHelper::unreliableDataToArray(\Request::input('member_coupon_ids'));
if (\Setting::get('coupon.is_singleton')) {
$member_coupon_ids = array_slice($member_coupon_ids, 0, 1);
}
$coupon_list = [];
//不实用集合方法是因为集合会把选中的顺序重新排序
foreach ($member_coupon_ids as $k => $v) {
$coupon = $this->getMemberCoupon()->where('id', $v);
$this->getMemberCoupon()->push($coupon);
$coupon_list[$k] = $coupon;
}
$this->selectedMemberCoupon = collect($coupon_list)->collapse();
}
return $this->selectedMemberCoupon;
}
public function sendCoupon()
{
$orderGoods = $this->orderGoods;
foreach ($orderGoods as $goods) {
$goodsCoupon = GoodsCoupon::ofGoodsId($goods->goods_id)->first();
//未开启 或 已关闭 或 未设置优惠券
if (!$goodsCoupon || !$goodsCoupon->is_give || !$goodsCoupon->coupon) {
continue;
}
//每月发送时,发送月数 为空 或为 0
if (($goodsCoupon->send_type == '0' || $goodsCoupon->send_type == '3') && empty($goodsCoupon->send_num)) {
continue;
}
for ($i = 1; $i <= $goods->total; $i++) {
switch ($goodsCoupon->send_type) {
//订单完成立即发送
case '1':
$this->promptlySendCoupon($goodsCoupon);
break;
//每月发送
case '0':
$this->everyMonthSendCoupon($goodsCoupon);
break;
}
}
}
}
/**
* 商品消费赠送优惠券新方式
*/
public function sendCouponLog()
{
$orderGoods = $this->orderGoods;
foreach ($orderGoods as $goods) {
$goodsCoupon = GoodsCoupon::ofGoodsId($goods->goods_id)->first();
//未开启 或 已关闭 或 未设置优惠券
if (!$goodsCoupon || !$goodsCoupon->is_give || !$goodsCoupon->coupon) {
continue;
}
//每月发送时,发送月数 为空 或为 0
if (($goodsCoupon->send_type == '0' || $goodsCoupon->send_type == '3') && empty($goodsCoupon->send_num)) {
continue;
}
//若添加项有多个一样的优惠劵这里做合并处理
$coupon = $goodsCoupon->coupon;
$coupon2 = [];
foreach ($coupon as $key => $item) {
if (isset($coupon2[$item['coupon_id']])) {
$coupon2[$item['coupon_id']]['coupon_several'] += $item['coupon_several'];
} else {
$coupon2[$item['coupon_id']] = $coupon[$key];
}
}
$coupon2 = array_merge($coupon2);
$this->doCouponLog($goodsCoupon,$goods->id,$goods->total, $coupon2);
}
}
public function promptlySendCoupon($goodsCoupon)
{
$coupon_ids = [];
foreach ($goodsCoupon->coupon as $key => $item) {
if ($item['coupon_several'] > 1) {
for ($i = 1; $i <= $item['coupon_several']; $i++) {
$coupon_ids[] = $item['coupon_id'];
}
} else {
$coupon_ids[] = $item['coupon_id'];
}
}
(new CouponSendService())->sendCouponsToMember($this->order->uid, $coupon_ids, 4, $this->order->order_sn);
}
public function everyMonthSendCoupon($goodsCoupon)
{
foreach ($goodsCoupon->coupon as $key => $item) {
if ($item['coupon_several'] > 1) {
for ($i = 1; $i <= $item['coupon_several']; $i++) {
$this->addSendCouponQueue($goodsCoupon, $item['coupon_id']);
}
} else {
$this->addSendCouponQueue($goodsCoupon, $item['coupon_id']);
}
}
}
/**
* @param $goodsCoupon
* @param $orderGoodsId
* @param $total
* 为了不多发少发,从源头控制锁定原因,定时发放
*/
public function doCouponLog($goodsCoupon, $orderGoodsId, $total, $coupon)
{
foreach ($coupon as $key => $item) {
$insertArr = [
'uniacid' => \YunShop::app()->uniacid,
'order_goods_id' => $orderGoodsId,
'coupon_id' => $item['coupon_id'],
'coupon_several' => bcmul($item['coupon_several'],$total),
'send_type' => $goodsCoupon->send_type,
'remark' => json_encode($goodsCoupon->coupon)
];
if($goodsCoupon->send_type == 0 || $goodsCoupon->send_type == 3){
$monthArr = [
'send_num' => $goodsCoupon->send_num,
'end_send_num' => 0,
];
$insertArr = array_merge($insertArr,$monthArr);
}
$model = new OrderGoodsCoupon();
$model->fill($insertArr);
$model->save();
}
}
public function addSendCouponQueue($goodsCoupon, $coupon_id)
{
$queueData = [
'uniacid' => \YunShop::app()->uniacid,
'goods_id' => $goodsCoupon->goods_id,
'uid' => $this->order->uid,
'coupon_id' => $coupon_id,
'send_num' => $goodsCoupon->send_num,
'end_send_num' => 0,
'status' => 0,
'created_at' => time(),
];
$this->dispatch((new addGoodsCouponQueueJob($queueData)));
}
}