GoodsForm.php 70 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614
  1. <?php
  2. /**
  3. * 重庆赤晓店信息科技有限公司
  4. * https://www.chixiaodian.com
  5. * Copyright (c) 2023 赤店商城 All rights reserved.
  6. */
  7. namespace app\modules\client\models\v1;
  8. use app\constants\OptionSetting;
  9. use app\models\AboutArticle;
  10. use app\models\ActivityRebateOrderN;
  11. use app\models\Address;
  12. use app\models\Cart;
  13. use app\models\Cat;
  14. use app\models\Coupon;
  15. use app\models\DeliveryRules;
  16. use app\models\FreeQueue;
  17. use app\models\FreeQueueGoods;
  18. use app\models\GoodsBook;
  19. use app\models\GoodsBrowse;
  20. use app\models\GoodsCat;
  21. use app\models\GoodsFullMinus;
  22. use app\models\IntegralAppreciationGoods;
  23. use app\models\Level;
  24. use app\models\material\Material;
  25. use app\models\MchGoodsCat;
  26. use app\models\Md;
  27. use app\models\MdGoods;
  28. use app\models\MdGroupActivities;
  29. use app\models\MdGroupActivitiesGoods;
  30. use app\models\Option;
  31. use app\models\OrderDetail;
  32. use app\models\PtActivity;
  33. use app\models\PtActivityGoods;
  34. use app\models\PtActivityOrder;
  35. use app\models\PtActivityOrderDetail;
  36. use app\models\SaasUser;
  37. use app\models\SeckillActivity;
  38. use app\models\SeckillActivityGoods;
  39. use app\models\Share;
  40. use app\models\ShareLevel;
  41. use app\models\User;
  42. use app\models\Store;
  43. use app\models\VerifyCard;
  44. use app\models\Favorite;
  45. use app\models\Goods;
  46. use app\models\GoodsPic;
  47. use app\models\Order;
  48. use app\models\PostageRules;
  49. use app\models\Shop;
  50. use app\models\ActivityNewUser;
  51. use app\models\ActivityNewUserGoods;
  52. use app\models\ActivityWechatRoom;
  53. use app\models\ActivityWechatRoomGoods;
  54. use app\models\ActivityCutPrice;
  55. use app\modules\admin\models\ActivityCutPriceForm;
  56. use app\models\ActivityCutPriceGoods;
  57. use app\modules\admin\models\givingGifts\GivingGiftsForm;
  58. use app\models\GoodsLoweringPrice;
  59. use app\models\TerritorialLimitation;
  60. use app\modules\client\models\v1\common\CommonGoods;
  61. use app\modules\client\models\v1\diy\GetInfo;
  62. use app\modules\client\models\v1\mch\ShopDataForm;
  63. use app\plugins\product_traceability\models\ProductBatch;
  64. use app\utils\Notice\NoticeAction;
  65. use app\utils\Tools;
  66. use yii\base\Model;
  67. use yii\helpers\Json;
  68. class GoodsForm extends Model
  69. {
  70. public $mini_id;
  71. public $id;
  72. public $user_id;
  73. public $store_id;
  74. public $mch_id;
  75. public $shop_id;
  76. public $address_id;
  77. public $verify_card_id;
  78. public $activity_new_user_id = 0;
  79. public $activity_cut_price_id = 0;
  80. public $is_pt;
  81. public $is_seckill;
  82. public $cat_id;
  83. public $md_id;
  84. public function rules()
  85. {
  86. return [
  87. [['id'], 'required'],
  88. [['mch_id', 'shop_id', 'address_id', 'cat_id', 'md_id'], 'integer'],
  89. [['mini_id', 'user_id', 'activity_new_user_id', 'activity_cut_price_id', 'is_pt', 'is_seckill'], 'safe'],
  90. ];
  91. }
  92. /**
  93. * 排序类型$sort 1--综合排序 2--销量排序
  94. */
  95. public function search()
  96. {
  97. $cacheKey = $this->attributes;
  98. // unset($cacheKey['user_id']);
  99. // $cacheVal = cache()->get($cacheKey);
  100. // if($cacheVal){
  101. // return array_merge($cacheVal, ['_cache' => 1]);
  102. // }
  103. if (!$this->validate()) {
  104. return $this->getErrorSummary(false)[0];
  105. }
  106. $where = [
  107. 'id' => $this->id,
  108. 'is_delete' => 0,
  109. 'status' => 1,
  110. 'store_id' => $this->store_id
  111. ];
  112. if (\Yii::$app->prod_is_dandianpu()) {
  113. unset($where['store_id']);
  114. }
  115. $result = StoreConfigForm::getStoreSwitch($this->store_id);
  116. if ($result['is_switch_store']) {
  117. $this->store_id = $where['store_id'] = $result['store_id'];
  118. }
  119. $goods = Goods::findOne($where);
  120. //加价保护start
  121. $platform_profit_strategy = Option::get('platform_profit_strategy', 0, 'store')['value'];
  122. $platform_profit_strategy = json_decode($platform_profit_strategy, true);
  123. if (!empty($platform_profit_strategy) && $goods->cloud_goods_id > 0) {
  124. if (intval($platform_profit_strategy['is_risk_control'])) {
  125. //开启风控
  126. $id = \Yii::$app->cache->get('risk_control_model_id_' . $this->id);
  127. if ($id && !\Yii::$app->queue->isDone($id)) {//\Yii::$app->queue->status($id)
  128. \Yii::$app->queue->remove($id);
  129. }
  130. $id =\queue_push(new \app\jobs\RiskControlModelJob(['goods_id' => $this->id]));
  131. \Yii::$app->cache->set('risk_control_model_id_' . $this->id, $id);
  132. }
  133. }
  134. //加价保护end
  135. $goodsBrowse = GoodsBrowse::find()->where(['goods_id' => $this->id])->select('level')->column();
  136. if(!empty($goodsBrowse) && (empty(get_user()->level) || !in_array(get_user()->level, $goodsBrowse))){
  137. return ['code' => 1,'msg' => '指定会员等级用户才能浏览此商品'];
  138. }
  139. \app\modules\admin\models\erp\InventoryForm::erp2Goods($this->store_id, $goods);
  140. \app\modules\admin\models\jushuitan\JuShuiTanForm::syncStoreJstGoodsQty($this->store_id, $goods);
  141. if (!empty($goods->verify_card_id)) {
  142. $ids = explode(',', $goods->verify_card_id);
  143. $verify_card = Tools::getVerifyList($ids);
  144. } else {
  145. $verify_card = [];
  146. }
  147. $md_is_single = 0;
  148. if (get_md_id()) {
  149. $md = Md::findOne(get_md_id());
  150. if ($md->is_single) {
  151. $md_is_single = 1;
  152. $md_goods = MdGoods::findOne(['md_id' => get_md_id(), 'goods_id' => $this->id]);
  153. if ($md_goods) {
  154. if ($md_goods->status == 0) {
  155. return [
  156. 'code' => 1,
  157. 'msg' => '商品已下架'
  158. ];
  159. }
  160. } else {
  161. if (!$goods) {
  162. return [
  163. 'code' => 1,
  164. 'msg' => '商品不存在'
  165. ];
  166. }
  167. }
  168. } else {
  169. if (!$goods) {
  170. return [
  171. 'code' => 1,
  172. 'msg' => '商品已下架'
  173. ];
  174. }
  175. }
  176. } else {
  177. if (!$goods) {
  178. return [
  179. 'code' => 1,
  180. 'msg' => '商品不存在'
  181. ];
  182. }
  183. }
  184. $mch = null;
  185. if ($goods->mch_id) {
  186. $mch = $this->getMch($goods);
  187. if (!$mch) {
  188. return [
  189. 'code' => 1,
  190. 'msg' => '店铺已经打烊了哦~'
  191. ];
  192. }
  193. }
  194. $pic_list = GoodsPic::find()->select('pic_url')->where(['goods_id' => $goods->id, 'is_delete' => 0])->asArray()->all();
  195. $is_favorite = 0;
  196. if ($this->user_id) {
  197. $exist_favorite = Favorite::find()->where(['user_id' => $this->user_id, 'goods_id' => $goods->id, 'is_delete' => 0])->exists();
  198. if ($exist_favorite) {
  199. $is_favorite = 1;
  200. }
  201. }
  202. $service_list = explode(',', $goods->service);
  203. // 默认商品服务
  204. if (!$goods->service) {
  205. $option = Option::get('good_services', $this->store_id, 'admin', []);
  206. foreach ($option as $item) {
  207. if (!empty($item['is_default'])) {
  208. $service_list = explode(',', $item['service']);
  209. break;
  210. }
  211. }
  212. }
  213. $new_service_list = [];
  214. if (is_array($service_list)) {
  215. foreach ($service_list as $item) {
  216. $item = trim($item);
  217. if ($item) {
  218. $new_service_list[] = $item;
  219. }
  220. }
  221. }
  222. // 门店逻辑
  223. $is_md = false;
  224. if (get_md_id()) {
  225. $md_goods = MdGoods::findOne(['goods_id' => $goods->id, 'md_id' => get_md_id()]);
  226. if ($md_goods && $md_is_single) {
  227. $is_md = true;
  228. }
  229. }
  230. //展示新人专享活动商品信息
  231. // if($this->activity_new_user_id){
  232. $this->activity_new_user($this->activity_new_user_id, $goods, $md_goods);
  233. // }
  234. //展示砍价活动商品信息
  235. $cutGoods = null;
  236. if($this->activity_cut_price_id){
  237. $cutGoods = ActivityCutPriceGoods::findOne(['activity_id' => $this->activity_cut_price_id, 'goods_id' => $goods->id, 'is_delete' => 0]);
  238. // $this->activity_cut_price($this->activity_cut_price_id, $goods, $md_goods);
  239. }
  240. //群活动商品信息
  241. $activityWechatRoom = $this->activity_wechat_room($goods, $md_goods);
  242. $new_price = $is_md ? $md_goods->price : $goods->price;
  243. $price_attr = $is_md ? Json::decode($md_goods->attr) : Json::decode($goods->attr);
  244. $price = [];
  245. // 是否是团购活动商品
  246. $activityModel = MdGroupActivitiesGoods::find()->alias('mgag')->leftJoin(['mga'=>MdGroupActivities::tableName()],'mga.id=mgag.activities_id')->where(['goods_id'=>$goods->id,'mgag.is_delete'=>0])->andWhere(['>=','mga.end_time',time()])->andWhere(['mga.is_delete'=>0])->asArray()->select('mgag.*,mga.start_time,mga.end_time')->one();
  247. if (is_array($price_attr)) {
  248. if($activityModel){
  249. $group_price_attr = Json::decode($activityModel['attr']);
  250. foreach ($group_price_attr as $v) {
  251. if (is_object($v) && $v->group_price > 0) {
  252. $price[] = $v->group_price;
  253. } else {
  254. $price[] = floatval($activityModel['price']);
  255. }
  256. }
  257. }else{
  258. foreach ($price_attr as $v) {
  259. if (is_object($v) && $v->price > 0) {
  260. $price[] = $v->price;
  261. } else {
  262. $price[] = floatval($new_price);
  263. }
  264. }
  265. }
  266. } else {
  267. if($activityModel){
  268. $price = [$activityModel['price']];
  269. }else{
  270. $price = [$goods->price];
  271. }
  272. }
  273. $res_url = GetInfo::getVideoInfo($goods->video_url);
  274. $goods->video_url = $res_url['url'];
  275. if ($goods->is_negotiable) {
  276. $min_price = Goods::GOODS_NEGOTIABLE;
  277. } else {
  278. $min_price = sprintf('%.2f', min($price));
  279. }
  280. $res = CommonGoods::getMMPrice([
  281. 'attr' => $activityModel ? $activityModel['attr'] : ($is_md ? $md_goods->attr : $goods->attr),
  282. 'attr_setting_type' => $goods->attr_setting_type,
  283. 'share_type' => $goods->share_type,
  284. 'share_commission_first' => $goods->share_commission_first,
  285. 'price' => $activityModel ? $activityModel['price'] : $new_price,
  286. 'individual_share' => $goods->individual_share,
  287. 'mch_id' => $goods->mch_id,
  288. 'is_level' => $goods->is_level,
  289. 'use_attr' => $goods->use_attr,
  290. ]);
  291. $attr = $price_attr;
  292. $goodsPrice = $new_price;
  293. $isMemberPrice = false;
  294. if ($res['user_is_member'] === true && count($attr) === 1 && $attr[0]['attr_list'][0]['attr_name'] == '默认') {
  295. $goodsPrice = $res['min_member_price'] ? $res['min_member_price'] : $new_price;
  296. $isMemberPrice = true;
  297. }
  298. $GoodsFullMinus = GoodsFullMinus::find()
  299. ->select('*')
  300. ->where(['store_id' => $this->store_id, 'goods_id' => $goods->id])
  301. ->orderBy('full_minus_num ASC')->asArray()->all();
  302. $seckill_activity_arr = null;
  303. $seckill_activity_goods = [];
  304. if ($this->is_seckill) {
  305. //秒杀活动
  306. $seckill_activity_goods = SeckillActivityGoods::find()->alias('sag')->where(['sag.goods_id' => $goods->id])
  307. ->leftJoin(['sa' => SeckillActivity::tableName()], 'sag.activity_id = sa.id')
  308. ->andWhere(['AND', ['sa.is_delete' => 0], ['>', 'sa.end_time', time()], ['sag.is_delete' => 0]])
  309. ->select('sa.id, sa.self_limit_num, sa.order_limit_num, sa.start_time, sa.end_time, sag.attr, sag.seckill_num, sag.seckill_price, sag.use_attr, sag.sale_num, sag.virtual_sales, sag.virtual_num')->asArray()->all();
  310. }
  311. $level = null;
  312. //获取下一会员等级
  313. if (get_user()) {
  314. $level = Level::find()->where([
  315. 'store_id' => get_store_id(),
  316. 'is_delete' => Level::NOT_DELETE
  317. ])->andWhere(['AND', ['>', 'level', get_user()->level], ['>', 'price', 0]])->select('id, level, name, discount')->orderBy('level ASC')->asArray()->one();
  318. if ($level) {
  319. $level['goods_price'] = $res['min_next_member_price'] > 0 ? sprintf('%.2f', $res['min_next_member_price']) : sprintf('%.2f', ($goods->price * ($level['discount'] / 10)));
  320. //20240816前端要显示下个会员等级预计省多钱
  321. $min_member_price = $res['min_member_price'];
  322. if ($min_member_price <= 0) {
  323. $min_member_price = $goods->price;
  324. }
  325. $level['diff_price'] = bcsub($min_member_price, $level['goods_price'], 2);
  326. if ($level['diff_price'] <= 0) {
  327. $level = null;
  328. }
  329. }
  330. }
  331. if (!empty($seckill_activity_goods) && empty($this->activity_new_user_id) && empty($this->activity_cut_price_id) && empty($this->is_pt)) {
  332. $last_names = array_column($seckill_activity_goods,'start_time');
  333. array_multisort($last_names, SORT_ASC, $seckill_activity_goods);
  334. foreach ($seckill_activity_goods as $activity_good) {
  335. if (($activity_good['seckill_num'] + $activity_good['sale_num'] + $activity_good['virtual_sales']) > 0) {
  336. $activity_good['progress'] = sprintf('%.2f', (($activity_good['sale_num'] + $activity_good['virtual_sales']) / ($activity_good['seckill_num'] + $activity_good['sale_num'] + $activity_good['virtual_sales'])) * 100);
  337. } else {
  338. $activity_good['progress'] = 0;
  339. }
  340. $activity_good['seckill_num'] <= 0 && $activity_good['progress'] = 100;
  341. $activity_good['price'] = $new_price;
  342. $activity_good['seckill_price'] = sprintf('%.2f', $activity_good['seckill_price']);
  343. if ($activity_good['start_time'] < time()) { //活动进行中 前端展示距离结束
  344. $activity_good['status'] = 1;
  345. $seckill_activity_arr = $activity_good;
  346. goto seckill_activity_arr;
  347. }
  348. if ($activity_good['start_time'] >= time()) {//活动进行中 前端展示距离开始
  349. $activity_good['status'] = 2;
  350. $activity_good['progress'] = 0;
  351. $seckill_activity_arr = $activity_good;
  352. goto seckill_activity_arr;
  353. }
  354. }
  355. seckill_activity_arr:
  356. }
  357. if (!empty($seckill_activity_arr)) {
  358. $seckill_activity_arr['attr'] = json_decode($seckill_activity_arr['attr'], true);
  359. if (!empty($seckill_activity_arr['attr'])) {
  360. foreach ($seckill_activity_arr['attr'] as &$activity_attr) {
  361. $activity_attr['seckill_price'] = sprintf('%.2f', $activity_attr['seckill_price']);
  362. }
  363. }
  364. }
  365. //拼团活动信息
  366. $ptGoodsActivity = PtActivityGoods::find()->alias('pag')->where(['pag.is_delete' => 0, 'pa.is_delete' => 0, 'pa.store_id' => get_store_id()])
  367. ->leftJoin(['pa' => PtActivity::tableName()], 'pag.activity_id = pa.id')
  368. ->andWhere(['pag.goods_id' => $goods->id])
  369. ->select('pag.pt_price, pag.sale_num, pag.virtual_sales, pag.attr, pa.party_size, pa.party_type, pa.party_goods_count, pa.split_time, pa.head_integral, pa.head_is_free')
  370. ->andWhere(['AND', ['<', 'pa.start_time', time()], ['>', 'pa.end_time', time()]])->asArray()->one();
  371. if ($ptGoodsActivity && !empty($this->is_pt)) {
  372. $split_time = $ptGoodsActivity['split_time'];
  373. $party_size = $ptGoodsActivity['party_size'];
  374. $party_type = $ptGoodsActivity['party_type'];
  375. $party_goods_count = $ptGoodsActivity['party_goods_count'];
  376. //当前商品拼团数据
  377. $pt_arr = PtActivityOrderDetail::find()->alias('pod')
  378. ->where(['store_id' => get_store_id(), 'pod.goods_id' => $goods->id])
  379. ->leftJoin(['po' => PtActivityOrder::tableName()], 'pod.order_id = po.id')
  380. ->andWhere(['po.pt_number' => 0, 'po.is_pay' => 1, 'po.is_pt_finish' => 0])
  381. ->select('po.id, po.pay_time')->orderBy('po.created_at desc')->asArray()->all();
  382. $arr = [];
  383. foreach ($pt_arr as $index => $item) {
  384. $arr[$index]['id'] = $item['id'];
  385. $end_time = ($item['pay_time'] + ($split_time * 60 * 60)) - time();
  386. $arr[$index]['end_time'] = $end_time > 0 ? $end_time : 0;
  387. $arr[$index]['user_list'] = PtActivityOrder::find()->alias('o')->where(['o.is_pay' => 1])
  388. ->leftJoin(['u' => User::tableName()], 'o.user_id = u.id')
  389. ->leftJoin(['su' => SaasUser::tableName()], 'u.binding = su.mobile')
  390. ->andWhere(['OR' , ['o.id' => $item['id']], ['o.pt_number' => $item['id']]])
  391. ->select('su.avatar, su.name')->limit(2)->asArray()->all();
  392. $arr[$index]['surplus_num'] = $party_size - count($arr[$index]['user_list']);
  393. $arr[$index]['party_type'] = $party_type;
  394. $arr[$index]['surplus_num_goods'] = 0;
  395. if($party_type == 1){
  396. $goodsCountQuery = PtActivityOrderDetail::find()->alias('pod')
  397. ->leftJoin(['po' => PtActivityOrder::tableName()], 'pod.order_id = po.id')
  398. ->where(['po.is_pay' => 1, 'pod.is_delete' => 0])
  399. ->andWhere(['OR' , ['po.id' => $item['id']], ['po.pt_number' => $item['id']]]);
  400. $goodsCount = $goodsCountQuery->sum('pod.num');
  401. $arr[$index]['surplus_num_goods'] = $party_goods_count - (int)$goodsCount;
  402. }
  403. }
  404. //拼团商品拼团数据
  405. $order_detail = PtActivityOrderDetail::find()->alias('pod')->where(['store_id' => get_store_id()])
  406. ->leftJoin(['po' => PtActivityOrder::tableName()], 'pod.order_id = po.id')
  407. ->andWhere(['po.pt_number' => 0, 'po.is_pay' => 1, 'po.is_pt_finish' => 0])
  408. ->select('pod.goods_id, pod.goods_name, pod.pic, pod.total_price pt_price, po.pay_time, pod.activity_id, po.user_id, po.id')
  409. ->orderBy('num desc')->asArray()->all();
  410. // $current_activity_num = count($order_detail);
  411. // $order_detail = $order_detail[0];
  412. $goods_activity = null;
  413. if ($order_detail) {
  414. foreach ($order_detail as $index => $value) {
  415. $activity = PtActivity::findOne($value['activity_id']);
  416. $goods_activity[$index]['name'] = $value['goods_name'];
  417. $goods_activity[$index]['cover_pic'] = $value['pic'];
  418. $saas_user = User::find()->alias('u')->leftJoin(['su' => SaasUser::tableName()], 'u.binding = su.mobile')
  419. ->select('su.name, su.avatar')->where(['u.id' => $value['user_id']])->asArray()->one();
  420. $goods_activity[$index]['avatar'] = $saas_user['avatar'];
  421. $goods_activity[$index]['end_time'] = 0;
  422. $goods_activity[$index]['pt_price'] = $value['pt_price'];
  423. if (($value['pay_time'] + ($activity->split_time * 60 * 60)) > time()) {
  424. $goods_activity[$index]['end_time'] = ($value['pay_time'] + ($activity->split_time * 60 * 60)) - time();
  425. }
  426. $goods_activity[$index]['goods_id'] = $value['goods_id'];
  427. $goods_activity[$index]['pt_number'] = $value['id'];
  428. }
  429. }
  430. //获取活动规则
  431. $aboutArticle = AboutArticle::findOne(['store_id' => get_store_id(), 'is_delete' => 0, 'type' => 1]);
  432. $pt_activity = [
  433. 'party_type' => (int)$party_type,
  434. 'is_join_pt' => (bool)$ptGoodsActivity,
  435. 'current_activity' => $arr,
  436. 'pt_price' => (string)$ptGoodsActivity['pt_price'],
  437. 'sale_num' => ((int)$ptGoodsActivity['sale_num'] + (int)$ptGoodsActivity['virtual_sales']),
  438. 'current_activity_num' => count($arr),
  439. 'goods_activity' => $goods_activity,
  440. 'rule' => $aboutArticle->desc ?? '',
  441. 'head_integral' => (int)$ptGoodsActivity['head_integral'],
  442. 'head_is_free' => (int)$ptGoodsActivity['head_is_free']
  443. ];
  444. } else {
  445. $pt_activity = null;
  446. }
  447. if($activityModel){
  448. $goods_attr = $activityModel['attr'];
  449. }else{
  450. $goods_attr = $goods->attr;
  451. if ($is_md && !in_array($goods->product_type, [4])) {
  452. $goods_attr = $md_goods->attr;
  453. }
  454. }
  455. if (!empty($ptGoodsActivity) && !empty($this->is_pt)) {
  456. $goods_attr = json_decode($goods_attr, true);
  457. $pt_attr = json_decode($ptGoodsActivity['attr'], true);
  458. if (!$goods->use_attr) {
  459. $goods_attr = [$goods_attr[0]];
  460. $pt_attr = [$pt_attr[0]];
  461. }
  462. foreach ($goods_attr as &$g_attr) {
  463. $g_attr_id = array_column($g_attr['attr_list'], 'attr_id');
  464. sort($g_attr_id);
  465. foreach ($pt_attr as $p_attr) {
  466. $p_attr_id = array_column($p_attr['attr_list'], 'attr_id');
  467. sort($p_attr_id);
  468. if (!array_diff($g_attr_id, $p_attr_id)) {
  469. $attr_name = $ptGoodsActivity['party_size'] . "人团";
  470. if($ptGoodsActivity['party_type'] == 1){
  471. $attr_name = $ptGoodsActivity['party_goods_count'] . "个商品成团";
  472. }
  473. $g_attr['attr_list'] = array_merge([
  474. [
  475. "attr_id" => -1,
  476. "attr_name" => $attr_name,
  477. ]
  478. ], $g_attr['attr_list']);
  479. $g_attr['price'] = $p_attr['pt_price'];
  480. }
  481. }
  482. }
  483. $last_names = array_column($pt_attr,'pt_price');
  484. array_multisort($last_names,SORT_DESC, $pt_attr);
  485. $pt_activity['pt_price'] = (string)($pt_attr[0]['pt_price']);
  486. $goods_attr = json_encode($goods_attr);
  487. }
  488. //配送时间展示
  489. $delivery_rules = DeliveryRules::find()->where(['id' => $goods->delivery_rules_id, 'is_delete' => 0, 'status' => 1])->select('id, times, type, days, name')->one();
  490. if ($delivery_rules) {
  491. $days = "下单" . $delivery_rules['days'] . "天后";
  492. $delivery_rules['times'] =
  493. (int)$delivery_rules['type'] === 1 ? $days : date("m月d日 H:i:s", $delivery_rules['times']);
  494. $delivery_rules['type'] .= '';
  495. }
  496. if($goods->goods_send_profit > 0 || $goods->goods_take_price > 0){
  497. $is_league = 1;
  498. }else{
  499. $is_league = 0;
  500. }
  501. // $send_profit_model = Option::findOne(['name' => 'store_send_profit']);//平台让利比例
  502. // $this_store_send_profit_model= Option::findOne(['name' => 'store_this_profit','store_id' => get_store_id()]);
  503. // if($this_store_send_profit_model->value > 0){
  504. // $basic_send_profit = $this_store_send_profit_model->value;
  505. // }else{
  506. // $basic_send_profit = $send_profit_model->value;
  507. // }
  508. // $basic_send_profit = (float)$basic_send_profit;
  509. $goods_send_profit = $goods->goods_send_profit * 0.01;
  510. $goods_take_profit = $goods->goods_take_price * 0.01;
  511. if($goods->product_type == Goods::GOODS_TYPE_VIEW && $this->mini_id){
  512. $aweme_id = \app\utils\Douyin\DouyinMini::query_aweme_user_bind_ok($this->mini_id);
  513. }
  514. $activityOrderRebateSelf = \app\models\ActivityOrderRebateSelf::activityAt($goods->store_id, $goods->id);
  515. //需要判断当前商品是否是排队免单商品
  516. $cashback_bili = 0;
  517. $is_queue = 0;
  518. $single_price = 0;
  519. $single_bili = 0;
  520. $queue_goods = FreeQueueGoods::find()->where(['goods_id' => $goods->id, 'is_delete' => 0,'store_id' => $goods->store_id])->one();
  521. if ($queue_goods) {
  522. $is_queue = 1;
  523. $queue_free = FreeQueue::find()->where(['id'=>$queue_goods->activity_id])->one();
  524. $cashback_bili = $queue_free->cashback_bili;
  525. if($queue_free->cashback_type){
  526. $cashback_bili = $goodsPrice <= 0 ? 0 : ($queue_free->cashback_money * $queue_free->cashback_money_bili / 100) / $goodsPrice * 100;
  527. }
  528. $single_bili = $goods->queue_rate > 0 ? $goods->queue_rate : $queue_free->single_bili;
  529. $single_price = round($goodsPrice * $cashback_bili /100 * $single_bili /100,2);
  530. }
  531. $is_show_alliance_coupon = \app\models\Option::get('is_show_alliance_coupon', get_store_id(), 'store', 0)['value'];
  532. $goods_integral = json_decode($goods->integral, true) ?: ['give' => 0, 'forehead' => 0, 'forehead_integral' => 0];
  533. // if ($goods_integral['give'] == 0) {
  534. // $goods_integral['give'] = Option::get(OptionSetting::SEND_INTEGRAL_PROFIT, $goods->store_id, 'store', 0)['value'];
  535. // }
  536. $materialId = 0;
  537. if(in_array('material',\yii::$app->getAttr('plugin')['store'])){
  538. $material = Material::find()->where(['goods_id' => $goods->id,'status'=>1])->andWhere(['OR', ['delete_time' => 0], ['IS', 'delete_time', NULL]])->orderBy('is_top DESC,create_time DESC')->one();
  539. if($material){
  540. $materialId = $material->id;
  541. }
  542. }
  543. $data = array_merge($goods->attributes, [
  544. 'goods' => $goods,
  545. 'is_queue'=>$is_queue,
  546. 'cashback_bili'=>round($cashback_bili, 2),
  547. 'single_price'=>$single_price,
  548. 'single_bili'=>$single_bili,
  549. 'activityOrderRebateSelf' => $activityOrderRebateSelf,
  550. 'aweme_id' => $aweme_id ?? '',
  551. 'cutGoods' => $cutGoods,
  552. 'activityWechatRoom' => $activityWechatRoom,
  553. 'activityPrice' => sprintf('%.2f', $goods->activityPrice),
  554. 'id' => $goods->id,
  555. 'is_league' => $is_league,
  556. 'goods_send_profit' => $goods_send_profit,
  557. 'goods_take_profit' => $is_show_alliance_coupon ? $goods_take_profit : 0,
  558. 'status' => $goods->status,
  559. 'pic_list' => $pic_list,
  560. 'attr' => $goods_attr,
  561. 'cover_pic' => $goods->cover_pic,
  562. 'is_negotiable' => $goods->is_negotiable,
  563. 'max_price' => sprintf('%.2f', max($price)),
  564. 'min_price' => $min_price,
  565. 'name' => $goods->name,
  566. 'sub_name' => $goods->sub_name ?: '',
  567. 'cat_id' => $goods->cat_id,
  568. 'price' => sprintf('%.2f', $goodsPrice),
  569. 'detail' => $goods->detail,
  570. 'sales' => $goods->getSalesVolume() + ($is_md ? $md_goods->virtual_sales : $goods->virtual_sales),
  571. 'attr_group_list' => $goods->getAttrGroupList($this->is_pt, $goods->use_attr),
  572. 'num' => $goods->getNum(),
  573. 'goods_num' => $goods->getNum(),
  574. 'is_favorite' => $is_favorite,
  575. 'service_list' => $new_service_list,
  576. 'original_price' => sprintf('%.2f', $goods->original_price),
  577. 'video_url' => $goods->video_url,
  578. 'unit' => $goods->unit,
  579. 'use_attr' => $this->is_pt ? 1 : intval($goods->use_attr),
  580. 'mch' => $mch,
  581. 'max_share_price' => sprintf('%.2f', $res['max_share_price']),
  582. 'min_member_price' => sprintf('%.2f', $res['min_member_price']),
  583. 'is_share' => $res['is_share'],
  584. 'is_level' => $res['is_level'],
  585. 'is_member_price' => $isMemberPrice,
  586. 'full_minus' => $GoodsFullMinus,
  587. 'verify_card_id' => $verify_card,
  588. 'goods_share_title' => $goods->goods_share_title,
  589. 'goods_share_desc' => $goods->goods_share_desc,
  590. 'goods_share_logo' => $goods->goods_share_logo,
  591. 'product_type' => $goods->product_type,
  592. 'confine_count' => $goods->confine_count ?: 0,
  593. 'integral' => $goods_integral,
  594. 'integral_price' => $goods->integral_price,
  595. 'delivery_rules' => $delivery_rules ?: null,
  596. 'seckill_activity_arr' => $seckill_activity_arr ?: null,
  597. 'next_level' => $level,
  598. 'pt_activity' => $pt_activity,
  599. 'parameter_list' =>json_decode($goods->parameter_list, true),
  600. 'accessories_image_status' => empty($goods->accessories_image) ? 0 : 1,
  601. // 商品所挂接的素材ID
  602. 'material_id' => $materialId
  603. ]);
  604. //分销最高可赚
  605. //获取商品中最大金额
  606. $attr = json_decode($goods->attr, true);
  607. $price_arr = array_column($attr, 'price');
  608. $max_price = max($price_arr);
  609. //获取会员价
  610. $user_level = get_user()->level;
  611. $level = Level::findOne(['store_id' => get_store_id(), 'level' => $user_level]);
  612. $discount = 10;
  613. if ($level) {
  614. $discount = $level->discount;
  615. }
  616. $level_price = $max_price * ($discount / 10);
  617. if ($user_level > 0) {
  618. $price_arr = array_column($attr, 'member_' . $user_level);
  619. $min_level_price = is_array($price_arr) ? floatval(min($price_arr ?: [$level_price])) : $level_price;
  620. if ($min_level_price > 0) {
  621. $level_price = $min_level_price;
  622. }
  623. }
  624. //获取分销配置
  625. $share_setting = Option::get('share_basic_setting', get_store_id());
  626. $share_setting = $share_setting ? Json::decode($share_setting['value']) : [];
  627. $rebate = 0;
  628. //判断是否开启三级分销且自购返利
  629. // if (!isset($share_setting['is_rebate']['value']) || (isset($share_setting['is_rebate']['value']) && $share_setting['is_rebate']['value'] >= 1)) {// && get_user()->is_distributor == 1
  630. $share_commission_money_first = 0;
  631. //获取最高分销比例
  632. $rebate = $this->getShareCommissionMoney($goods, get_user_id());
  633. // $setting_shara = Option::get('share_money_setting', get_store_id(), 'share');
  634. // $setting_shara = $setting_shara ? Json::decode($setting_shara['value']) : [];
  635. // $rate_first = doubleval($setting_shara['level_one']['value']);
  636. // if ($rate_first > 0) {
  637. // //计算比例
  638. // $share_commission_money_first += ($level_price * $rate_first / 100);
  639. // $rebate = sprintf("%.2f",$share_commission_money_first < 0.01 ? 0 : $share_commission_money_first);
  640. // }
  641. // }
  642. $data['rebate'] = floatval(sprintf('%.2f', $rebate));
  643. if ($data['integral']['forehead'] > 0) {
  644. $store_integral = Option::get(OptionSetting::STORE_INTEGRAL, get_store_id(), 'gift', Option::get(OptionSetting::STORE_INTEGRAL, get_store_id(), 'store')['value'])['value'];
  645. $data['integral']['forehead_integral'] = round($store_integral * $data['integral']['forehead']);
  646. }
  647. if ($data['integral']['give'] <= 0) {
  648. $send_integral_profit = Option::get(OptionSetting::SEND_INTEGRAL_PROFIT, get_store_id(), 'gift', Option::get(OptionSetting::SEND_INTEGRAL_PROFIT, get_store_id(), 'store')['value'])['value'];
  649. if ($send_integral_profit > 0) {
  650. $data['integral']['give'] = (int)(floatval($data['price']) * ($send_integral_profit / 100));
  651. }
  652. }
  653. // 处理app上不显示没加协议的图片
  654. $data['detail'] = str_replace('src="//', 'src="https://', $data['detail']);
  655. $now_date = strtotime(date('Y-m-d'));
  656. $goods_book = GoodsBook::findOne(['goods_id' => $goods->id]);
  657. // 预约参数配置
  658. if ($data['product_type'] == Goods::GOODS_TYPE_DATE) {
  659. $data['num'] = Goods::getGoodsNum($goods)['data'];
  660. $data['date_book'] = [
  661. 'date_book' => $data['num'] ,
  662. 'date' => count($data['num'])
  663. ];
  664. if ($goods_book && !empty($goods_book->date_book)) {
  665. $date_book = Json::decode($goods_book->date_book);
  666. $count = 0;
  667. foreach ($date_book as $value) {
  668. if (strtotime($value['date']) >= $now_date) {
  669. $count++;
  670. }
  671. }
  672. // if ($count <= 0) {
  673. // return [
  674. // 'code' => 1,
  675. // 'msg' => '商品预约数据不存在'
  676. // ];
  677. // }
  678. $data['date_book'] = [
  679. 'date_book' => $date_book,
  680. 'date' => count($date_book)
  681. ];
  682. } else {
  683. // return [
  684. // 'code' => 1,
  685. // 'msg' => '该商品暂无可预约数据'
  686. // ];
  687. }
  688. }
  689. if ($data['product_type'] == Goods::GOODS_TYPE_TIME) {
  690. if ($goods_book && !empty($goods_book->service_book)) {
  691. $new_arr = $this->goodsBookingTime($goods['id'], 7);
  692. $data['service_book'] = $new_arr;
  693. } else {
  694. return [
  695. 'code' => 1,
  696. 'msg' => '商品服务预约配置有误'
  697. ];
  698. }
  699. }
  700. $data['givingGifts'] = GivingGiftsForm::isopenGoods($goods['store_id'], $goods['id']) ? 1 : 0;
  701. $ProductBatch = ProductBatch::find()->where(['goods_id' => $goods->id, 'is_delete' => 0, 'state' => 1])->one();
  702. $data['have_product_traceability'] = $ProductBatch ? 1 : 0;
  703. $data['product_batch_id'] = $ProductBatch ? $ProductBatch->id : 0;
  704. $ruleBuyerLoc = \app\models\OrderRulesBuyerLocation::findOne($goods->order_rules_buyer_location_id);
  705. $data['order_rules_buyer_location'] = $ruleBuyerLoc;
  706. /* begin 2024/03/13 11:36:22 降价通知订阅消息相关 WPing丶 */
  707. $data['template_id'] = NoticeAction::getSendTamplateId(['lowering_price']);
  708. $data['is_lowering'] = GoodsLoweringPrice::find()->where(['user_id' => get_user_id(), 'goods_id' => $goods->id, 'store_id' => get_user_id(), 'is_delete' => 0])->exists();//判断当前用户是否订阅此商品的降价通知
  709. /* end */
  710. $goodsInfo = new Goods();
  711. $goodsInfo->id = $goods->id;
  712. //前端显示最近购买这个产品用户的头像
  713. $data['recently_purchased_user_info'] = [
  714. 'user_list' => [],
  715. 'sales_volume' => $goodsInfo->getSalesVolume()
  716. ];
  717. $limit = 10;
  718. $virtual_sales = $is_md ? $md_goods->virtual_sales : $goods->virtual_sales;
  719. if ($virtual_sales > 0) {
  720. $data['recently_purchased_user_info']['sales_volume'] = $virtual_sales;
  721. if ($limit > $virtual_sales) {
  722. $limit = $virtual_sales;
  723. }
  724. } else {
  725. if ($data['recently_purchased_user_info']['sales_volume'] <= 10) {
  726. $limit = $data['recently_purchased_user_info']['sales_volume'];
  727. }
  728. }
  729. $data['recently_purchased_user_info']['user_list'] = OrderDetail::find()->alias('od')
  730. ->leftJoin(['o' => Order::tableName()], 'od.order_id = o.id')
  731. ->leftJoin(['u' => User::tableName()], 'o.user_id = u.id')
  732. ->leftJoin(['su' => SaasUser::tableName()], 'su.mobile = u.binding')
  733. ->where(['od.goods_id' => $goods->id, 'od.is_delete' => 0, 'o.is_pay' => 1,
  734. 'o.trade_status' => [
  735. Order::ORDER_FLOW_NO_SEND,
  736. Order::ORDER_FLOW_SEND,
  737. Order::ORDER_FLOW_CONFIRM
  738. ]])->groupBy('o.user_id')->orderBy('o.id desc')->select('su.avatar')->limit($limit)->column();
  739. if ($virtual_sales <= 0 && empty($data['recently_purchased_user_info']['user_list'])) {
  740. $limit = 0;
  741. }
  742. if (count($data['recently_purchased_user_info']['user_list']) < $limit) {
  743. $limit = $limit - count($data['recently_purchased_user_info']['user_list']);
  744. $data['recently_purchased_user_info']['user_list'] = array_merge($data['recently_purchased_user_info']['user_list'], SaasUser::find()
  745. ->where(['AND', ['<>', 'avatar', ''], ['IS NOT', 'avatar', null], ['NOT LIKE', 'avatar', 'avatar.png']])
  746. ->orderBy(new \yii\db\Expression("RAND()"))
  747. ->select('avatar')->limit($limit)->column());
  748. }
  749. //是否是增值积分商品
  750. $integralAppreciationGoods = IntegralAppreciationGoods::findOne(['goods_id' => $goods->id, 'is_delete' => 0]);
  751. $data['is_integral_appreciation_goods'] = $integralAppreciationGoods ? 1 : 0;
  752. $data['reflux_amount'] = $integralAppreciationGoods->reflux_amount ?: '0.00';
  753. $res = [
  754. 'code' => 0,
  755. 'data' => $data
  756. ];
  757. $sqlDependency = new \yii\caching\DbDependency(['sql'=>Goods::find()->where(['id' => $this->id])->select('updated_at')->createCommand()->getRawSql()]);
  758. if (empty($pt_activity) || empty($this->activity_cut_price_id)) {
  759. cache()->set($cacheKey, $res, 600, $sqlDependency);
  760. }
  761. return $res;
  762. }
  763. public function getShareCommissionMoney($goods, $user_id) {
  764. $goods = Goods::findOne($goods->id);
  765. $store_id = $goods->store_id;
  766. $share = Share::findOne(['user_id' => $user_id, 'status' => Share::SHARE_AUDIT_PASS, 'is_delete' => Share::SHARE_NOT_DELETE]);
  767. $share_commission_money = 0;
  768. $attr = json_decode($goods->attr, true);
  769. $last_names = array_column($attr, 'price');
  770. array_multisort($last_names, SORT_DESC, $attr);
  771. $max_attr = $attr[0];
  772. if ($share) {
  773. $share_level_id = $share->level;
  774. $share_level = ShareLevel::findOne(['level' => $share_level_id, 'store_id' => $store_id, 'is_delete' => ShareLevel::SHARE_NOT_DELETE,
  775. 'status' => ShareLevel::STATUS_ON]);
  776. if(ActivityRebateOrderN::passBaseRebate($store_id, $goods->id)){
  777. return 0;
  778. }
  779. // TODO: 价格
  780. $item_price = doubleval($max_attr['price']);
  781. // $item_price = doubleval($orderShare->pay_price);
  782. //
  783. $rate_first = 0;
  784. //商品开启独立分销
  785. if ($goods->individual_share == 1) {
  786. $share_commission = $this->goodsAttrSettingType($goods, $share_level_id);
  787. $current_rebate_price = 0;
  788. foreach ($share_commission as $share_c_index => $share_c_item) {
  789. if ($current_rebate_price === 0 || $current_rebate_price < $share_c_item['share_commission_level_' . $share_level_id] ?? 0) {
  790. $current_rebate_price = $share_c_item['share_commission_level_' . $share_level_id] ?? 0;
  791. }
  792. }
  793. $rate_first = $current_rebate_price;
  794. $shareType = $goods->share_type;
  795. } else {
  796. $setting_shara = Option::get('share_money_setting', $store_id, 'share');
  797. $setting_shara = $setting_shara ? Json::decode($setting_shara['value']) : [];
  798. $rate_first = $share_level->first_profit ?? ($setting_shara['level_one']['value'] ?? 0);
  799. if ($rate_first < $share_level->second_profit ?? ($setting_shara['level_two']['value'] ?? 0)) {
  800. $rate_first = $share_level->second_profit ?? ($setting_shara['level_two']['value'] ?? 0);
  801. }
  802. if ($rate_first < $share_level->third_profit ?? ($setting_shara['level_three']['value'] ?? 0)) {
  803. $rate_first = $share_level->third_profit ?? ($setting_shara['level_three']['value'] ?? 0);
  804. }
  805. if ($share_level) {
  806. $shareType = intval($share_level->profit_type);
  807. } else {
  808. $shareType = 0;
  809. }
  810. }
  811. if ($shareType == 1) { // 金钱
  812. $share_commission_money += $rate_first ;
  813. } else { // 比例
  814. $share_commission_money += $item_price * $rate_first / 100;
  815. }
  816. return sprintf("%.2f", $share_commission_money < 0.01 ? 0 : $share_commission_money);
  817. }
  818. return 0;
  819. }
  820. //获取商品详细模式下的佣金最高可得
  821. private function goodsAttrSettingType($goods, $share_level) {
  822. $goods = Goods::findOne($goods->id);
  823. if ($goods->attr_setting_type) {
  824. $attr = json_decode($goods->attr, true);
  825. $share_commission_level = 'share_commission_level_' . $share_level;
  826. $current_attr_max_rebate_price = 0;
  827. $current_attr = [];
  828. foreach ($attr as $attr_item) {
  829. if (empty($current_attr)) {
  830. $current_attr = $attr_item;
  831. }
  832. if (isset($attr_item['share_commission_new_first'][$share_commission_level])) {
  833. $current_attr_rebate_price = bcmul($attr_item['price'], $attr_item['share_commission_new_first'][$share_commission_level], 2);
  834. if ($current_attr_rebate_price > $current_attr_max_rebate_price) {
  835. $current_attr_max_rebate_price = $current_attr_rebate_price;
  836. $current_attr = $attr_item;
  837. }
  838. }
  839. if (isset($attr_item['share_commission_new_second'][$share_commission_level])) {
  840. $current_attr_rebate_price = bcmul($attr_item['price'], $attr_item['share_commission_new_second'][$share_commission_level], 2);
  841. if ($current_attr_rebate_price > $current_attr_max_rebate_price) {
  842. $current_attr_max_rebate_price = $current_attr_rebate_price;
  843. $current_attr = $attr_item;
  844. }
  845. }
  846. if (isset($attr_item['share_commission_new_third'][$share_commission_level])) {
  847. $current_attr_rebate_price = bcmul($attr_item['price'], $attr_item['share_commission_new_third'][$share_commission_level], 2);
  848. if ($current_attr_rebate_price > $current_attr_max_rebate_price) {
  849. $current_attr_max_rebate_price = $current_attr_rebate_price;
  850. $current_attr = $attr_item;
  851. }
  852. }
  853. }
  854. return [
  855. 'share_commission_new_first' => $current_attr['share_commission_new_first'],
  856. 'share_commission_new_second' => $current_attr['share_commission_new_second'],
  857. 'share_commission_new_third' => $current_attr['share_commission_new_third'],
  858. ];
  859. } else {
  860. $share_commission_new_first = json_decode($goods->share_commission_new_first, true);
  861. $share_commission_new_second = json_decode($goods->share_commission_new_second, true);
  862. $share_commission_new_third = json_decode($goods->share_commission_new_third, true);
  863. return [
  864. 'share_commission_new_first' => $share_commission_new_first,
  865. 'share_commission_new_second' => $share_commission_new_second,
  866. 'share_commission_new_third' => $share_commission_new_third,
  867. ];
  868. }
  869. }
  870. // public function activity_cut_price($activity_cut_price_id, &$goods, &$md_goods = null) {
  871. // //展示活动商品信息
  872. // if($activity_cut_price_id){
  873. // $activityAt = ActivityCutPrice::activityAt($activity_cut_price_id);
  874. // $goods_ext = ActivityCutPriceGoods::findOne(['activity_id' => $activity_cut_price_id, 'goods_id' => $goods->id, 'is_delete' => 0]);
  875. // //商品属于当前进行中活动
  876. // if($activityAt && $activityAt->id == $activity_cut_price_id && $goods_ext){
  877. // $goods->virtual_sales += $goods_ext->virtual_sales;
  878. // $md_goods && $md_goods->virtual_sales += $goods_ext->virtual_sales;
  879. // if($goods_ext->price){
  880. // $goods->price = $goods_ext->price;
  881. // $md_goods && $md_goods->price = $goods_ext->price;
  882. // }
  883. // $ext_attrs = json_decode($goods_ext->attr, true);
  884. // $attrs = json_decode($goods->attr, true);
  885. // if($md_goods){
  886. // $md_attrs = json_decode($md_goods->attr, true);
  887. // }
  888. // foreach($ext_attrs as $ext_attr){
  889. // $ext_attr_list = json_encode($ext_attr['attr_list']);
  890. // foreach($attrs as &$attr){
  891. // $attr_list = json_encode($attr['attr_list']);
  892. // if($attr_list == $ext_attr_list){
  893. // $attr['price'] = $ext_attr['price'];
  894. // $attr['num'] = $ext_attr['num'];
  895. // }
  896. // }
  897. // if($md_goods){
  898. // foreach($md_attrs as &$md_attr){
  899. // $md_attr_list = json_encode($md_attr['attr_list']);
  900. // if($md_attr_list == $ext_attr_list){
  901. // $md_attr['price'] = $ext_attr['price'];
  902. // $md_attr['num'] = $ext_attr['num'];
  903. // }
  904. // }
  905. // }
  906. // }
  907. // $goods->attr = json_encode($attrs);
  908. // $md_goods && $md_goods->attr = json_encode($md_attrs);
  909. // }
  910. // }
  911. // }
  912. public function activity_new_user($activity_new_user_id, &$goods, &$md_goods = null) {
  913. // $activityAt = ActivityNewUser::activityAt($goods->store_id);
  914. // $activityAt && $this->activity_new_user_id = $activityAt->id;
  915. //展示活动商品信息
  916. $activityAt = ActivityNewUser::activityAt($goods->store_id);
  917. if ($activityAt) {
  918. $goods_ext = ActivityNewUserGoods::findOne(['activity_id' => $activityAt->id, 'goods_id' => $goods->id, 'is_delete' => 0]);
  919. //商品属于当前进行中活动
  920. if($goods_ext){
  921. if($goods_ext->price){
  922. $goods->price = $goods_ext->price;
  923. $md_goods && $md_goods->price = $goods_ext->price;
  924. }
  925. $ext_attrs = json_decode($goods_ext->attr, true);
  926. $attrs = json_decode($goods->attr, true);
  927. if($md_goods){
  928. $md_attrs = json_decode($md_goods->attr, true);
  929. }
  930. foreach($ext_attrs as $ext_attr){
  931. $ext_attr_list = json_encode($ext_attr['attr_list']);
  932. foreach($attrs as &$attr){
  933. $attr_list = json_encode($attr['attr_list']);
  934. if($attr_list == $ext_attr_list){
  935. $attr['price'] = $ext_attr['price'];
  936. }
  937. }
  938. if($md_goods){
  939. foreach($md_attrs as &$md_attr){
  940. $md_attr_list = json_encode($md_attr['attr_list']);
  941. if($md_attr_list == $ext_attr_list){
  942. $md_attr['price'] = $ext_attr['price'];
  943. }
  944. }
  945. }
  946. }
  947. $goods->attr = json_encode($attrs);
  948. $md_goods && $md_goods->attr = json_encode($md_attrs);
  949. }
  950. }
  951. }
  952. public function activity_wechat_room(&$goods, &$md_goods = null) {
  953. if($this->is_pt || $this->is_seckill || $this->activity_new_user_id || $this->activity_cut_price_id){
  954. return null;
  955. }
  956. $goods_ext = null;
  957. $activityAt = ActivityWechatRoom::activityAtByGoodsId($goods->id, $goods_ext);
  958. //展示活动商品信息
  959. if ($activityAt) {
  960. $inRoom = false;
  961. if($this->user_id){
  962. $wechatRoomIds = explode(',', $activityAt['wechat_room_id']);
  963. foreach($wechatRoomIds as $roomId){
  964. if(\app\modules\admin\models\mochat\MochatForm::userInRoom($this->store_id, $roomId, $this->user_id)){
  965. $inRoom = true;
  966. break;
  967. }
  968. }
  969. }
  970. $activityAt['inRoom'] = $inRoom;
  971. $activityAt['inTime'] = $activityAt['end_time'] - time();
  972. $minPrice = $goods->price;
  973. //商品属于当前进行中活动
  974. if($goods_ext){
  975. // if($goods_ext->price){
  976. // $goods->price = $goods_ext->price;
  977. // $md_goods && $md_goods->price = $goods_ext->price;
  978. // }
  979. $ext_attrs = json_decode($goods_ext->attr, true);
  980. $attrs = json_decode($goods->attr, true);
  981. if($md_goods){
  982. $md_attrs = json_decode($md_goods->attr, true);
  983. }
  984. foreach($ext_attrs as $ext_attr){
  985. $ext_attr_list = json_encode($ext_attr['attr_list']);
  986. foreach($attrs as &$attr){
  987. $attr_list = json_encode($attr['attr_list']);
  988. if($attr_list == $ext_attr_list){
  989. $attr['price'] = $ext_attr['price'];
  990. $minPrice = $attr['price'] < $minPrice ? $attr['price'] : $minPrice;
  991. }
  992. }
  993. if($md_goods){
  994. foreach($md_attrs as &$md_attr){
  995. $md_attr_list = json_encode($md_attr['attr_list']);
  996. if($md_attr_list == $ext_attr_list){
  997. $md_attr['price'] = $ext_attr['price'];
  998. $minPrice = $md_attr['price'] < $minPrice ? $md_attr['price'] : $minPrice;
  999. }
  1000. }
  1001. }
  1002. }
  1003. $goods->attr = json_encode($attrs);
  1004. $md_goods && $md_goods->attr = json_encode($md_attrs);
  1005. }
  1006. }
  1007. $goods->activityPrice = $minPrice;
  1008. $md_goods && $md_goods->activityPrice = $minPrice;
  1009. return $activityAt;
  1010. }
  1011. // 快速给购买商品
  1012. public function quickGoods($twocatid)
  1013. {
  1014. $goods = Goods::find()
  1015. ->where([
  1016. 'store_id' => $this->store_id,
  1017. 'is_delete' => 0,
  1018. 'status' => 1,
  1019. 'quick_purchase' => 1
  1020. ])
  1021. ->andWhere([
  1022. 'in', 'cat_id', $twocatid
  1023. ])->asArray()
  1024. ->all();
  1025. foreach ($goods as $key => &$value) {
  1026. $value['attr'] = json_decode($value['attr']);
  1027. foreach ($value['attr'] as $key2 => $value2) {
  1028. foreach ($value2->attr_list as $key3 => $value3) {
  1029. $value['attr_name'] = $value3->attr_name;
  1030. }
  1031. $value['num'] = 0;
  1032. }
  1033. }
  1034. return [
  1035. 'code' => 0,
  1036. 'data' => [
  1037. 'list' => $goods,
  1038. ],
  1039. ];
  1040. }
  1041. /**
  1042. * 获取优惠详情
  1043. */
  1044. public function getYouhui()
  1045. {
  1046. if (!$this->validate()) {
  1047. return $this->getErrorSummary(false)[0];
  1048. }
  1049. $data = [];
  1050. $goods = Goods::findOne($this->id);
  1051. // 是否赠送积分
  1052. // $integral = json_decode($goods->integral, true);
  1053. // if ($integral['give'] > 0) {
  1054. // $data[] = [
  1055. // 'name' => '赠送积分',
  1056. // 'content' => '购买赠送' . $integral['give'] . '积分'
  1057. // ];
  1058. // }
  1059. // if ($integral['forehead'] > 0) {
  1060. // $data[] = [
  1061. // 'name' => '积分抵扣',
  1062. // 'content' => '最高可抵扣' . $integral['forehead'] . '元'
  1063. // ];
  1064. // }
  1065. $goods_card = Goods::getGoodsCard($goods->id);
  1066. foreach ($goods_card as $card) {
  1067. $data[] = [
  1068. 'name' => '卡券',
  1069. 'content' => $card['name']
  1070. ];
  1071. }
  1072. // 核销卡列表获取
  1073. // 获取商品已添加核销卡
  1074. if (empty($goods->verify_card_id)) {
  1075. $goods_verify_card_list = [];
  1076. } else {
  1077. $verify_cards = explode(',', $goods['verify_card_id']);
  1078. foreach ($verify_cards as $k => $v) {
  1079. $verifyCard = VerifyCard::find()->select(['id', 'name'])->where(['id' => $v, 'is_delete' => 0])->asArray()->one();
  1080. if ($verifyCard) {
  1081. $goods_verify_card_list[] = $verifyCard;
  1082. }
  1083. }
  1084. }
  1085. foreach ((array)$goods_verify_card_list as $verify) {
  1086. $data[] = [
  1087. 'name' => '核销卡',
  1088. 'content' => $verify['name']
  1089. ];
  1090. }
  1091. $coupon_list = Coupon::getList($goods->mch_id);
  1092. $coupon_list_res = [];
  1093. foreach ($coupon_list as $coupon) {
  1094. if ($coupon['appoint_type'] !== 3) {
  1095. if ($coupon['appoint_type'] == 0) {
  1096. $coupon_list_res[] = $coupon;
  1097. } else {
  1098. if ($coupon['appoint_type'] == 2) {
  1099. $goods_id_arr = array_column($coupon['goods'], 'id');
  1100. if (in_array($goods->id, $goods_id_arr) || empty($goods_id_arr)) {
  1101. $coupon_list_res[] = $coupon;
  1102. }
  1103. } else {
  1104. if ($coupon['appoint_type'] == 1) {
  1105. $cat_list = GoodsCat::find()->where([
  1106. 'goods_id' => $goods->id,
  1107. 'is_delete' => 0,
  1108. 'store_id' => get_store_id()
  1109. ])->all();
  1110. $cat_id_arr = array_column($coupon['cat'], 'id');
  1111. if (empty($cat_id_arr)) {
  1112. $coupon_list_res[] = $coupon;
  1113. } else {
  1114. foreach ($cat_list as $cat) {
  1115. if (in_array($cat->cat_id, $cat_id_arr) || empty($cat_id_arr)) {
  1116. $coupon_list_res[] = $coupon;
  1117. break;
  1118. }
  1119. }
  1120. }
  1121. }
  1122. }
  1123. }
  1124. }
  1125. }
  1126. $dataRes = [
  1127. 'data' => $data,
  1128. 'coupon' => $coupon_list_res
  1129. ];
  1130. return [
  1131. 'code' => 0,
  1132. 'data' => $dataRes
  1133. ];
  1134. }
  1135. /**
  1136. * @description: 获取商品收货地址
  1137. * @param {*}
  1138. * @return {*}
  1139. */
  1140. public function getAddress()
  1141. {
  1142. if ($this->address_id) {
  1143. $query = Address::find()->where(['store_id' => get_store_id(), 'is_delete' => 0, 'id' => $this->address_id]);
  1144. if (is_platform()) {
  1145. $address = $query->andWhere([
  1146. 'user_id' => get_saas_user_id()
  1147. ])->one();
  1148. } else {
  1149. $address = $query->andWhere([
  1150. 'user_id' => get_user_id()
  1151. ])->one();
  1152. }
  1153. } else {
  1154. $query = Address::find()->where(['store_id' => get_store_id(), 'is_delete' => 0]);
  1155. if (is_platform()) {
  1156. $query->andWhere([
  1157. 'user_id' => get_saas_user_id()
  1158. ]);
  1159. } else {
  1160. $query->andWhere([
  1161. 'user_id' => get_user_id()
  1162. ]);
  1163. }
  1164. $address = $query->orderBy(['is_default' => SORT_DESC])->one();
  1165. }
  1166. $goods = Goods::findOne($this->id);
  1167. // 计算运费
  1168. $express_price = $this->getExpressPrice($address, $goods);
  1169. // 计算区域限制购买
  1170. $is_area = $this->getTerritorialLimitation($address, $goods);
  1171. $shop_id = null;
  1172. $shop = null;
  1173. if ($this->shop_id) {
  1174. $shop_id = $this->shop_id;
  1175. } else {
  1176. $order = Order::find()->where([
  1177. 'is_offline' => 1,
  1178. 'user_id' => get_user_id()
  1179. ])->orderBy(['id' => SORT_DESC])->one();
  1180. if ($order) {
  1181. $shop_id = $order->shop_id;
  1182. }
  1183. }
  1184. if ($shop_id) {
  1185. $shop = Shop::findOne($shop_id);
  1186. }
  1187. return [
  1188. 'code' => 0,
  1189. 'data' => [
  1190. 'address' => $address,
  1191. 'shop' => $shop,
  1192. 'express_price' => $express_price,
  1193. 'is_area' => $is_area
  1194. ]
  1195. ];
  1196. }
  1197. /**
  1198. * 门店推荐
  1199. */
  1200. public function mchRecommend()
  1201. {
  1202. $goods_list = Goods::find()->where([
  1203. 'mch_id' => $this->mch_id,
  1204. 'status' => 1,
  1205. 'is_delete' => 0
  1206. ])->orderBy(['sort' => SORT_ASC])
  1207. ->select(['id', 'name', 'cover_pic', 'price'])->limit(6)->all();
  1208. return [
  1209. 'code' => 0,
  1210. 'data' => [
  1211. 'list' => $goods_list
  1212. ]
  1213. ];
  1214. }
  1215. /**
  1216. * 猜你喜欢
  1217. */
  1218. public function guessLike()
  1219. {
  1220. $cat_list = GoodsCat::find()->where(['goods_id' => $this->id, 'is_delete' => 0])->all();
  1221. $cat_id = [];
  1222. foreach ($cat_list as $val) {
  1223. $cat_id[] = $val->cat_id;
  1224. }
  1225. $goods_list = Goods::find()->alias('g')
  1226. ->leftJoin(['gc' => GoodsCat::tableName()], 'gc.goods_id=g.id')
  1227. ->where([
  1228. 'g.status' => 1,
  1229. 'g.is_delete' => 0,
  1230. 'gc.cat_id' => $cat_id
  1231. ])->orderBy(['g.sort' => SORT_DESC])
  1232. ->select(['g.id', 'g.name', 'g.cover_pic', 'g.price'])->groupBy('gc.goods_id')->limit(6)->all();
  1233. return [
  1234. 'code' => 0,
  1235. 'data' => [
  1236. 'list' => $goods_list
  1237. ]
  1238. ];
  1239. }
  1240. /**
  1241. * 计算单个商品的运费
  1242. */
  1243. protected function getExpressPrice($address, $goods)
  1244. {
  1245. $expressPrice = 0;
  1246. if ($address) {
  1247. //再通过运费规则计算运费
  1248. $expressPrice = PostageRules::getExpressPrice($goods->store_id, $address->city_id, $goods, 1, $address->province_id);
  1249. }
  1250. return $expressPrice >= 0 ? $expressPrice : 0;
  1251. }
  1252. /**
  1253. * 计算单个商品是否区域限制购买
  1254. */
  1255. protected function getTerritorialLimitation($address, $goods)
  1256. {
  1257. $isArea = 0;
  1258. if ($address) {
  1259. $area = TerritorialLimitation::findOne([
  1260. 'store_id' => get_store_id(),
  1261. 'is_delete' => 0,
  1262. 'is_enable' => 1,
  1263. ]);
  1264. if ($area) {
  1265. $city_id = []; //限制的地区ID
  1266. $detail = json_decode($area->detail);
  1267. if (!is_array($detail)) {
  1268. $detail = [];
  1269. }
  1270. foreach ($detail as $key => $value) {
  1271. foreach ($value->province_list as $key2 => $value2) {
  1272. $city_id[] = $value2->id;
  1273. }
  1274. }
  1275. $addressArr = [
  1276. $address['province_id'],
  1277. $address['city_id'],
  1278. $address['district_id']
  1279. ];
  1280. $addressArray = array_intersect($addressArr, $city_id);
  1281. if (empty($addressArray)) {
  1282. $isArea = 1;
  1283. }
  1284. }
  1285. }
  1286. return $isArea;
  1287. }
  1288. /**
  1289. * User: chiyanying
  1290. * Date: 2020/9/27
  1291. * Time: 17:27
  1292. * Notes:获取单个商品信息
  1293. */
  1294. public static function getGoods($goods_id = 0, $tore_id = 0, $type = 0)
  1295. {
  1296. if ($type == 0) {
  1297. $form = new GoodsForm();
  1298. $form->id = $goods_id;
  1299. $form->store_id = $tore_id;
  1300. return $form->search()['data'];
  1301. }
  1302. }
  1303. /**
  1304. * 获取店铺信息
  1305. */
  1306. public function getMch($goods)
  1307. {
  1308. $mch = \app\models\Mch::find()->where(['id' => $goods->mch_id, 'is_delete' => 0, 'is_open' => 1])->one();
  1309. if (!$mch) {
  1310. return null;
  1311. }
  1312. $mch->kefu_info = json_decode($mch->kefu_info ?: '', true) ?: [
  1313. 'kefu_id' => ''
  1314. ];
  1315. return $mch;
  1316. }
  1317. public function getDateByInterval(int $num) :array
  1318. {
  1319. //var_dump($st, $et);die;
  1320. $returnData = [];
  1321. $i = 0;
  1322. do {
  1323. $temp = date('Y-m-d', strtotime('+' . $i . ' day', strtotime(date('Y-m-d'))));
  1324. $returnData[] = $temp;
  1325. $i++;
  1326. } while ($i < $num);
  1327. return $returnData;
  1328. }
  1329. public function goodsBookingTime($goods_id, $dayCount = 7) {
  1330. $now_date = strtotime(date('Y-m-d'));
  1331. $goods_book = GoodsBook::findOne(['goods_id' => $goods_id]);
  1332. $service_book = Json::decode($goods_book->service_book);
  1333. $date_data = $this->getDateByInterval($dayCount);
  1334. $new_arr = [
  1335. 'data' => []
  1336. ];
  1337. $order = Order::find()->alias('o')
  1338. ->leftJoin(['od' => OrderDetail::tableName()], 'o.id = od.order_id')
  1339. ->where(['o.trade_status' => [0, 2, 3], 'o.is_delete' => 0, 'o.order_type' => 2, 'goods_id' => $goods_id])
  1340. ->andWhere(['>', 'o.created_at', time() - 3600 - $dayCount * 86400])
  1341. ->select('od.attr, od.num')->asArray()->all();
  1342. foreach ($date_data as $index => $datum) {
  1343. $new_arr['data'][$index]['date'] = $datum;
  1344. $new_arr['data'][$index]['time'] = $service_book['data'][0]['time'];
  1345. }
  1346. foreach ($new_arr['data'] as &$value) {
  1347. if (strtotime($value['date']) >= $now_date) {
  1348. foreach ($value['time'] as &$m) {
  1349. foreach ($m['times'] as &$n) {
  1350. $times = explode('-', $n['time']);
  1351. foreach ($order as $item) {
  1352. if ($item['attr']) {
  1353. $item['attr'] = json_decode($item['attr'], true);
  1354. $order_time = explode('-', $item['attr']['time']);
  1355. if (
  1356. strtotime($item['attr']['date'] . ' ' . $times[0]) === strtotime($value['date'] . ' ' . $order_time[0]) &&
  1357. strtotime($item['attr']['date'] . ' ' . $times[1]) === strtotime($value['date'] . ' ' . $order_time[1])
  1358. ) {
  1359. $n['num'] = $n['num'] - $item['num'];
  1360. }
  1361. }
  1362. }
  1363. }
  1364. }
  1365. }
  1366. }
  1367. return $new_arr;
  1368. }
  1369. public function goodsPurchaseCatList() {
  1370. $user_id = $this->user_id;
  1371. $md_id = $this->md_id;
  1372. if ($md_id <= 0) {
  1373. $md_id = [-1, 0];
  1374. }
  1375. $query = OrderDetail::find()->alias('od')
  1376. ->leftJoin(['g' => Goods::tableName()], 'od.goods_id = g.id')
  1377. ->leftJoin(['o' => Order::tableName()], 'od.order_id = o.id')
  1378. ->leftJoin(['odg' => OrderDetail::find()->alias('od_')
  1379. ->leftJoin(['g_' => Goods::tableName()], 'od_.goods_id = g_.id')
  1380. ->leftJoin(['o_' => Order::tableName()], 'od_.order_id = o_.id')
  1381. ->where(['o_.user_id' => $user_id, 'g_.status' => 1, 'g_.is_delete' => 0])
  1382. ->andWhere(['or', ['o_.is_pay' => 1], ['o_.pay_type' => 2]])
  1383. ->andWhere(['<>', 'o_.trade_status', 1])
  1384. ->groupBy('od_.goods_id')
  1385. ->select('goods_id, sum(od_.num) as num, o_.id as order_id')],
  1386. 'od.goods_id = odg.goods_id')
  1387. ->where(['o.user_id' => $user_id, 'g.status' => 1, 'g.is_delete' => 0])
  1388. ->andWhere(['or', ['o.is_pay' => 1], ['o.pay_type' => 2]])
  1389. ->andWhere(['<>', 'o.trade_status', 1]);
  1390. $data = $query->orderBy('odg.num DESC, g.id DESC')->groupBy('od.goods_id')->select('od.goods_id, o.id order_id')->asArray()->all();
  1391. $cat_data = [];
  1392. foreach ($data as $item) {
  1393. $goods_cat_info = GoodsCat::find()->alias('gc')->leftJoin(['c' => Cat::tableName()], 'gc.cat_id = c.id')
  1394. ->where(['gc.goods_id' => $item['goods_id'], 'gc.is_delete' => 0, 'c.is_delete' => 0, 'c.is_show' => 1])
  1395. ->select(' c.name, c.id')->asArray()->all();
  1396. foreach ($goods_cat_info as $goods_cat_item) {
  1397. if (isset($cat_data[$goods_cat_item['id']])) {
  1398. $cat_data[$goods_cat_item['id']]['goods_id'][] = $item['goods_id'];
  1399. } else {
  1400. $cat_data[$goods_cat_item['id']] = [
  1401. 'id' => $goods_cat_item['id'],
  1402. 'name' => $goods_cat_item['name'],
  1403. 'goods_id' => [$item['goods_id']]
  1404. ];
  1405. }
  1406. }
  1407. }
  1408. $cat_data = array_values($cat_data);
  1409. foreach ($cat_data as &$item) {
  1410. $item['cart_num'] = intval(Cart::find()->where(['user_id' => $user_id, 'goods_id' => $item['goods_id'], 'is_delete' => 0, 'md_id' => $md_id])
  1411. ->select('num')->sum('num') ?? 0);
  1412. }
  1413. return [
  1414. 'code' => 0,
  1415. 'msg' => '',
  1416. 'data' => [
  1417. 'list' => $cat_data
  1418. ]
  1419. ];
  1420. }
  1421. //获取用户常购商品
  1422. public function goodsPurchaseList() {
  1423. $store_id = $this->store_id;
  1424. $user_id = $this->user_id;
  1425. $cat_id = intval($this->cat_id);
  1426. $md_id = $this->md_id;
  1427. if ($md_id <= 0) {
  1428. $md_id = [-1, 0];
  1429. }
  1430. if ($cat_id <= 0) {
  1431. return [
  1432. 'code' => 1,
  1433. 'msg' => '参数错误',
  1434. ];
  1435. }
  1436. $query = OrderDetail::find()->alias('od')
  1437. ->leftJoin(['g' => Goods::tableName()], 'od.goods_id = g.id')
  1438. ->leftJoin(['o' => Order::tableName()], 'od.order_id = o.id')
  1439. ->leftJoin(['odg' => OrderDetail::find()->alias('od_')
  1440. ->leftJoin(['g_' => Goods::tableName()], 'od_.goods_id = g_.id')
  1441. ->leftJoin(['o_' => Order::tableName()], 'od_.order_id = o_.id')
  1442. ->where(['o_.user_id' => $user_id, 'g_.status' => 1, 'g_.is_delete' => 0])
  1443. ->andWhere(['or', ['o_.is_pay' => 1], ['o_.pay_type' => 2]])
  1444. ->andWhere(['<>', 'o_.trade_status', 1])
  1445. ->groupBy('od_.goods_id')
  1446. ->select('goods_id, sum(od_.num) as num')],
  1447. 'od.goods_id = odg.goods_id')
  1448. ->where(['o.user_id' => $user_id, 'g.status' => 1, 'g.is_delete' => 0])
  1449. ->andWhere(['or', ['o.is_pay' => 1], ['o.pay_type' => 2]])
  1450. ->andWhere(['<>', 'o.trade_status', 1]);
  1451. $query->leftJoin(['gc' => GoodsCat::tableName()], 'od.goods_id = gc.goods_id')->andWhere([
  1452. 'gc.cat_id' => $cat_id
  1453. ])->orderBy('odg.num DESC');
  1454. $query->orderBy('odg.num DESC, g.id DESC')->groupBy('gc.goods_id')->select('odg.*');
  1455. $pagination = pagination_make($query);
  1456. foreach ($pagination['list'] as &$item) {
  1457. $goods_id = $item['goods_id'];
  1458. $goods = Goods::findOne($goods_id);
  1459. $item['name'] = $goods->name;
  1460. $item['cover_pic'] = $goods->cover_pic;
  1461. $item['price'] = $goods->price;
  1462. $item['original_price'] = $goods->original_price;
  1463. $item['use_attr'] = intval($goods->use_attr);
  1464. $item['attr'] = json_decode($goods->attr, true);
  1465. $item['sales'] = $goods->getSalesVolume();
  1466. $item['goods_num'] = $goods->goods_num;
  1467. $item['cart_num'] = Cart::find()->where(['user_id' => $user_id, 'goods_id' => $goods_id, 'is_delete' => 0, 'md_id' => $md_id])
  1468. ->select('num')->sum('num') ?? 0;
  1469. $item['cart_id'] = Cart::find()->where(['user_id' => $user_id, 'goods_id' => $goods_id, 'is_delete' => 0, 'md_id' => $md_id])
  1470. ->select('id')->scalar() ?: 0;
  1471. }
  1472. return [
  1473. 'code' => 0,
  1474. 'msg' => '',
  1475. 'data' => $pagination
  1476. ];
  1477. }
  1478. }