文件
Henglianshutong/addons/shopro/service/partner/PartnerRewardService.php

260 行
9.1 KiB
PHP

<?php
namespace addons\shopro\service\partner;
use think\Db;
use addons\shopro\service\Wallet;
use app\admin\model\shopro\partner\Reward as RewardModel;
use app\admin\model\shopro\order\Order as OrderModel;
use app\admin\model\shopro\commission\CommissionGoods;
use app\admin\model\shopro\commission\Agent as AgentModel;
/**
* 订单即时奖入口 + 退款回滚
*/
class PartnerRewardService
{
public function settleOrder($orderId)
{
if (!PartnerConfig::isEnabled()) {
return false;
}
return Db::transaction(function () use ($orderId) {
$order = OrderModel::with(['items'])->where('id', $orderId)->lock(true)->find();
if (!$order) {
return false;
}
if (!$this->isQualified($order)) {
return false;
}
$exists = RewardModel::where('order_id', $orderId)->where('order_id', '>', 0)->find();
if ($exists) {
return true;
}
$buyerId = intval($order['user_id']);
$active = new ActiveService();
$chainService = new ChainService();
$parentChain = $chainService->collect($buyerId, false);
$selfChain = $chainService->collect($buyerId, true);
$parent = $parentChain[0] ?? null;
(new Push3Reward())->run($order, $buyerId, $parent, $active);
$diff = (new MakerDiffReward())->run($order, $buyerId, $parentChain, $active);
(new MakerPeerReward())->run($order, $buyerId, $parentChain, $diff, $active);
$team = (new TeamSplitReward())->run($order, $buyerId, $selfChain, $active);
(new PeerShareReward())->run($order, $buyerId, $selfChain, $team, $active);
(new VoucherService())->grant($order, $buyerId);
return true;
});
}
public function refund($orderId)
{
return Db::transaction(function () use ($orderId) {
$rewards = RewardModel::where('order_id', $orderId)
->where('order_id', '>', 0)
->where('status', 1)
->whereIn('reward_type', array_merge(PartnerConfig::instantTypes(), ['voucher_grant']))
->lock(true)
->select();
$order = OrderModel::where('id', $orderId)->find();
if ($order) {
(new VoucherService())->refundConsume($order);
}
if (!$rewards || count($rewards) == 0) {
(new VoucherService())->closeByOrder($orderId);
return true;
}
foreach ($rewards as $reward) {
if (in_array($reward->reward_type, PartnerConfig::instantTypes()) && (float) $reward->amount > 0 && $reward->user_id > 0) {
Wallet::change($reward->user_id, 'commission', -$reward->amount, 'reward_back', [
'partner_reward_id' => $reward->id,
'order_id' => $orderId,
], '合伙股东收益退回');
AgentModel::where('user_id', $reward->user_id)->setDec('total_income', $reward->amount);
}
if ($reward->reward_type === 'push3' && $reward->user_id > 0) {
(new Push3Reward())->rollbackSeq($reward->user_id);
}
$reward->status = -2;
$reward->save();
}
(new VoucherService())->closeByOrder($orderId);
return true;
});
}
/**
* 部分退款处理:仅等比缩减兑换券额度,不全额撤销分销商奖励
*/
public function refundPartial($order, $item)
{
return Db::transaction(function () use ($order, $item) {
$orderId = intval(is_array($order) ? ($order['id'] ?? 0) : ($order->id ?? 0));
$itemPayFee = floatval(is_array($item) ? ($item['pay_fee'] ?? 0) : ($item->pay_fee ?? 0));
$voucherService = new VoucherService();
if ($itemPayFee > 0) {
$voucherService->reduceByRefund($orderId, $itemPayFee);
}
PartnerRewardService::write([
'order_id' => $orderId,
'buyer_id' => intval($order['user_id'] ?? 0),
'user_id' => intval($order['user_id'] ?? 0),
'role' => 'taster',
'reward_type' => 'voucher_grant',
'amount' => 0,
'base_amount' => $itemPayFee,
'ext' => [
'formula' => "子商品退款 {$itemPayFee},缩减兑换券总额",
'item_id' => $item['id'] ?? 0,
'partial_refund' => 1
],
'status' => -2,
]);
return true;
});
}
public function isQualified($order)
{
if (!$order || ($order['type'] ?? '') === 'score') {
return false;
}
if ((float) ($order['pay_fee'] ?? 0) <= 0) {
return false;
}
$status = $order['status'] ?? '';
if (!in_array($status, [OrderModel::STATUS_PAID, OrderModel::STATUS_COMPLETED])) {
return false;
}
$items = $order['items'] ?? [];
if (empty($items) && !empty($order['id'])) {
$fresh = OrderModel::with(['items'])->where('id', $order['id'])->find();
if ($fresh) {
$order = $fresh;
$items = $fresh['items'] ?? [];
}
}
foreach ($items as $item) {
if (isset($item['ext']['is_commission']) && !$item['ext']['is_commission']) {
continue;
}
$goods = CommissionGoods::where('goods_id', $item['goods_id'])
->where('status', CommissionGoods::GOODS_COMMISSION_STATUS_ON)
->find();
if ($goods) {
return true;
}
}
return false;
}
public function touchSelfOrder($userId, $time = null)
{
$agent = AgentModel::where('user_id', $userId)->find();
if ($agent) {
$agent->last_self_order_time = $time ?: time();
$agent->save();
}
}
public static function dailyOrderId($settleDate)
{
return -intval(date('Ymd', strtotime($settleDate)));
}
public static $lastWriteCreated = false;
public static function write($data)
{
self::$lastWriteCreated = false;
$now = time();
$payload = array_merge([
'order_id' => 0,
'buyer_id' => 0,
'user_id' => 0,
'role' => '',
'reward_type' => '',
'amount' => 0,
'madow' => 0,
'base_amount' => 0,
'rate' => 0,
'ext' => [],
'settle_date' => null,
'status' => 0,
'createtime' => $now,
'updatetime' => $now,
], $data);
try {
$row = RewardModel::create($payload);
self::$lastWriteCreated = true;
return $row;
} catch (\Exception $e) {
$msg = $e->getMessage();
if (stripos($msg, 'Duplicate') !== false || stripos($msg, '1062') !== false) {
return RewardModel::where('order_id', $payload['order_id'])
->where('user_id', $payload['user_id'])
->where('reward_type', $payload['reward_type'])
->find();
}
throw $e;
}
}
public static function writeSkip($order, $buyerId, $userId, $type, $role, $reason, $formula = '')
{
$orderId = is_array($order) || $order instanceof \think\Model ? ($order['id'] ?? 0) : intval($order);
return self::write([
'order_id' => $orderId,
'buyer_id' => $buyerId,
'user_id' => $userId,
'role' => $role,
'reward_type' => $type,
'amount' => 0,
'base_amount' => 0,
'ext' => [
'skip_reason' => $reason,
'formula' => $formula ?: PartnerConfig::skipReasonText($reason),
],
'status' => -1,
]);
}
public static function account($order, $buyerId, $userId, $type, $role, $amount, $base, $ext = [])
{
$orderId = is_array($order) || $order instanceof \think\Model ? ($order['id'] ?? 0) : intval($order);
$row = self::write([
'order_id' => $orderId,
'buyer_id' => $buyerId,
'user_id' => $userId,
'role' => $role,
'reward_type' => $type,
'amount' => $amount,
'base_amount' => $base,
'ext' => $ext,
'status' => 1,
]);
if ($row && self::$lastWriteCreated && (float) $amount > 0 && $userId > 0 && $row->status == 1 && in_array($type, PartnerConfig::instantTypes())) {
Wallet::change($userId, 'commission', $amount, $type, [
'partner_reward_id' => $row->id,
'order_id' => $orderId,
]);
AgentModel::where('user_id', $userId)->setInc('total_income', $amount);
}
return $row;
}
}