CashExt.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. <?php
  2. /**
  3. * 重庆赤晓店信息科技有限公司
  4. * https://www.chixiaodian.com
  5. * Copyright (c) 2023 赤店商城 All rights reserved.
  6. */
  7. namespace app\models;
  8. use app\constants\OptionSetting;
  9. use Yii;
  10. use yii\db\ActiveRecord;
  11. use yii\behaviors\TimestampBehavior;
  12. /**
  13. * This is the model class for table "{{%cash_ext}}".
  14. *
  15. * @property integer $id
  16. * @property integer $cash_id
  17. * @property integer $cash_price_type
  18. * @property float $price
  19. * @property integer $is_pay
  20. * @property float $service_charge
  21. * @property float $real_price
  22. * @property integer $created_at
  23. * @property integer $updated_at
  24. */
  25. class CashExt extends \yii\db\ActiveRecord
  26. {
  27. const CASH_PRICE_TYPE_AMOUNT = 1;
  28. const CASH_PRICE_TYPE_INTEGRAL = 2;
  29. const CASH_PRICE_TYPE_BALANCE = 3;
  30. const CASH_TYPE_SHARE = 'share';
  31. const CASH_TYPE_SHARE_HOLDER = 'shareHolder';
  32. const CASH_TYPE_AREA_DIVIDEND = 'areaDividend';
  33. const CASH_TYPE_TEAM_BONUS = 'teamBonus';
  34. const CASH_TYPE_SHARE_GROUP = 'shareGroup';
  35. const CASH_TYPE_SUPER_SALES = 'superSales';
  36. const CASH_TYPE_INTEGRAL_APPRECIATION = 'integralAppreciation';
  37. const CASH_TYPE_LOCAL_PUBLIC_RANKING = 'localPublicRanking';
  38. const CASH_TYPE_ARR = [
  39. self::CASH_TYPE_SHARE,
  40. self::CASH_TYPE_SHARE_HOLDER,
  41. self::CASH_TYPE_AREA_DIVIDEND,
  42. self::CASH_TYPE_TEAM_BONUS,
  43. self::CASH_TYPE_SHARE_GROUP,
  44. self::CASH_TYPE_SUPER_SALES,
  45. self::CASH_TYPE_INTEGRAL_APPRECIATION,
  46. self::CASH_TYPE_LOCAL_PUBLIC_RANKING
  47. ];
  48. public static $cashPriceTypeMap = [
  49. self::CASH_PRICE_TYPE_AMOUNT => '现金',
  50. self::CASH_PRICE_TYPE_INTEGRAL => '积分',
  51. self::CASH_PRICE_TYPE_BALANCE => '余额'
  52. ];
  53. /**
  54. * {@inheritdoc}
  55. */
  56. public static function tableName()
  57. {
  58. return '{{%cash_ext}}';
  59. }
  60. public function behaviors()
  61. {
  62. return [
  63. [
  64. 'class' => TimestampBehavior::class,
  65. 'attributes' => [
  66. ActiveRecord::EVENT_BEFORE_INSERT => ['created_at'],
  67. ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at']
  68. ]
  69. ]
  70. ];
  71. }
  72. /**
  73. * {@inheritdoc}
  74. */
  75. public function rules()
  76. {
  77. return [
  78. [['id', 'cash_id', 'cash_price_type', 'is_pay', 'created_at', 'updated_at'], 'integer'],
  79. [['price', 'service_charge', 'real_price'], 'number']
  80. ];
  81. }
  82. /**
  83. * {@inheritdoc}
  84. */
  85. public function attributeLabels()
  86. {
  87. return [
  88. 'id' => '',
  89. 'cash_id' => '提现ID',
  90. 'cash_price_type' => '提现金额类型:1现金;2积分;3余额',
  91. 'price' => '提现金额',
  92. 'is_pay' => '是否打款',
  93. 'service_charge' => '手续费',
  94. 'real_price' => '实际打款金额',
  95. 'created_at' => '创建时间',
  96. 'updated_at' => '',
  97. ];
  98. }
  99. /**
  100. * 提现前计算各项提现金额
  101. * @param $type
  102. * @param $store_id
  103. * @param $cash_price
  104. * @return array
  105. */
  106. public static function cashFront($type, $store_id, $cash_price,$cashType = 0) {
  107. try {
  108. $cash_price_type = '';
  109. $cash_price_amount = 0;
  110. $cash_price_integral = 0;
  111. $cash_price_balance = 0;
  112. $cash_service_charge = 0;
  113. if ($type == self::CASH_TYPE_SHARE) {
  114. $share_basic_setting = Option::get(OptionSetting::SHARE_BASIC_SETTING, $store_id, OptionSetting::SHARE_GROUP_NAME)['value'];
  115. $share_basic_setting = json_decode($share_basic_setting ?: '', true);
  116. $cash_price_type = $share_basic_setting['cash_price_type']['value'] ?? '1';
  117. $cash_price_amount = $share_basic_setting['cash_price_amount']['value'] ?? 100;
  118. $cash_price_integral = $share_basic_setting['cash_price_integral']['value'] ?? 0;
  119. $cash_price_balance = $share_basic_setting['cash_price_balance']['value'] ?? 0;
  120. $cash_service_charge = $share_basic_setting['cash_service_charge']['value'] ?? 0;
  121. }
  122. if ($type == self::CASH_TYPE_SHARE_HOLDER) {
  123. $cash_price_type = Option::get('cash_price_type', $store_id, 'bonus_pool', '1')['value'];
  124. $cash_price_amount = Option::get('cash_price_amount', $store_id, 'bonus_pool', 100)['value'];
  125. $cash_price_integral = Option::get('cash_price_integral', $store_id, 'bonus_pool', 0)['value'];
  126. $cash_price_balance = Option::get('cash_price_balance', $store_id, 'bonus_pool', 0)['value'];
  127. $cash_service_charge = Option::get('shareHolderCashProfit', $store_id, 'bonus_pool', 0)['value'];
  128. }
  129. if ($type == self::CASH_TYPE_AREA_DIVIDEND) {
  130. $cash_price_type = Option::get('cash_price_type', $store_id, 'bonus_pool_area_agent', '1')['value'];
  131. $cash_price_amount = Option::get('cash_price_amount', $store_id, 'bonus_pool_area_agent', 100)['value'];
  132. $cash_price_integral = Option::get('cash_price_integral', $store_id, 'bonus_pool_area_agent', 0)['value'];
  133. $cash_price_balance = Option::get('cash_price_balance', $store_id, 'bonus_pool_area_agent', 0)['value'];
  134. $cash_service_charge = Option::get('shareHolderCashProfit', $store_id, 'bonus_pool_area_agent', 0)['value'];
  135. }
  136. if ($type == self::CASH_TYPE_TEAM_BONUS) {
  137. $teamBonus = Option::get(OptionSetting::TEAM_BONUS_SETTING, $store_id, 'store')['value'];
  138. $teamBonus = json_decode($teamBonus ?: '', true);
  139. $cash_price_type = $teamBonus['cash_price_type'] ?? '1';
  140. $cash_price_amount = $teamBonus['cash_price_amount'] ?? 100;
  141. $cash_price_integral = $teamBonus['cash_price_integral'] ?? 0;
  142. $cash_price_balance = $teamBonus['cash_price_balance'] ?? 0;
  143. $cash_service_charge = $setting['cash_rate'] ?? 0;
  144. }
  145. if ($type == self::CASH_TYPE_SHARE_GROUP) {
  146. $share_group_setting = Option::get('share_group_setting', $store_id, 'share_group')['value'];
  147. $share_group_setting = json_decode($share_group_setting ?: '', true);
  148. $cash_price_type = $share_group_setting['cash_price_type'] ?? '1';
  149. $cash_price_amount = $share_group_setting['cash_price_amount'] ?? 100;
  150. $cash_price_integral = $share_group_setting['cash_price_integral'] ?? 0;
  151. $cash_price_balance = $share_group_setting['cash_price_balance'] ?? 0;
  152. $cash_service_charge = $share_group_setting['cash_service_charge'] ?? 0;
  153. }
  154. if ($type == self::CASH_TYPE_SUPER_SALES) {
  155. $share_group_setting = Option::get('super_sales_setting', $store_id, 'super_sales')['value'];
  156. $share_group_setting = json_decode($share_group_setting ?: '', true);
  157. $cash_price_type = $share_group_setting['cash_price_type'] ?? '1';
  158. $cash_price_amount = $share_group_setting['cash_price_amount'] ?? 100;
  159. $cash_price_integral = $share_group_setting['cash_price_integral'] ?? 0;
  160. $cash_price_balance = $share_group_setting['cash_price_balance'] ?? 0;
  161. $cash_service_charge = $share_group_setting['cash_service_charge'] ?? 0;
  162. }
  163. if ($type == self::CASH_TYPE_INTEGRAL_APPRECIATION) {
  164. $integral_appreciation_setting = Option::get('integral_appreciation_setting', $store_id, 'integral_appreciation')['value'];
  165. $integral_appreciation_setting = json_decode($integral_appreciation_setting ?: '', true);
  166. $cash_price_type = $integral_appreciation_setting['cash_price_type'] ?? '1';
  167. $cash_price_amount = $integral_appreciation_setting['cash_price_amount'] ?? 100;
  168. $cash_price_integral = $integral_appreciation_setting['cash_price_integral'] ?? 0;
  169. $cash_price_balance = $integral_appreciation_setting['cash_price_balance'] ?? 0;
  170. $cash_service_charge = $integral_appreciation_setting['cash_service_charge'] ?? 0;
  171. }
  172. $cash = Option::get(OptionSetting::CASH_SETTING, get_store_id(), 'store')['value'];
  173. if ($cash) {
  174. $res = json_decode($cash, true);
  175. $cash_price_type = $res['cash_price_type'] ?? '1';
  176. $cash_price_amount = $res['cash_price_amount'] ?? 100;
  177. $cash_price_integral = $res['cash_price_integral'] ?? 0;
  178. $cash_price_balance = $res['cash_price_balance'] ?? 0;
  179. $cash_service_charge = $res['cash_service_charge'] ?? 0;
  180. }
  181. if($cashType == Cash::TYPE_RECHARGE){
  182. $cash_service_charge = 0;
  183. }
  184. $amount_price = 0;
  185. $integral_price = 0;
  186. $balance_price = 0;
  187. $real_amount_price = 0;
  188. $real_integral_price = 0;
  189. $real_balance_price = 0;
  190. $real_cash_price = bcsub($cash_price, bcdiv(bcmul($cash_price, $cash_service_charge, 2), 100, 2), 2);//实际可提现金额
  191. $total_profit = 0;
  192. $cash_price_type = explode(',', $cash_price_type);
  193. if (in_array(self::CASH_PRICE_TYPE_AMOUNT, $cash_price_type)) {
  194. $total_profit = bcadd($total_profit, $cash_price_amount, 2);
  195. $amount_price = bcdiv(bcmul($cash_price, $cash_price_amount, 2), 100, 2);
  196. $real_amount_price = bcdiv(bcmul($real_cash_price, $cash_price_amount, 2), 100, 2);//99.4 * 1
  197. }
  198. if (in_array(self::CASH_PRICE_TYPE_INTEGRAL, $cash_price_type)) {
  199. $total_profit = bcadd($total_profit, $cash_price_integral, 2);
  200. $integral_price = bcdiv(bcmul($cash_price, $cash_price_integral, 2), 100, 2);
  201. //兼容计算精度问题
  202. if ($cash_price_balance <= 0 || !in_array(self::CASH_PRICE_TYPE_BALANCE, $cash_price_type)) {
  203. $real_integral_price = bcsub($real_cash_price, $real_amount_price, 2);
  204. } else {
  205. $real_integral_price = bcdiv(bcmul($real_cash_price, $cash_price_integral, 2), 100, 2);
  206. }
  207. }
  208. if (in_array(self::CASH_PRICE_TYPE_BALANCE, $cash_price_type)) {
  209. $total_profit = bcadd($total_profit, $cash_price_balance, 2);
  210. $balance_price = bcdiv(bcmul($cash_price, $cash_price_balance, 2), 100, 2);
  211. // $real_balance_price = bcmul($cash_price_service, bcdiv($cash_price_balance, 100, 2), 2);
  212. //兼容计算精度问题
  213. $real_balance_price = bcsub($real_cash_price, bcadd($real_amount_price, $real_integral_price, 2), 2);
  214. }
  215. if ($total_profit != 100) {
  216. throw new \Exception('计算失败,佣金配置错误');
  217. }
  218. return [
  219. 'code' => 0,
  220. 'msg' => '计算成功',
  221. 'data' => [
  222. 'amount_price' => $amount_price,
  223. 'integral_price' => $integral_price,
  224. 'balance_price' => $balance_price,
  225. 'cash_service_charge' => $cash_service_charge,
  226. 'real_amount_price' => $real_amount_price,
  227. 'real_integral_price' => $real_integral_price,
  228. 'real_balance_price' => $real_balance_price,
  229. ]
  230. ];
  231. } catch (\Exception $e) {
  232. return [
  233. 'code' => 1,
  234. 'msg' => $e->getMessage(),
  235. ];
  236. }
  237. }
  238. public static function cashExtSave($cash_id, $cash_price_type, $price, $service_charge, $real_price) {
  239. try {
  240. $model = new self();
  241. $model->cash_id = $cash_id;
  242. $model->cash_price_type = $cash_price_type;
  243. $model->price = $price;
  244. $model->service_charge = $service_charge;
  245. $model->real_price = $real_price;
  246. if (!$model->save()) {
  247. throw new \Exception(implode(';', array_values($model->firstErrors)));
  248. }
  249. return [
  250. 'code' => 0,
  251. 'msg' => '添加成功'
  252. ];
  253. } catch (\Exception $e) {
  254. return [
  255. 'code' => 1,
  256. 'msg' => $e->getMessage(),
  257. ];
  258. }
  259. }
  260. //计算增值积分提现金额
  261. public static function integral_appreciation_cash($cash_price, $store_id) {
  262. $integral_pool = IntegralAppreciationPool::findOne(['store_id' => $store_id]);
  263. $integral_appreciation_setting = Option::get('integral_appreciation_setting', $store_id, 'integral_appreciation')['value'];
  264. $integral_appreciation_setting = json_decode($integral_appreciation_setting ?: '', true);
  265. //提现回流奖金池比例
  266. $integral_payout_pool_profit = $integral_appreciation_setting['integral_payout_pool_profit'];
  267. //增值积分初始金额
  268. $integral_price = $integral_appreciation_setting['integral_init_price'] ?? 0;
  269. //将增值积分转为实际金额进行计算
  270. if ($integral_pool) {
  271. $integral_price = $integral_pool->integral_price;
  272. }
  273. //计算积分回流后的实际提现到账金额
  274. $cash_price = bcmul($cash_price, $integral_price, 2);
  275. $payout_pool_price = bcdiv(bcmul($cash_price, $integral_payout_pool_profit, 2), 100, 2);
  276. $cash_price = bcsub($cash_price, $payout_pool_price, 2);
  277. if ($cash_price <= 0) {
  278. $cash_price = 0;
  279. }
  280. return [
  281. 'cash_price' => $cash_price,//实际提现金额
  282. 'integral_payout_pool_profit' => $integral_payout_pool_profit,//回流比例
  283. 'integral_price' => $integral_price,//增值积分价格
  284. 'payout_pool_price' => $payout_pool_price//回流金额
  285. ];
  286. }
  287. }