Pārlūkot izejas kodu

add: 后台清仓和幸运活动

joe 4 gadi atpakaļ
vecāks
revīzija
af6805dfde

+ 1 - 0
app/models/store/StoreOrder.php

@@ -507,6 +507,7 @@ class StoreOrder extends BaseModel
         $bargain_id = $order['bargain_id'];
         $res5 = true;
         $cartInfo = StoreOrderCartInfo::where('cart_id', 'in', $order['cart_id'])->select();
+        $cartInfo = $cartInfo ? $cartInfo->toArray() : [];
         foreach ($cartInfo as $cart) {
             //增库存减销量
             if ($combinationId) $res5 = $res5 && StoreCombination::incCombinationStock($cart['cart_info']['cart_num'], $combinationId, isset($cart['cart_info']['productInfo']['attrInfo']) ? $cart['cart_info']['productInfo']['attrInfo']['unique'] : '');

+ 0 - 5
crmeb/services/async/ActivitiesCalc.php

@@ -1,5 +0,0 @@
-<?php
-
-abstract class ActivitiesCalc {
-
-}

+ 35 - 0
crmeb/services/async/ActivityCalc.php

@@ -0,0 +1,35 @@
+<?php
+
+use app\models\store\StoreOrderCartInfo;
+
+abstract class ActivityCalc {
+    protected $ctx = [];
+
+    public function __construct() {
+
+    }
+
+    /**
+     * @param $cate_id
+     * @return array
+     */
+    public static function getOrders($cate_id) {
+        $products = StoreOrderCartInfo::alias('ci')
+            ->join('store_order o', 'o.id=ci.oid')
+            ->join('store_product p', 'ci.product_id=p.id')
+            ->join('user u', 'u.uid = o.uid')
+            ->where('o.paid', 1)
+            ->where('o.status', '>=', 0)
+            ->where('o.refund_status', 0)
+            ->where('o.is_del', 0)
+            ->where('o.is_system_del', 0)
+            ->where('p.cart_id', $cate_id)
+            ->where('ci.activity', '')
+            ->field('o.id, o.pay_price, ci.product_id, ci.cart_info, u.uid, u.now_money, p.store_name')->select();
+        $products = $products ? $products->toArray() : [];
+        return $products;
+    }
+
+    abstract public function getId();
+    abstract public function getName();
+}

+ 4 - 17
crmeb/services/async/ClearanceCalc.php

@@ -9,6 +9,7 @@ use app\models\store\StoreOrderCartInfo;
 use crmeb\basic\BaseModel;
 use think\facade\Config;
 use think\facade\Log;
+use ActivityCalc;
 
 /**
  * 抢清仓活动
@@ -30,20 +31,7 @@ class ClearanceCalc {
     public function calc() {
         $clearance_cate_id = Config::get('activity.clearance_cate_id');
         // 找到清仓场次中未参加活动的订单
-        $products = StoreOrderCartInfo::alias('ci')
-            ->join('store_order o', 'o.id=ci.oid')
-            ->join('store_product p', 'ci.product_id=p.id')
-            ->join('user u', 'u.uid = o.uid')
-            ->where('o.paid', 1)
-            ->where('o.status', '>=', 0)
-            ->where('o.refund_status', 0)
-            ->where('o.is_del', 0)
-            ->where('o.is_system_del', 0)
-            ->where('p.cart_id', $clearance_cate_id)
-            ->where('ci.activity', '')
-            ->field('o.id, o.pay_price, ci.product_id, ci.cart_info, u.uid, u.now_money, p.store_name')->select();
-        $products = $products ? $products->toArray() : [];
-
+        $products = ActivityCalc::getOrders($clearance_cate_id);
         if (count($products) <= 1) {
             Log::info('not enough order, stop clearance activity');
             return;
@@ -61,7 +49,7 @@ class ClearanceCalc {
 
         // 标记有多件商品的订单
         $orders = [];
-        foreach($products as $p) {
+        foreach($products as &$p) {
             $counter += 1;
 
             $ci = json_decode($p['cart_info'], true);
@@ -115,7 +103,6 @@ class ClearanceCalc {
         }
 
         // 结果处置
-        $single = 0;
         foreach($winners as $p) {
             $single = $orders[$p['id']] == 1;
             $this->execute($p, $single, true);
@@ -173,7 +160,7 @@ class ClearanceCalc {
         BaseModel::checkTrans($ok);
 
         if ($ok) {
-            // 中奖用户发送中奖消息. TODO
+            // 中奖用户发送中奖消息.
             UserNotice::sendNoticeTo($product['uid'], '您的订单已退款',
                 '您好,由于活动商品库存有限,您的订单 ' . $product['store_name']
                 . ' 未能成功分配. 该商品付款' . $product['paid'] . '元已如数退还, 并赔付您' . $reparation

+ 173 - 0
crmeb/services/async/LuckyCalc.php

@@ -0,0 +1,173 @@
+<?php
+namespace crmeb\services\async;
+
+use app\admin\model\user\User;
+use app\admin\model\user\UserBill;
+use app\models\store\StoreOrder;
+use app\models\store\StoreOrderCartInfo;
+use app\models\user\UserNotice;
+use crmeb\basic\BaseModel;
+use think\facade\Config;
+use think\facade\Log;
+use ActivityCalc;
+
+class LuckyCalc {
+
+    protected static $NAME = 'lucky';
+
+    private function searchActiveInSuk($suk) {
+        $parts = explode(",", $suk);
+        if (count($parts) <= 0) {
+            return false;
+        }
+        foreach ($parts as $part) {
+            $t = trim($part);
+            if ($t == 20 || $t == 21) {
+                return $t;
+            }
+        }
+
+        return false;
+    }
+
+    public function calc() {
+        $lucky_cate_id = Config::get('activity.lucky_cate_id');
+        $products = ActivityCalc::getOrders($lucky_cate_id);
+
+        if (count($products) <= 1) {
+            Log::info('not enough order, stop lucky activity');
+            return;
+        }
+
+        // split win & lose
+        shuffle($products);
+        shuffle($products);
+
+        $left = [];
+        $right = [];
+        $left_spent = 0.0;
+        $right_spent = 0.0;
+
+        $orders = [];
+        foreach ($products as &$p) {
+            $ci = json_decode($p['cart_info'], true);
+            $num = $ci['num'];  // 购买个数
+            $productInfo = isset($ci['productInfo']) ? $ci['productInfo'] : [];
+            $attrInfo = isset($productInfo['attrInfo']) ? $productInfo['attrInfo'] : [];
+            $price = isset($attrInfo['price']) ? $attrInfo['price'] : 0.0;
+            $cost = isset($attrInfo['cost']) ? $attrInfo['cost'] : 0.0;
+            $ppaid = bcmul($num, $price, 2);// product paid
+            $pcost = bcmul($num, $cost, 2);
+            $oid = $p['id'];
+            $p['paid'] = $ppaid;
+            $p['cost'] = $pcost;
+
+            if (!isset($orders[$oid])) {
+                $orders[$oid] = 1;
+            } else {
+                $orders[$oid] += 1;
+            }
+            if ($ppaid <= 1.0) {
+                Log::warning("impossible price, order: ". $p['id']);
+                continue;
+            }
+            if ($cost <= 0.1) {
+                Log::warning("impossible cost, order: ". $p['id']);
+                continue;
+            }
+            $suk = isset($attrInfo['suk']) ? $attrInfo['suk'] : 'any';
+            $flag = $this->searchActiveInSuk($suk);
+
+            if ($flag == 20) {
+                $left[] = $p;
+                $left_spent = bcadd($left_spent, $ppaid, 2);
+            } else if ($flag == 21) {
+                $right[] = $p;
+                $right_spent = bcadd($right_spent, $ppaid, 2);
+            } else {
+                Log::error('cant find suk in lucky field. id=' . $oid);
+                continue;
+            }
+        }// foreach
+
+        $products = [];
+
+        $diff_money = bcsub($left_spent, $right_spent, 2);
+        if ($diff_money < 0.0) {
+            $diff_money = -$diff_money;
+        }
+        $open = 20;
+        $winners = $left;
+        $losers = $right;
+        if ($left_spent > $right_spent) {
+            $open = 21;
+            $winners = $right;
+            $losers = $left;
+        }
+
+        // 结果处置
+        foreach($winners as $p) {
+            $single = $orders[$p['id']] == 1;
+            $this->execute($p, $single, true);
+        }
+        foreach($losers as $p) {
+            $single = $orders[$p['id']] == 1;
+            $this->execute($p, $single, false);
+        }
+    } // calc
+
+    /**
+     * 奖励分配
+     *
+     * @param $product  获奖订单中的商品
+     * @param bool $single  是否是单种商品构成的订单
+     * @param bool $win 是否中奖
+     */
+    protected function execute($product, $single=true, $win=true) {
+        BaseModel::beginTrans();
+        $result = 0;
+        $reparation = 0.0;
+        if ($win) {
+            $result = 1;
+            $reparation = bcmul(bcsub($product['paid'], $product['cost'], 2), 0.1, 2);
+        }
+        // 标记商品为已参与活动
+        $r1 = StoreOrderCartInfo::where('oid', $product['id'])
+            ->where('product_id', $product['product_id'])
+            ->update([
+                'activity' => self::$NAME,
+                'result' => $result,
+                'reparation' => $reparation,
+            ]);
+
+        if (!$win) {
+            return;
+        }
+
+        $refund_price = bcadd($product['paid'], $reparation, 2);
+        // 订单全部商品都中奖的退单
+        $r2 = true;
+        if ($single) {
+            $r2 = StoreOrder::where('id', $product['id'])->update([
+                'refund_price' => $refund_price,
+                'refund_status' => 2,
+            ]);
+        }
+        // 中奖的 退款并赔款返回到佣金
+        $r3 = UserBill::income('參加活动', $product['uid'], 'now_money', 'brokerage',
+            $refund_price, $product['id'], bcadd($product['now_money'], $refund_price, 2),
+            '订单退款' . $product['paid'] . '+' . $reparation . '元');
+        $r4 = User::bcInc($product['uid'], 'brokerage_price', $refund_price, 'uid');
+
+        $ok = $r1 && $r2 && $r3 && $r4;
+        BaseModel::checkTrans($ok);
+
+        if ($ok) {
+            // 中奖用户发送中奖消息.
+            UserNotice::sendNoticeTo($product['uid'], '您的订单已退款',
+                '您好,由于活动商品库存有限,您的订单 ' . $product['store_name']
+                . ' 未能成功分配. 该商品付款' . $product['paid'] . '元已如数退还, 并赔付您' . $reparation
+                . '元作为补偿, 对您造成的不便我们深感抱歉. 同时感谢您对美天旺的喜爱和信任, 美天旺活动场将永远为您守候. 顺祝生活愉快.');
+        }
+    }
+}