CommonGoods.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. <?php
  2. /**
  3. * 重庆赤晓店信息科技有限公司
  4. * https://www.chixiaodian.com
  5. * Copyright (c) 2023 赤店商城 All rights reserved.
  6. */
  7. namespace app\modules\client\models\v1\common;
  8. use app\models\CashierGoodsPriceLog;
  9. use app\models\Level;
  10. use app\models\Goods;
  11. use app\models\MchSetting;
  12. use app\models\SupplierSetting;
  13. use yii\helpers\Json;
  14. class CommonGoods
  15. {
  16. /**
  17. * 获取当前规格的相应信息
  18. * @param array $goods 商品信息
  19. * @param array $currentAttrIds 当前选择的规格数据 例:[42,43]
  20. * @param array $otherData 特殊数据处理 阶梯团、秒杀
  21. * @return array
  22. */
  23. public static function currentGoodsAttr(array $goods, array $currentAttrIds, array $otherData = [], $number = 1,$goods_id=0)
  24. {
  25. $batch_price_tips = '';
  26. $current_batch_price_tips = '';
  27. $is_true = 0;
  28. $full_minus_attrs = [];
  29. /**
  30. * 判断商品是否开启会员折扣,且用户是否为会员,且会员中的折扣存在
  31. */
  32. //获取用户信息
  33. isset($otherData['user']) && $user = $otherData['user'];
  34. if (empty($user)) {
  35. $user = get_user();
  36. }
  37. //获取会员折扣信息
  38. $level = Level::find()->where(['store_id' => $user->store_id, 'status' => 1, 'is_delete' => 0, 'level' => $user->level])->andWhere(['>', 'discount', 0])->select('id')->one();
  39. $open = true;
  40. //判断商品是否开启会员折扣,且用户是否为会员,且会员中的折扣存在
  41. if ($user->level && !empty($level)) {
  42. $open = false;
  43. }
  44. //如果以上条件成立,则不使用满减折扣
  45. if (isset($goods['full_minus']) && $open){
  46. foreach ($goods['full_minus'] as $k => $v){
  47. $full_minus_list = json_decode($goods['full_minus'][$k]['attr'], true);
  48. if (!$full_minus_list || count($full_minus_list) < 1) {
  49. continue;
  50. }
  51. foreach ($full_minus_list as $key => $value) {
  52. $attrIds = [];
  53. foreach ($full_minus_list[$key]['attr_list'] as $item) {
  54. $attrIds[] = $item['attr_id'];
  55. }
  56. sort($attrIds);
  57. sort($currentAttrIds);
  58. if (($number >= $goods['full_minus'][$k]['full_minus_num']) && (implode($attrIds) === implode($currentAttrIds)) && $full_minus_list[$key]['price']) {
  59. $full_minus_attrs = $full_minus_list[$key];
  60. $current_batch_price_tips ='满'.$goods['full_minus'][$k]['full_minus_num'].$goods['unit'].', '. $full_minus_list[$key]['price'] .'元';
  61. }
  62. if (($number <= $goods['full_minus'][$k]['full_minus_num']) && $is_true == 0 && (implode($attrIds) === implode($currentAttrIds)) && $full_minus_list[$key]['price']){
  63. $is_true = 1;
  64. $batch_price_tips ='满'.$goods['full_minus'][$k]['full_minus_num'].$goods['unit'].', '. $full_minus_list[$key]['price'] .'元';
  65. }elseif (($number > $goods['full_minus'][$k]['full_minus_num']) && (implode($attrIds) === implode($currentAttrIds)) && $full_minus_list[$key]['price']){
  66. $batch_price_tips ='满'.$goods['full_minus'][$k]['full_minus_num'].$goods['unit'].', '. $full_minus_list[$key]['price'] .'元';
  67. }
  68. }
  69. }
  70. }
  71. $attrs = Json::decode($goods['attr']);
  72. $level = self::currentLevelDiscount($user ? $user : null);
  73. foreach ($attrs as $attr) {
  74. $attrIds = [];
  75. foreach ($attr['attr_list'] as $item) {
  76. $attrIds[] = $item['attr_id'];
  77. }
  78. sort($attrIds);
  79. sort($currentAttrIds);
  80. // 找出当前规格信息
  81. if (implode($attrIds) === implode($currentAttrIds)) {
  82. // 如果是收银台过来的订单 不再走满减活动!!!!因为收银台可以改商品价格
  83. if (!(isset($otherData['form']) && $otherData['form'] == 'cashier') && $full_minus_attrs && $full_minus_attrs['price']){
  84. $goods['price'] = $attr['price'] = $full_minus_attrs['price'];
  85. }
  86. // price 前端展示价格(该价格可以是 原价、会员价)
  87. $data['price'] = $goods['use_attr'] == 1 ? ($attr['price'] > 0 ? (isset($attr['group_price']) ? $attr['group_price'] : $attr['price']) : $goods['price']) : $goods['price'];//$goods['use_attr'] == 1 ? ($attr['price'] > 0 ? $attr['price'] : $goods['price']) : $goods['price'];
  88. $data['num'] = $attr['num'];
  89. if ($otherData['goods_id'] && $otherData['user_id']) {
  90. $goods_price_log = CashierGoodsPriceLog::find()->where(['goods_id' => $otherData['goods_id'], 'user_id' => $otherData['user_id'], 'md_id' => $goods['md_id'] ?: 0])->asArray()->all();
  91. foreach ($goods_price_log as $price_log_item) {
  92. $price_attr = json_decode($price_log_item['attr'], true);
  93. $price_attr_id = array_column($price_attr['attr_list'], 'attr_id');
  94. sort($price_attr_id);
  95. if (!array_diff($attrIds, $price_attr_id)) {
  96. $data['old_price'] = $price_log_item['price'] ?? '0.00';
  97. }
  98. }
  99. }
  100. $data['supplier_id'] = isset($goods['supplier_id']) ? $goods['supplier_id'] : 0;
  101. $data['supplier_goods_id'] = isset($goods['supplier_goods_id']) ? $goods['supplier_goods_id'] : 0;
  102. $data['supplier_price'] = isset($attr['supplier_price']) ? ($attr['supplier_price'] > 0 ? $attr['supplier_price'] : (isset($goods['supplier_price']) ? $goods['supplier_price'] : 0)) : 0;
  103. $data['goods_price'] = $goods['use_attr'] == 1 ? ($attr['price'] > 0 ? (isset($attr['group_price']) ? $attr['group_price'] : $attr['price']) : $goods['price']) : $goods['price'];//$goods['use_attr'] == 1 ? ($attr['price'] > 0 ? $attr['price'] : $goods['price']) : $goods['price'];//商品售价
  104. $data['attr_list'] = $attr['attr_list'];
  105. $data['pic'] = $attr['pic'];
  106. $data['no'] = $attr['no'];
  107. $data['share_commission_first'] = $attr['share_commission_first'];
  108. $data['share_commission_second'] = $attr['share_commission_second'];
  109. $data['share_commission_third'] = $attr['share_commission_third'];
  110. $data['is_member_price'] = false;
  111. $data['is_level'] = false;
  112. $data['next_level_price'] = $data['level_price'] = $goods['use_attr'] == 1 ? ($attr['price'] > 0 ? (isset($attr['group_price']) ? $attr['group_price'] : $attr['price']) : $goods['price']) : $goods['price'];//$goods['use_attr'] == 1 ? ($attr['price'] > 0 ? $attr['price'] : $goods['price']) : $goods['price'] ;//会员折扣价
  113. $data['batch_price_tips'] = $batch_price_tips;
  114. $data['current_batch_price_tips'] = $current_batch_price_tips;
  115. // 用户等级 可以传入指定用户等级
  116. $userLevel = $level['userLevel'] ? $level['userLevel'] : 0;
  117. $keyName = 'member' . $userLevel;
  118. $nextKeyName = 'member' . $level['userNextLevel'];
  119. // 为会员用户 会员价 > 0 并且商品开启了会员折扣 则显示会员价
  120. if (isset($attr[$keyName]) && $attr[$keyName] > 0 && $goods['is_level'] && $level['userLevel'] >= 0) {
  121. $data['price'] = $attr[$keyName];
  122. $data['is_member_price'] = true;
  123. $data['is_level'] = true;
  124. }
  125. //计算会员股东佣金方式
  126. $level_price_arr = [];
  127. foreach ($level['level'] as $level_index => $level_) {
  128. $level_price_arr[$level_index] = $data['price'];
  129. if (isset($attr[$level_index]) && $attr[$level_index] > 0 && $goods['is_level']) {
  130. $level_price_arr[$level_index] = $attr[$level_index];
  131. } elseif (isset($attr[$level_index]) && $attr[$level_index] <= 0 && $goods['is_level']) {
  132. $level_price_arr[$level_index] = (($data['price'] * $level_) / 10) >= 0.01 ? (($data['price'] * $level_) / 10) : 0.00;
  133. } elseif (1) {
  134. $level_price_arr[$level_index] = ($data['price'] * floatval($level_) / 10) >= 0.01 ? ($data['price'] * floatval($level_) / 10) : 0.00;
  135. }
  136. }
  137. $data['level_price_arr'] = $level_price_arr;
  138. if (isset($attr[$nextKeyName]) && $attr[$nextKeyName] > 0 && $goods['is_level']) {
  139. if (isset($attr[$nextKeyName])) {
  140. $data['next_price'] = $attr[$nextKeyName];
  141. }
  142. }
  143. // \Yii::error([$attr, $keyName, $goods, $level]);
  144. // 为会员用户 开启了规格会员价、但没设置或者规格价等于0 则使用全局会员折扣
  145. if (isset($attr[$keyName]) && $attr[$keyName] <= 0 && $level['userLevel'] >= 0) {
  146. // 如果算出的会员折扣价 < 0.01 那会员价就是0
  147. $data['price'] = (($data['price'] * $level['discount']) / 10) >= 0.01 ? (($data['price'] * $level['discount']) / 10) : 0.00;
  148. $data['is_member_price'] = true;
  149. $data['is_level'] = true;
  150. }
  151. if (isset($attr[$keyName]) && $attr[$keyName] <= 0) {
  152. $data['next_price'] = (($data['price'] * $level['next_discount']) / 10) >= 0.01 ? (($data['price'] * $level['next_discount']) / 10) : 0.00;
  153. }
  154. // 商城开启了会员折扣 且是会员用户
  155. if ($level['userLevel'] >= 0) {
  156. // 会员折扣价为 会员价
  157. if ($data['is_member_price'] === true) {
  158. $data['level_price'] = $data['price'];
  159. $data['next_level_price'] = $data['next_price'];
  160. // $data['is_level'] = false;
  161. } else {
  162. // 会员折扣价 根据会员折扣计算而来
  163. $data['level_price'] = ($data['price'] * floatval($level['discount']) / 10) >= 0.01 ? ($data['price'] * floatval($level['discount']) / 10) : 0.00;
  164. $data['next_level_price'] = ($data['price'] * floatval($level['next_discount']) / 10) >= 0.01 ? ($data['price'] * floatval($level['next_discount']) / 10) : 0.00;
  165. $data['is_level'] = true;
  166. }
  167. // TODO 特殊 拼团单买暂时不需要计算会员折扣
  168. if (!empty($otherData['order_type']) && $otherData['order_type'] === 'ONLY_BUY') {
  169. $data['is_level'] = false;
  170. // TODO 以下两个字段会被覆盖,没什么作用
  171. $data['goods_price'] = $attr['single'] > 0 ? $attr['single'] : $otherData['single_price'];
  172. $data['level_price'] = $data['single_price'];
  173. }
  174. }
  175. // 商城开启了会员折扣 且是普通用户
  176. if ($level['userLevel'] === -1) {
  177. // 会员折扣价为 会员价
  178. $data['level_price'] = $data['goods_price'];
  179. $data['next_level_price'] = $data['next_price'];
  180. $data['is_level'] = false;
  181. if (isset($otherData['order_type']) && $otherData['order_type'] === 'ONLY_BUY') {
  182. $data['is_level'] = false;
  183. $data['goods_price'] = $attr['single'] > 0 ? $attr['single'] : $otherData['single_price'];
  184. $data['level_price'] = $data['single_price'];
  185. $data['next_level_price'] = ($data['single_price'] * ($level['next_discount'] / 10));
  186. }
  187. }
  188. $data['price'] = sprintf("%.2f", $data['price']) > 0 ? sprintf("%.2f", $data['price']) : $goods['price'];
  189. $data['level_price'] = sprintf("%.2f", $data['level_price']) > 0 ? sprintf("%.2f", $data['level_price']) : sprintf("%.2f", $data['price']);
  190. $data['next_level_price'] = sprintf("%.2f", $data['next_level_price']) > 0 ? sprintf("%.2f", $data['next_level_price']) : sprintf("%.2f", $data['price']);
  191. $food_ext_goods_price = 0;
  192. if($goods['food_ext_goods']){
  193. $food_ext_goods = is_array($goods['food_ext_goods']) ? $goods['food_ext_goods'] : json_decode($goods['food_ext_goods'], true);
  194. foreach($food_ext_goods as $egitem){
  195. $food_ext_goods_price += $egitem['price'] * $egitem['num'];
  196. }
  197. }
  198. $data['price'] += $food_ext_goods_price;
  199. $data['level_price'] += $food_ext_goods_price;
  200. $data['next_level_price'] += $food_ext_goods_price;
  201. return $data;
  202. }
  203. }
  204. }
  205. /**
  206. * 获取当前商品的最高分销价、及最低会员价(根据用户等级)
  207. * user_is_member 是否会员
  208. * is_level 是否开启会员折扣
  209. * is_share 是否开启分销
  210. * min_member_price 最低会员价
  211. * max_share_price 最高分销价
  212. * @param $goods
  213. * @return array
  214. */
  215. public static function getMMPrice(array $goods, $otherData = [])
  216. {
  217. $attrs = is_string($goods['attr']) && !empty($goods['attr']) ? Json::decode($goods['attr']) : [];
  218. $storeId = get_store_id();
  219. $level = self::currentLevelDiscount();
  220. $maxSharePriceArr = [];
  221. $minMemberPriceArr = [];
  222. $minNextMemberPriceArr = [];
  223. foreach ($attrs as $attr) {
  224. $price = $goods['use_attr'] == 1 ? ($attr['price'] > 0 ? $attr['price'] : $goods['price']) : $goods['price'];
  225. // 商品开启单独分销设置 (按一级分销佣金计算)
  226. if ((int)$goods['individual_share'] === 1) {
  227. // 普通设置 (单商品全局)
  228. if ((int)$goods['attr_setting_type'] === 0 && $goods['share_commission_first'] > 0) {
  229. // 分销普通设置 按百分比
  230. if ((int)$goods['share_type'] === 0) {
  231. $maxSharePriceArr[] = ($goods['share_commission_first'] * $price) / 100;
  232. }
  233. // 分销普通设置 按固定金额
  234. if ((int)$goods['share_type'] === 1) {
  235. $maxSharePriceArr[] = $goods['share_commission_first'];
  236. }
  237. }
  238. // 详细设置 (多规格分销价)
  239. if ((int)$goods['attr_setting_type'] === 1 && $attr['share_commission_first'] > 0) {
  240. if ((int)$goods['share_type'] === 0) {
  241. $maxSharePriceArr[] = ($attr['share_commission_first'] * $price) / 100;
  242. }
  243. if ((int)$goods['share_type'] === 1) {
  244. $maxSharePriceArr[] = $attr['share_commission_first'];
  245. }
  246. }
  247. }
  248. // 开启商品会员折扣
  249. $data['user_is_member'] = false;
  250. if (1) {
  251. // 普通用户 (显示下一级会员价)
  252. if ($level['userLevel'] === -1) {
  253. $data['user_is_member'] = false;
  254. $keyName = 'member' . $level['list'][0]['level'];
  255. // 多规格会员价大于 > 0 则直接展示
  256. if (isset($attr[$keyName]) && $attr[$keyName] > 0 && $goods['is_level']) {
  257. $minMemberPriceArr[] = $attr[$keyName];
  258. } else {
  259. $minMemberPriceArr[] = ($price * $level['list'][0]['discount']) / 10;
  260. }
  261. }
  262. // 会员用户 (显示当前会员价)
  263. if ($level['userLevel'] >= 0) {
  264. $data['user_is_member'] = true;
  265. $keyName = 'member' . $level['userLevel'];
  266. // 多规格会员价大于 > 0 则直接展示
  267. if (isset($attr[$keyName]) && $attr[$keyName] > 0 && $goods['is_level']) {
  268. $minMemberPriceArr[] = $attr[$keyName];
  269. } else {
  270. $minMemberPriceArr[] = ($price * $level['discount']) / 10;
  271. }
  272. }
  273. $keyNextName = 'member' . $level['userNextLevel'];
  274. if (isset($attr[$keyNextName]) && $attr[$keyNextName] > 0) {
  275. $minNextMemberPriceArr[] = $attr[$keyNextName];
  276. } else {
  277. $minNextMemberPriceArr[] = ($price * $level['next_discount']) / 10;
  278. }
  279. }
  280. // 未开启商品会员折扣
  281. if (1) {
  282. // 显示最小规格价
  283. $minMemberPriceArr[] = $price;
  284. }
  285. }
  286. $data['max_share_price'] = !empty($maxSharePriceArr) ? max($maxSharePriceArr) : 0;
  287. $data['min_member_price'] = !empty($minMemberPriceArr) ? min($minMemberPriceArr) : 0;
  288. $data['min_next_member_price'] = !empty($minNextMemberPriceArr) ? min($minNextMemberPriceArr) : 0;
  289. // 商品是否开启会员折扣
  290. $data['is_level'] = false;
  291. if (1) {
  292. $data['is_level'] = true;
  293. }
  294. // 总商城分销 是否开启
  295. $data['is_share'] = false;
  296. // 如果会员价 <= 0 则不显示
  297. if (sprintf('%.2f', $data['min_member_price']) <= 0) {
  298. $data['is_level'] = false;
  299. }
  300. // 如果会员中心一个会员都没有,则不显示会员价
  301. if (empty($level['list'])) {
  302. $data['is_level'] = false;
  303. }
  304. return $data;
  305. }
  306. /**
  307. * 获取当前会员折扣
  308. */
  309. private static function currentLevelDiscount($user = null)
  310. {
  311. $user = $user ? $user : get_user();
  312. $userNextLevel = $userLevel = isset($user->level) ? $user->level : -1;
  313. $storeId = $user->store_id;
  314. $levelList = Level::find()->where(['store_id' => $storeId, 'is_delete' => 0, 'status' => Level::STATUS_TRUE])
  315. ->select('id, level, name, discount, price')
  316. ->orderBy('level ASC')
  317. ->asArray()->all();
  318. $currentLevelDiscount = 10;
  319. $next_currentLevelDiscount = 10;
  320. $is_discount = false;
  321. $level_ = [];
  322. foreach ($levelList as $level) {
  323. $level_['member' . $level['level']] = $level['discount'];
  324. }
  325. foreach ($levelList as $level) {
  326. if ((int)$level['level'] === $userLevel && !$is_discount) {
  327. $currentLevelDiscount = $level['discount'];
  328. $is_discount = true;
  329. continue;
  330. }
  331. if ((int)$level['level'] > $userLevel && $level['price'] > 0) {
  332. $userNextLevel = (int)$level['level'];
  333. $next_currentLevelDiscount = $level['discount'];
  334. break;
  335. }
  336. }
  337. return [
  338. 'discount' => $currentLevelDiscount,
  339. 'next_discount' => $next_currentLevelDiscount,
  340. 'userLevel' => $userLevel,
  341. 'userNextLevel' => $userNextLevel,
  342. 'list' => $levelList,
  343. 'level' => $level_
  344. ];
  345. }
  346. public static function getMemberPrice(array $goods, $otherData = [], $user = null)
  347. {
  348. $attrs = json_decode($goods['attr'], true);
  349. $storeId = get_store_id();
  350. $level = self::currentLevelDiscount($user);
  351. $use_attr = isset($goods['use_attr']) ? $goods['use_attr'] : 0;
  352. $minMemberPriceArr = [];
  353. foreach ((array)$attrs as $attr) {
  354. if ((bool)$use_attr) {
  355. $price = $attr['price'] > 0 ? $attr['price'] : $goods['price'];
  356. } else {
  357. $price = $goods['price'];
  358. }
  359. // 秒杀插件规格价字段有所不同
  360. if ($otherData && $otherData['type'] === 'MIAOSHA') {
  361. $price = $attr['miaosha_price'] > 0 ? $attr['miaosha_price'] : $goods['price'];
  362. }
  363. // 开启商品会员折扣
  364. $data['user_is_member'] = false;
  365. if (1) {
  366. // 普通用户 (显示下一级会员价)
  367. if ($level['userLevel'] === -1) {
  368. $data['user_is_member'] = false;
  369. $keyName = 'member' . $level['list'][0]['level'];
  370. // 多规格会员价大于 > 0 则直接展示
  371. // if (isset($attr[$keyName])) {
  372. // if ($attr[$keyName] > 0) {
  373. // $minMemberPriceArr[] = $attr[$keyName];
  374. // }
  375. // // 如果开启了会员折扣,但i设置的多规格会员价为0,则使用下一级全局会员折扣
  376. // if ($attr[$keyName] <= 0) {
  377. // $minMemberPriceArr[] = ($price * $level['list'][0]['discount']) / 10;
  378. // }
  379. // }
  380. $minMemberPriceArr[] = sprintf("%.2f", $price);
  381. }
  382. // 会员用户 (显示当前会员价)
  383. if ($level['userLevel'] >= 0) {
  384. $data['user_is_member'] = true;
  385. $keyName = 'member' . $level['userLevel'];
  386. if (isset($attr[$keyName]) && $goods['is_level']) {
  387. // 多规格会员价大于 > 0 则直接展示
  388. if ($attr[$keyName] > 0) {
  389. $minMemberPriceArr[] = $attr[$keyName];
  390. }
  391. // 如果开启了会员折扣,但设置的多规格会员价为0,则使用全局会员折扣
  392. if ($attr[$keyName] <= 0) {
  393. $minMemberPriceArr[] = ($price * $level['discount']) / 10;
  394. }
  395. } else {
  396. // 如果开启了会员折扣,但设置的多规格会员价为0,则使用全局会员折扣
  397. $minMemberPriceArr[] = ($price * $level['discount']) / 10;
  398. }
  399. }
  400. }
  401. // 未开启商品会员折扣
  402. if (1) {
  403. // 显示最小规格价
  404. $minMemberPriceArr[] = $price;
  405. }
  406. }
  407. $data['min_member_price'] = !empty($minMemberPriceArr) ? min($minMemberPriceArr) : 0;
  408. // 商品是否开启会员折扣
  409. $data['is_level'] = false;
  410. if (1) {
  411. $data['is_level'] = true;
  412. }
  413. // 如果会员价 <= 0 则不显示
  414. if (sprintf('%.2f', $data['min_member_price']) <= 0) {
  415. $data['is_level'] = false;
  416. }
  417. // 如果会员中心一个会员都没有,则不显示会员价
  418. if (empty($level['list'])) {
  419. $data['is_level'] = false;
  420. }
  421. return $data;
  422. }
  423. }