Goods.php 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2017~2021 https://www.yiovo.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
  8. // +----------------------------------------------------------------------
  9. // | Author: 萤火科技 <admin@yiovo.com>
  10. // +----------------------------------------------------------------------
  11. declare (strict_types=1);
  12. namespace app\api\model;
  13. use app\api\model\card\RiceCard;
  14. use app\api\model\card\UserRiceCard;
  15. use app\api\model\Coupon as CouponModel;
  16. use app\api\model\ActivityDiscountGoods as ActivityDiscountGoodsModel;
  17. use app\api\model\ActivityDiscount as ActivityDiscountModel;
  18. use app\api\model\fullsend\FullSendActivity;
  19. use app\api\model\member\MemberGoods;
  20. use app\api\model\mj\MjSendActivity;
  21. use app\api\model\qc\QcMjSendActivity;
  22. use app\api\service\User as UserService;
  23. use app\api\model\GoodsSpecRel as GoodsSpecRelModel;
  24. use app\common\model\Goods as GoodsModel;
  25. use app\common\enum\goods\Status as GoodsStatusEnum;
  26. use app\common\library\helper;
  27. use app\common\exception\BaseException;
  28. use app\common\model\UserFavorite as UserFavoriteModel;
  29. use app\common\service\commission\RecordWaitCommission;
  30. use app\common\service\delivery\Express as ExpressService;
  31. use app\api\model\Order as OrderModel;
  32. use app\common\model\GoodsSku as GoodsSkuModel;
  33. use app\api\model\Setting as SettingModel;
  34. use app\common\enum\Setting as SettingEnum;
  35. use app\api\model\member\MemberGoods as MemerGoodsModel;
  36. /**
  37. * 商品模型
  38. * Class Goods
  39. * @package app\api\model
  40. */
  41. class Goods extends GoodsModel
  42. {
  43. /**
  44. * 隐藏字段
  45. * @var array
  46. */
  47. public $hidden = [
  48. // 'images',
  49. 'deduct_stock_type',
  50. 'sales_initial',
  51. 'sales_actual',
  52. 'sort',
  53. 'is_delete',
  54. 'store_id',
  55. 'create_time',
  56. 'update_time',
  57. 'provider', //
  58. ];
  59. /**
  60. * 商品详情:HTML实体转换回普通字符
  61. * @param $value
  62. * @return string
  63. */
  64. public function getContentAttr($value)
  65. {
  66. return htmlspecialchars_decode((string)$value);
  67. }
  68. /**
  69. * 获取商品列表
  70. * @param array $param 查询条件
  71. * @param int $listRows 分页数量
  72. * @param bool $showVip
  73. * @return mixed|\think\model\Collection|\think\Paginator
  74. * @throws \think\db\exception\DbException
  75. */
  76. public function getList(array $param = [], int $listRows = 15 , bool $showVip = false,bool $enableExchange = false)
  77. {
  78. // 整理查询参数
  79. $params = array_merge($param, ['status' => GoodsStatusEnum::ON_SALE]);
  80. // 获取商品列表
  81. $list = parent::getListFront($params, $listRows ,$showVip,$enableExchange);
  82. if ($list->isEmpty()) {
  83. return $list;
  84. }
  85. // 隐藏冗余的字段
  86. $list->hidden(array_merge($this->hidden, ['content', 'goods_images', 'images']));
  87. // 整理列表数据并返回
  88. return $this->setGoodsListDataFromApi($list);
  89. }
  90. //抄首页的代码 lrh
  91. public function getRiceList($param = []){
  92. $allGoods = [];
  93. $goodsList = GoodsModel::alias('goods')->with(['images.file'])
  94. ->field('goods.*,(goods.sales_initial+goods.sales_actual + goods.sales_shops) as goods_sales,(goods.collect_num*0.8+goods.cart_num+(goods.sales_initial+goods.sales_actual)*1.5) as common_sort')
  95. ->where('goods.status', 10)
  96. ->where('goods.stock_total', '>', 0)
  97. ->where('goods.is_delete', 0)
  98. ->where('goods.is_show', 1)
  99. ->where("goods.goods_id",'in',$param['goods_id_arr'])
  100. ->where("goods_type",10)
  101. ->order(['create_time'=>'desc'])->select();
  102. if (!empty($goodsList)) {
  103. foreach ($goodsList as $vv) {
  104. $goodsInfo = $vv;
  105. $goodsInfo['goods_images'] = helper::getArrayColumn($vv['images'], 'file');
  106. // 商品主图
  107. $goodsInfo['goods_image'] = current($goodsInfo['goods_images'])['preview_url'];
  108. $allGoods[] = [
  109. 'goods_id' => $goodsInfo['goods_id'],
  110. 'goods_name' => $goodsInfo['goods_name'],
  111. 'spec_type' => $goodsInfo['spec_type'],
  112. 'goods_price_min' => $goodsInfo['goods_price_min'],
  113. 'goods_price_max' => $goodsInfo['goods_price_max'],
  114. 'line_price_min' => $goodsInfo['line_price_min'],
  115. 'line_price_max' => $goodsInfo['line_price_max'],
  116. 'goods_images' => $goodsInfo['goods_images'],
  117. 'goods_image' => $goodsInfo['goods_image'],
  118. 'goods_sales' => $goodsInfo['goods_sales'],
  119. 'stock_total' => $goodsInfo['stock_total']
  120. ];
  121. }
  122. }
  123. return $allGoods;
  124. }
  125. /**
  126. * 获取商品详情 (详细数据用于页面展示)
  127. * @param int $goodsId 商品id
  128. * @param array|bool $userInfo 用户信息
  129. * @return mixed
  130. * @throws BaseException
  131. * @throws \think\db\exception\DataNotFoundException
  132. * @throws \think\db\exception\DbException
  133. * @throws \think\db\exception\ModelNotFoundException
  134. */
  135. public function getDetails(int $goodsId, $userInfo = false, $addressId = 0, $staffUserId = 0)
  136. {
  137. // 关联查询
  138. $with = ['images' => ['file'], 'skuList' => ['image']];
  139. // 获取商品记录
  140. $goodsInfo = static::detail($goodsId, $with);
  141. // 判断商品的状态
  142. if (empty($goodsInfo) || $goodsInfo['is_delete'] || $goodsInfo['status'] != GoodsStatusEnum::ON_SALE) {
  143. throwError('很抱歉,商品信息不存在或已下架');
  144. }
  145. // 设置商品展示的数据
  146. $goodsInfo = $this->setGoodsDataFromApi($goodsInfo);
  147. // 商品规格列表
  148. $goodsInfo['specList'] = GoodsSpecRelModel::getSpecList($goodsInfo['goods_id']);
  149. $userFavoriteModel = new UserFavoriteModel;
  150. $goodsInfo['collect'] = $userFavoriteModel->getGoodCollect($userInfo->user_id ?? 0, $goodsId);
  151. // 预计佣金
  152. $o = new RecordWaitCommission();
  153. $goodsInfo['fc_yj_amount'] = $o->calcFcYjAmount($goodsInfo, $userInfo);
  154. // 判断配送范围
  155. $goodSkuId = GoodsSkuModel::where('goods_id',$goodsId)->order('id', 'asc')->value('goods_sku_id');
  156. $goodsList = $this->getOrderGoodsListForDelivery(
  157. (int)$goodsId,
  158. (string)$goodSkuId,
  159. 1
  160. );
  161. // 获取收货地址
  162. $address_info = [];
  163. if (!empty($userInfo) && $addressId) {
  164. $address_info = UserAddress::where('user_id', $userInfo->user_id)->where('address_id', $addressId)->find();
  165. }
  166. if (empty($address_info)) {
  167. $address_info = $userInfo['address_default']??null;
  168. }
  169. $goodsInfo['address_info'] = $address_info;
  170. $cityId = $address_info ? (int)$address_info['city_id'] : 0;
  171. // 初始化配送服务类
  172. $ExpressService = new ExpressService($cityId, $goodsList);
  173. $goodsInfo['isIntraRegion'] = true;
  174. // 验证商品是否在限购配送范围
  175. $isDeliveryLimit = $ExpressService->isDeliveryLimit();
  176. if ($isDeliveryLimit == false) {
  177. $goodsInfo['isIntraRegion'] = false;
  178. } else {
  179. // 验证商品是否在配送范围
  180. $isIntraRegion = $ExpressService->isIntraRegion();
  181. if ($cityId > 0 && $isIntraRegion == false) {
  182. $goodsInfo['isIntraRegion'] = false;
  183. }
  184. }
  185. // 可使用现金卡数据
  186. $goodsInfo['valid_cash_rice_card'] = (new RiceCard())->validCashRiceCard($goodsInfo);
  187. $CouponModel = new CouponModel;
  188. $couponList = $CouponModel->getList(50, true,0,null,2,1);//获取可领取的优惠券
  189. // 验证是否可使用优惠券
  190. $goodsInfo['valid_cash_coupon'] = false;
  191. $newCouponList = [];
  192. //剔除当前商品不可用的优惠券
  193. foreach ($couponList as $item){
  194. $exceptGoodsId = helper::getArrayColumn($item['goodsExcept'],'goods_id');
  195. $excludedGoodsIds = array_intersect($exceptGoodsId, [$goodsId]);
  196. if(count($excludedGoodsIds)>0) continue;
  197. if($item['is_receive']){
  198. $goodsInfo['valid_cash_coupon'] = true;
  199. }
  200. //最低限额
  201. if($item['min_price']>$goodsInfo['goods_price_min']) continue;
  202. // 计算打折金额
  203. if ($item['coupon_type'] == 50) {
  204. $reducePrice = helper::bcmul($goodsInfo['goods_price_min'], 1-($item['discount'] / 100));
  205. //如果设置了最大的优惠金额并且当前优惠的金额大于设置的金额
  206. if($item['max_discount_price']>0 && $item['max_discount_price']<$reducePrice){
  207. $reducePrice = $item['max_discount_price'];
  208. }
  209. $item['reduced_price'] = $reducePrice;
  210. } else
  211. $item['reduced_price'] = $item['reduce_price'];
  212. $newCouponList[] = $item->toArray();
  213. }
  214. //按照reduced_price倒叙,tmp_expire_time升序
  215. $tempCs = array_values(array_sort($newCouponList, 'reduced_price', true));
  216. $reducePrices = array_values(array_unique(array_column($tempCs,'reduced_price')));
  217. $fc = [];
  218. foreach ($reducePrices as $k=>$i){
  219. $tt = [];
  220. foreach ($newCouponList as $j=>$c){
  221. if ($i == $c['reduced_price']){
  222. $tt[] = $c;
  223. unset($newCouponList[$j]);
  224. }
  225. }
  226. if (count($tt)){
  227. $ttt = array_sort($tt, 'fmt_expire_time', false);
  228. $fc = array_merge($fc,$ttt);
  229. }
  230. }
  231. $goodsInfo['coupon_list'] = $fc;
  232. //$goodsInfo['coupon_list'] = array_values(array_sort($newCouponList, 'reduced_price', true));
  233. // 顾客购物优惠金额--start---
  234. $distributorRadio = SettingModel::getItem(SettingEnum::DISTRIBUTOR)['shopping_discount'];
  235. $shopping_discount_amount = 0;
  236. // 获取分享链接的用户信息
  237. $userStaff = User::detail($staffUserId);
  238. if ($distributorRadio > 0) {
  239. if ((!empty($userInfo) && $userInfo->role == User::COMMISSION_USER) || (!empty($userStaff) && $userStaff->role == User::COMMISSION_USER)) {
  240. $shopping_discount_amount = helper::bcmul($goodsInfo['goods_price_min'], $distributorRadio / 100, 2);
  241. }
  242. }
  243. $goodsInfo['shopping_discount_amount'] = $shopping_discount_amount;
  244. // 顾客购物优惠金额--end---
  245. // 顾客购物优惠金额--start---
  246. $member_good_discount = MemberGoods::where('goods_id',$goodsInfo['goods_id'])->where('status',0)->value('discount');
  247. if($member_good_discount){
  248. $goodsInfo['is_member_goods'] = 1;
  249. if($userInfo['member_expire_time']>time()){
  250. $goodsInfo['is_member'] = 1;
  251. }else{
  252. $goodsInfo['is_member'] = 0;
  253. }
  254. $goodsInfo['member_discount_amount'] = helper::bcmul($goodsInfo['goods_price_min'], (100-$member_good_discount)/100);//换算成百分比,会员优惠券
  255. }else{
  256. $goodsInfo['member_discount_amount'] = 0;
  257. $goodsInfo['is_member'] = 0;
  258. $goodsInfo['is_member_goods'] = 0;
  259. }
  260. // 顾客购物优惠金额--end---
  261. //满就送、满件送、全场满件送活动显示规则
  262. self::getSendActivityOrder($goodsInfo);
  263. //添加判断是否有第N件打折的活动
  264. self::getActivityDiscount($goodsInfo);
  265. return $goodsInfo;
  266. }
  267. //获取排名显示顺序
  268. private function getSendActivityOrder(&$goodsInfo){
  269. //满就送对象
  270. $goodsInfo['full_send_act'] = FullSendActivity::validActivity($goodsInfo['goods_id']);
  271. //满件送对象详情
  272. $goodsInfo['mj_send_act'] = MjSendActivity::validActivity($goodsInfo['goods_id']);
  273. //全场满件赠对象
  274. $goodsInfo['qc_mj_send_act'] = QcMjSendActivity::validActivity($goodsInfo['goods_id']);
  275. $goodsInfo['is_send_act'] = 0;//是否显示活动 0不显示 1显示满就送 2显示满件送 3全场满件送
  276. $time1 = $goodsInfo['full_send_act']['remain_secs']??0;
  277. $time2 = $goodsInfo['mj_send_act']['remain_secs']??0;
  278. $time3 = $goodsInfo['qc_mj_send_act']['remain_secs']??0;
  279. if($goodsInfo['full_send_act'] && $goodsInfo['mj_send_act'] && $goodsInfo['qc_mj_send_act']){
  280. $time1 = $goodsInfo['full_send_act']['remain_secs'];
  281. $time2 = $goodsInfo['mj_send_act']['remain_secs'];
  282. $time3 = $goodsInfo['qc_mj_send_act']['remain_secs'];
  283. if($time1>$time2 && $time2>$time3){
  284. $goodsInfo['is_send_act'] = 3;
  285. }
  286. if($time1>$time2 && $time3>$time2){
  287. $goodsInfo['is_send_act'] = 2;
  288. }
  289. if($time2>$time1 && $time1>$time3){
  290. $goodsInfo['is_send_act'] = 3;
  291. }
  292. if($time2>$time3 && $time3>$time1){
  293. $goodsInfo['is_send_act'] = 1;
  294. }
  295. if($time3>$time1 && $time1>$time2){
  296. $goodsInfo['is_send_act'] = 2;
  297. }
  298. if($time3>$time2 && $time2>$time1){
  299. $goodsInfo['is_send_act'] = 1;
  300. }
  301. }
  302. if($goodsInfo['full_send_act'] && $goodsInfo['mj_send_act'] && !$goodsInfo['qc_mj_send_act']){
  303. if($time1>$time2){
  304. $goodsInfo['is_send_act'] = 2;
  305. }else{
  306. $goodsInfo['is_send_act'] = 1;
  307. }
  308. }
  309. if($goodsInfo['full_send_act'] && !$goodsInfo['mj_send_act'] && $goodsInfo['qc_mj_send_act']){
  310. if($time1>$time3){
  311. $goodsInfo['is_send_act'] = 3;
  312. }else{
  313. $goodsInfo['is_send_act'] = 1;
  314. }
  315. }
  316. if($goodsInfo['full_send_act'] && !$goodsInfo['mj_send_act'] && !$goodsInfo['qc_mj_send_act']){
  317. $goodsInfo['is_send_act'] = 1;
  318. }
  319. if(!$goodsInfo['full_send_act'] && $goodsInfo['mj_send_act'] && $goodsInfo['qc_mj_send_act']){
  320. if($time3>$time2){
  321. $goodsInfo['is_send_act'] = 2;
  322. }else{
  323. $goodsInfo['is_send_act'] = 3;
  324. }
  325. }
  326. if(!$goodsInfo['full_send_act'] && $goodsInfo['mj_send_act'] && !$goodsInfo['qc_mj_send_act']){
  327. $goodsInfo['is_send_act'] = 2;
  328. }
  329. if(!$goodsInfo['full_send_act'] && !$goodsInfo['mj_send_act'] && $goodsInfo['qc_mj_send_act']){
  330. $goodsInfo['is_send_act'] = 3;
  331. }
  332. $goodsInfo['is_show_line_price'] = 0;
  333. if($goodsInfo['line_price_min']<=$goodsInfo['goods_price_min']){
  334. $goodsInfo['is_show_line_price'] = 1;
  335. }
  336. }
  337. /**
  338. * 获取当前商品是否存在N件X折活动
  339. * @param $goodsInfo 商品详情
  340. * @param $type 商品详情
  341. * @return mixed
  342. * @throws \think\db\exception\DataNotFoundException
  343. * @throws \think\db\exception\DbException
  344. * @throws \think\db\exception\ModelNotFoundException
  345. * @author: zjwhust
  346. * @Time: 2022/3/10 14:47
  347. */
  348. public function getActivityDiscount(&$goodsInfo){
  349. $goodsInfo['is_activity_discount'] = 0; //是否有折扣活动 0没有 1有
  350. $activity_ids = ActivityDiscountGoodsModel::where('goods_id',$goodsInfo['goods_id'])->column('activity_id');//获取所有有该商品的活动ID
  351. if($activity_ids){
  352. $ActivityDiscount = ActivityDiscountModel::where('id','in',$activity_ids)
  353. ->where(['is_up'=>1,'audit_status_zg'=>10])
  354. ->where('start_time','<',date('Y-m-d H:i:s'))
  355. ->where('end_time','>',date('Y-m-d H:i:s'))
  356. ->find();
  357. if($ActivityDiscount){
  358. $discount_props = array_values(array_sort($ActivityDiscount['discount_props'], 'value'));
  359. $goodsInfo['is_activity_discount'] = 1;
  360. $goodsInfo['activity_discount_time'] = (strtotime($ActivityDiscount['end_time'])-time());//折扣活动倒计时时间戳
  361. if($ActivityDiscount['type']==1){ //1:第N件起打折,2:满N件起打折
  362. $goodsInfo['activity_discount_desc'] = '第'.$discount_props[0]['value'].'件起'.floatval($discount_props[0]['count']).'折';
  363. $goodsInfo['discount_type'] = 1; //是否有折扣活动 0没有 1有
  364. }else{
  365. $goodsInfo['activity_discount_desc'] = '满'.$discount_props[0]['value'].'件打'.floatval($discount_props[0]['count']).'折';
  366. $goodsInfo['discount_goods_price'] = helper::number2(helper::bcmul($goodsInfo['goods_price_min'],$discount_props[0]['count']/10),true);
  367. $goodsInfo['discount_type'] = 2; //是否有折扣活动 0没有 1有
  368. $goodsInfo['discount_num'] = $discount_props[0]['value'];
  369. }
  370. $goodsInfo['activity_discount'] = $ActivityDiscount;
  371. }
  372. }
  373. return $goodsInfo;
  374. }
  375. public function getOrderGoodsListForDelivery(int $goodsId, string $goodsSkuId, int $goodsNum)
  376. {
  377. // 获取商品列表
  378. $model = new GoodsModel;
  379. $goodsList = $this->getListByIdsFromApi([$goodsId]);
  380. if ($goodsList->isEmpty()) {
  381. throwError('未找到商品信息1');
  382. }
  383. // 隐藏冗余的属性
  384. $goodsList->hidden(array_merge($model->hidden, ['content', 'goods_images', 'images']));
  385. foreach ($goodsList as &$item) {
  386. // 商品sku信息
  387. $item['skuInfo'] = GoodsSkuModel::detail($item['goods_id'], $goodsSkuId);
  388. // 商品单价
  389. $item['goods_price'] = $item['skuInfo']['goods_price'];
  390. // 商品购买数量
  391. $item['total_num'] = $goodsNum;
  392. // 商品SKU索引
  393. $item['goods_sku_id'] = $item['skuInfo']['goods_sku_id'];
  394. // 商品购买总金额
  395. $item['total_price'] = helper::bcmul($item['goods_price'], $goodsNum);
  396. }
  397. return $goodsList;
  398. }
  399. /**
  400. * 根据商品id集获取商品列表
  401. * @param array $goodsIds
  402. * @return mixed
  403. */
  404. public function getListByIdsFromApi(array $goodsIds)
  405. {
  406. // 获取商品列表
  407. // $data = $this->getListByIds($goodsIds, GoodsStatusEnum::ON_SALE);
  408. $data = $this->getListByIds($goodsIds, null);//不隐藏下架的商品
  409. // 整理列表数据并返回
  410. return $this->setGoodsListDataFromApi($data);
  411. }
  412. /**
  413. * 设置商品展示的数据 api模块
  414. * @param $data
  415. * @return mixed
  416. */
  417. private function setGoodsListDataFromApi($data)
  418. {
  419. return $this->setGoodsListData($data, function ($goods) {
  420. // 计算并设置商品会员价
  421. $this->setGoodsDataFromApi($goods);
  422. });
  423. }
  424. /**
  425. * 整理商品数据 api模块
  426. * @param $goodsInfo
  427. * @return mixed
  428. */
  429. private function setGoodsDataFromApi($goodsInfo)
  430. {
  431. return $this->setGoodsData($goodsInfo, function ($goods) {
  432. // 计算并设置商品会员价
  433. $this->setGoodsGradeMoney($goods);
  434. });
  435. }
  436. /**
  437. * 设置商品的会员价
  438. * @param Goods $goods
  439. * @throws BaseException
  440. */
  441. private function setGoodsGradeMoney(self $goods)
  442. {
  443. // 获取当前登录的用户信息
  444. $userInfo = UserService::getCurrentLoginUser();
  445. $goods['member_price'] = (new MemerGoodsModel)->getGoodsMemberPrice($goods['goods_id'],$goods['goods_price_min']);
  446. // 会员等级状态
  447. $gradeStatus = (!empty($userInfo) && $userInfo['grade_id'] > 0 && !empty($userInfo['grade']))
  448. && (!$userInfo['grade']['is_delete'] && $userInfo['grade']['status']);
  449. // 判断商品是否参与会员折扣
  450. if (!$gradeStatus || !$goods['is_enable_grade']) {
  451. $goods['is_user_grade'] = false;
  452. return;
  453. }
  454. // 商品单独设置了会员折扣
  455. if ($goods['is_alone_grade'] && isset($goods['alone_grade_equity'][$userInfo['grade_id']])) {
  456. // 折扣比例
  457. $discountRatio = helper::bcdiv($goods['alone_grade_equity'][$userInfo['grade_id']], 10);
  458. } else {
  459. // 折扣比例
  460. $discountRatio = helper::bcdiv($userInfo['grade']['equity']['discount'], 10);
  461. }
  462. if ($discountRatio > 0) {
  463. // 标记参与会员折扣
  464. $goods['is_user_grade'] = true;
  465. // 会员折扣价
  466. foreach ($goods['skuList'] as &$skuItem) {
  467. $skuItem['goods_price'] = helper::number2(helper::bcmul($skuItem['goods_price'], $discountRatio), true);
  468. }
  469. }
  470. }
  471. /**
  472. * 获取当前商品是否存在N件X折活动
  473. * @param $goodsInfo 商品详情
  474. * @param $type 类型 1购物车 2确认订单
  475. * @return mixed
  476. * @throws \think\db\exception\DataNotFoundException
  477. * @throws \think\db\exception\DbException
  478. * @throws \think\db\exception\ModelNotFoundException
  479. * @author: zjwhust
  480. * @Time: 2022/3/10 14:47
  481. */
  482. public function getActivityDiscountDetail(&$goodsInfo,$type=1){
  483. $goodsInfo['is_activity_discount'] = 0; //是否参与折扣活动 0没有 1有
  484. $goodsInfo['activity_discount_total_price'] = 0; //优惠的金额
  485. $goodsInfo['activity_discount_overlay'] = ''; //叠加的优惠
  486. $goodsInfo['activity_discount_count'] = ''; //数量
  487. $activity_ids = ActivityDiscountGoodsModel::where('goods_id',$goodsInfo['goods_id'])->column('activity_id');//获取所有有该商品的活动ID
  488. if($activity_ids){
  489. $ActivityDiscount = ActivityDiscountModel::with(['goods'])
  490. ->where('id','in',$activity_ids)
  491. ->where(['is_up'=>1,'audit_status_zg'=>10])
  492. ->where('start_time','<',date('Y-m-d H:i:s'))
  493. ->where('end_time','>',date('Y-m-d H:i:s'))
  494. ->find();
  495. if($ActivityDiscount){
  496. $residue_num = 0;
  497. foreach ($ActivityDiscount['goods'] as $goods){
  498. if($goods['goods_id']==$goodsInfo['goods_id']){
  499. $residue_num = $goods['limit_stock']-$goods['purchase_stock'];
  500. }
  501. }
  502. if($residue_num<1){//活动剩余数量为0
  503. return $goodsInfo;
  504. }
  505. if($type == 1 ){
  506. $good_num = $goodsInfo['goods_num'];
  507. $good_price = $goodsInfo['goods']['skuInfo']['goods_price'];
  508. }
  509. if($type == 2 ){
  510. $good_num = $goodsInfo['total_num'];
  511. $good_price = $goodsInfo['goods_price'];
  512. }
  513. $good_num2 = $good_num;
  514. if($good_num>$residue_num){
  515. $good_num2 = $residue_num;
  516. }
  517. // $goodsInfo['activity_discount_time'] = (strtotime($ActivityDiscount['end_time'])-time());//折扣活动倒计时时间戳
  518. $discount_props = array_values(array_sort($ActivityDiscount['discount_props'], 'value', true));
  519. $prop = [];
  520. foreach ($discount_props as $arr){
  521. if($good_num2>=$arr['value']){
  522. $prop = $arr;
  523. break;
  524. }
  525. }
  526. if(!empty($prop)){//当商品数量达到了商品活动的起始数量时
  527. $goodsInfo['is_activity_discount'] = 1;
  528. $goodsInfo['activity_discount_id'] = $ActivityDiscount['id']; //N件X折活动ID
  529. $goodsInfo['activity_discount_overlay'] = $ActivityDiscount['overlay_discount']; //叠加活动状态
  530. $goodsInfo['activity_discount_count'] = $good_num2; //叠加活动数量
  531. if($ActivityDiscount['type']==1){ //1:第N件起打折,2:满N件起打折
  532. $num = $good_num-$prop['value']+1;
  533. $goodsInfo['activity_discount_total_price'] = helper::bcmul((10-$prop['count'])/10,$good_price*$num,2);
  534. $goodsInfo['activity_discount_desc'] = '第'.$prop['value'].'件起打'.floatval($prop['count']).'折';
  535. }else{
  536. $goodsInfo['activity_discount_total_price'] = helper::bcmul((10-$prop['count'])/10,$good_price*$good_num,2);
  537. $goodsInfo['activity_discount_desc'] = '满'.$prop['value'].'件打'.floatval($prop['count']).'折';
  538. }
  539. }
  540. }
  541. }
  542. return $goodsInfo;
  543. }
  544. }