IntegralAppreciationPoolSub.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. <?php
  2. /**
  3. * 重庆赤晓店信息科技有限公司
  4. * https://www.chixiaodian.com
  5. * Copyright (c) 2023 赤店商城 All rights reserved.
  6. */
  7. namespace app\models;
  8. use yii\db\ActiveRecord;
  9. use yii\behaviors\TimestampBehavior;
  10. /**
  11. * This is the model class for table "{{%integral_appreciation_pool_sub}}".
  12. *
  13. * @property integer $id
  14. * @property integer $store_id
  15. * @property integer $user_id
  16. * @property integer $order_id
  17. * @property float $amount
  18. * @property float $integral_price
  19. * @property float $after_integral_price
  20. * @property float $integral
  21. * @property integer $is_send_integral
  22. * @property integer $reflux_type
  23. * @property string $created_at
  24. * @property string $updated_at
  25. */
  26. class IntegralAppreciationPoolSub extends \yii\db\ActiveRecord
  27. {
  28. const REFLUX_TYPE_ORDER = 0;
  29. const REFLUX_TYPE_WITHDRAW = 1;
  30. public static $reflux_type_text = [
  31. self::REFLUX_TYPE_ORDER => '订单',
  32. self::REFLUX_TYPE_WITHDRAW => '提现',
  33. ];
  34. const IS_SEND_TRUE = 1;
  35. const IS_SEND_FALSE = 0;
  36. /**
  37. * {@inheritdoc}
  38. */
  39. public static function tableName()
  40. {
  41. return '{{%integral_appreciation_pool_sub}}';
  42. }
  43. public function behaviors()
  44. {
  45. return [
  46. [
  47. 'class' => TimestampBehavior::class
  48. ]
  49. ];
  50. }
  51. /**
  52. * {@inheritdoc}
  53. */
  54. public function rules()
  55. {
  56. return [
  57. [['id', 'store_id', 'user_id', 'order_id', 'reflux_type', 'is_send_integral'], 'integer'],
  58. [['amount', 'integral_price', 'integral', 'after_integral_price', 'created_at', 'updated_at'], 'number']
  59. ];
  60. }
  61. /**
  62. * {@inheritdoc}
  63. */
  64. public function attributeLabels()
  65. {
  66. return [
  67. 'id' => '',
  68. 'store_id' => '店铺ID',
  69. 'user_id' => '用户ID',
  70. 'order_id' => '用户订单ID/提现ID',
  71. 'amount' => '贡献底池金额',
  72. 'integral_price' => '当前积分价格',
  73. 'after_integral_price' => '当前积分价格',
  74. 'integral' => '可得的积分数量',
  75. 'is_send_integral' => '订单回流类型下是否给用户发放完积分',
  76. 'reflux_type' => '回流类型:0=订单;1=提现',
  77. 'created_at' => '',
  78. 'updated_at' => '',
  79. ];
  80. }
  81. //计算积分金额 积分价格 添加奖金池
  82. /**
  83. * 设置发放活动积分
  84. * 订单情况流程:假设A在商城中下单购买商品 该商品中设置的活动金额为30元 将30元根据后台设置的奖金池铸造积分百分比拿出来铸造积分 假设设置的70%
  85. * 那可铸造出21积分 再获取奖金池中的积分价格(没有的话 就获取后台设置的初始积分价格)假设价格是1 那么 获取到用户实际可得的积分数量为21 / 1 = 21
  86. * 此时积分价格就变成了30 / 21 = 1.43元/积分
  87. * 假设有用户下单也是30元商品 那就还是铸造出21积分 积分价格为1.43元/积分 那么当前用户可获得的积分数量为21 / 1.43 = 14.68个积分数量
  88. * 此时积分价格就变成了(30 + 30) / (21 + 14.68) = 1.68元/积分
  89. * ...
  90. **/
  91. public static function setPool($order_id, $store_id, $reflux_type = self::REFLUX_TYPE_ORDER) {
  92. $transaction = \Yii::$app->db->beginTransaction();
  93. try {
  94. $integral_appreciation_setting = Option::get('integral_appreciation_setting', $store_id, 'integral_appreciation')['value'];
  95. $integral_appreciation_setting = json_decode($integral_appreciation_setting ?? '', true);
  96. //如果是订单
  97. if (intval($reflux_type) === self::REFLUX_TYPE_ORDER) {
  98. $order = Order::findOne($order_id);
  99. if (!$order) {
  100. throw new \Exception('订单不存在');
  101. }
  102. if (!intval($order->is_sale)) {
  103. throw new \Exception('订单未过售后期');
  104. }
  105. $is_repeat = self::findOne(['order_id' => $order_id, 'reflux_type' => self::REFLUX_TYPE_ORDER]);
  106. if ($is_repeat) {
  107. throw new \Exception('订单已参与过');
  108. }
  109. $order_goods = OrderDetail::find()->where(['order_id' => $order_id])->select('goods_id, num')
  110. ->asArray()->all();
  111. $integral_goods_amount = 0;
  112. foreach ($order_goods as $order_goods_item) {
  113. //计算订单中可为奖金池底池增加多少金额
  114. $integral_goods_amount += IntegralAppreciationGoods::find()->where(['store_id' => $order->store_id, 'is_delete' => 0])
  115. ->andWhere(['goods_id' => $order_goods_item['goods_id']])->sum('reflux_amount') ?: 0;
  116. $integral_goods_amount = bcmul($integral_goods_amount, $order_goods_item['num'], 2);
  117. }
  118. if ($integral_goods_amount <= 0) {
  119. throw new \Exception('当前订单未产生奖金池金额order_no=' . $order->order_no);
  120. }
  121. //计算当前订单可铸造多少积分
  122. $integral_amount_to_integral_profit = $integral_appreciation_setting['integral_amount_to_integral_profit'] ?: 0;
  123. //计算出积分数量
  124. $integral_num = round(($integral_goods_amount * $integral_amount_to_integral_profit) / 100, 2);
  125. //获取当前奖金池中的积分价格
  126. $integral_price = 0;
  127. $pool = IntegralAppreciationPool::findOne(['store_id' => $order->store_id]);
  128. if ($pool) {
  129. $integral_price = $pool->integral_price;
  130. } else {
  131. $pool = new IntegralAppreciationPool();
  132. $pool->store_id = $store_id;
  133. //方便计算积分价格趋势 给个默认值
  134. $model = new self();
  135. $model->store_id = $store_id;
  136. $model->user_id = 0;
  137. $model->order_id = 0;
  138. $model->amount = 0;
  139. $model->integral_price = 0;
  140. $model->integral = 0;
  141. $model->is_send_integral = self::IS_SEND_TRUE;
  142. $model->reflux_type = self::REFLUX_TYPE_ORDER;
  143. $model->after_integral_price = $integral_appreciation_setting['integral_init_price'] ?: 0;
  144. if (!$model->save()) {
  145. throw new \Exception(json_encode($model->errors, JSON_UNESCAPED_UNICODE));
  146. }
  147. }
  148. //如果没有获取到积分价格 就使用设置项中的积分初始价格
  149. if ($integral_price <= 0) {
  150. $integral_price = $integral_appreciation_setting['integral_init_price'] ?: 0;
  151. }
  152. if ($integral_price <= 0) {
  153. throw new \Exception('当前活动未设置积分初始价格' );
  154. }
  155. //计算用户可获得的积分数量
  156. $user_integral_num = round($integral_num / $integral_price, 2);
  157. //写入数据
  158. //.....
  159. //计算积分价格 写入到奖金池表
  160. //积分价格计算方式:奖金池总额 / 所有用户当前拥有的积分数量 (todo 修改积分价格计算方式:奖金池总额/积分池总积分)
  161. $user_total_integral = IntegralAppreciationUser::find()->where(['store_id' => $store_id])->sum('integral') ?: 0;
  162. $user_total_integral = bcadd($user_total_integral, $user_integral_num, 2);
  163. $amount = $pool->amount ?: 0;
  164. $pool->amount = bcadd($amount, $integral_goods_amount, 2);
  165. $pool->total_integral = bcadd($pool->total_integral, $user_integral_num, 2);
  166. $pool->integral_price = $pool->total_integral > 0 ? round($pool->amount / $pool->total_integral, 2) : 0;
  167. $pool->total_user_integral = $user_total_integral;
  168. $pool->save();
  169. $model = new self();
  170. $model->store_id = $store_id;
  171. $model->user_id = $order->user_id;
  172. $model->order_id = $order->id;
  173. $model->amount = $integral_goods_amount;
  174. $model->integral_price = $integral_price;
  175. $model->integral = $user_integral_num;
  176. $model->is_send_integral = self::IS_SEND_TRUE;
  177. $model->reflux_type = self::REFLUX_TYPE_ORDER;
  178. $model->after_integral_price = $pool->integral_price;
  179. if (!$model->save()) {
  180. throw new \Exception(json_encode($model->errors, JSON_UNESCAPED_UNICODE));
  181. }
  182. //发放积分
  183. $integral_appreciation_user = IntegralAppreciationUser::findOne(['user_id' => $order->user_id]);
  184. if (!$integral_appreciation_user) {
  185. $integral_appreciation_user = new IntegralAppreciationUser();
  186. $integral_appreciation_user->user_id = $order->user_id;
  187. $integral_appreciation_user->store_id = $store_id;
  188. }
  189. $integral_appreciation_user->total_integral = bcadd($integral_appreciation_user->total_integral, $user_integral_num, 2);
  190. $integral_appreciation_user->integral = bcadd($integral_appreciation_user->integral, $user_integral_num, 2);
  191. if (!$integral_appreciation_user->save()) {
  192. throw new \Exception(json_encode($integral_appreciation_user->errors, JSON_UNESCAPED_UNICODE));
  193. };
  194. $result = IntegralAppreciationUserIntegralLog::saveIntegralLog(
  195. $integral_appreciation_user->id,
  196. $user_integral_num,
  197. IntegralAppreciationUserIntegralLog::TYPE_INCOME,
  198. IntegralAppreciationUserIntegralLog::SOURCE_TYPE_CAST_INTEGRAL,
  199. "订单{$order->order_no}过售后期铸造积分",
  200. $order_id
  201. );
  202. if ($result['code']) {
  203. throw new \Exception('操作失败');
  204. }
  205. } else {
  206. $cash = Cash::findOne(['id' => $order_id, 'store_id' => $store_id]);
  207. if (!$cash) {
  208. throw new \Exception('提现记录不存在');
  209. }
  210. if (intval($cash->cash_type) !== Cash::IS_CASH_TYPE_INTEGRAL_APPRECIATION) {
  211. throw new \Exception('非增值积分提现');
  212. }
  213. if (!in_array(intval($cash->status), [$cash::STATUS_GIVEN, $cash::STATUS_HAND])) {
  214. throw new \Exception('提现未通过');
  215. }
  216. $integral_cash_log = IntegralAppreciationCashLog::findOne(['cash_id' => $cash->id]);
  217. if (!$integral_cash_log) {
  218. throw new \Exception('未找到增值积分提现');
  219. }
  220. $integral_price = 0;
  221. $pool = IntegralAppreciationPool::findOne(['store_id' => $store_id]);
  222. if ($pool) {
  223. $integral_price = $pool->integral_price;
  224. } else {
  225. $pool = new IntegralAppreciationPool();
  226. $pool->store_id = $store_id;
  227. //方便计算积分价格趋势 给个默认值
  228. $model = new self();
  229. $model->store_id = $store_id;
  230. $model->user_id = 0;
  231. $model->order_id = 0;
  232. $model->amount = 0;
  233. $model->integral_price = 0;
  234. $model->integral = 0;
  235. $model->is_send_integral = self::IS_SEND_TRUE;
  236. $model->reflux_type = self::REFLUX_TYPE_WITHDRAW;
  237. $model->after_integral_price = $integral_appreciation_setting['integral_init_price'] ?: 0;
  238. if (!$model->save()) {
  239. throw new \Exception(json_encode($model->errors, JSON_UNESCAPED_UNICODE));
  240. }
  241. }
  242. //如果没有获取到积分价格 就使用设置项中的积分初始价格
  243. if ($integral_price <= 0) {
  244. $integral_price = $integral_appreciation_setting['integral_init_price'] ?: 0;
  245. }
  246. //积分价格计算方式:奖金池总额 / 所有用户当前拥有的积分数量
  247. // $user_total_integral = IntegralAppreciationUser::find()->where(['store_id' => $store_id])->sum('integral') ?: 0;
  248. $amount = $pool->amount ?: 0;
  249. $pool->amount = bcadd($amount, $integral_cash_log->reflux_price, 2);
  250. $pool->total_integral = bcadd($pool->total_integral, 0, 2);
  251. $pool->total_user_integral = bcadd($pool->total_user_integral, 0, 2);
  252. $pool->integral_price = $pool->total_integral > 0 ? round($pool->amount / $pool->total_integral, 2) : 0;
  253. if (!$pool->save()) {
  254. throw new \Exception(json_encode($pool->errors, JSON_UNESCAPED_UNICODE));
  255. };
  256. $model = new self();
  257. $model->store_id = $store_id;
  258. $model->user_id = $cash->user_id;
  259. $model->order_id = $cash->id;
  260. $model->amount = $integral_cash_log->reflux_price;
  261. $model->integral_price = $integral_price;
  262. $model->integral = 0;
  263. $model->is_send_integral = self::IS_SEND_TRUE;
  264. $model->reflux_type = self::REFLUX_TYPE_WITHDRAW;
  265. $model->after_integral_price = $pool->integral_price;
  266. if (!$model->save()) {
  267. throw new \Exception(json_encode($model->errors, JSON_UNESCAPED_UNICODE));
  268. }
  269. }
  270. $transaction->commit();
  271. return [
  272. 'code' => 0,
  273. 'msg' => '操作成功'
  274. ];
  275. } catch (\Exception $e) {
  276. $transaction->rollBack();
  277. return [
  278. 'code' => 1,
  279. 'msg' => $e->getMessage()
  280. ];
  281. }
  282. }
  283. }