MActivity.Class.php 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012
  1. <?php
  2. /**
  3. * 促销活动
  4. * Created by PhpStorm.
  5. * User: XiaoMing
  6. * Date: 2019/12/18
  7. * Time: 12:08
  8. */
  9. namespace JinDouYun\Model\Market;
  10. use JinDouYun\Cache\ActivityLimitCache;
  11. use JinDouYun\Controller\Common\Logger;
  12. use JinDouYun\Dao\Market\DActivityGoodsUserLog;
  13. use JinDouYun\Model\Customer\MCustomer;
  14. use JinDouYun\Model\Goods\MGoods;
  15. use JinDouYun\Model\GoodsManage\MSku;
  16. use Mall\Framework\Core\ErrorCode;
  17. use Mall\Framework\Core\ResultWrapper;
  18. use Mall\Framework\Core\StatusCode;
  19. use JinDouYun\Cache\GoodsBasicRelevant;
  20. use JinDouYun\Dao\Market\DActivity;
  21. use JinDouYun\Model\MBaseModel;
  22. use JinDouYun\Model\Price\MPrice;
  23. class MActivity extends MBaseModel
  24. {
  25. private $onlineUserId;
  26. private $onlineEnterpriseId;
  27. private $objDActivity;
  28. private $objMActivityGoods;
  29. private $areaCode;
  30. private $objActivityLimitCache;
  31. private $objMSku;
  32. /**
  33. * true=>app false=>manage
  34. * @var boolean
  35. */
  36. private $isFront;//是否是前台调用此Model
  37. /**
  38. * @var DActivityGoodsUserLog
  39. */
  40. private $objDActivityGoodsUserLog;
  41. /**
  42. * MActivity constructor.
  43. * @param $onlineUserId
  44. * @param $onlineEnterpriseId
  45. * @param null $areaCode
  46. * @param bool $isFront
  47. * @throws \Exception
  48. */
  49. public function __construct($onlineUserId, $onlineEnterpriseId, $areaCode = null,$isFront = true)
  50. {
  51. $this->isFront = $isFront;
  52. $this->onlineUserId = $onlineUserId;
  53. $this->onlineEnterpriseId = $onlineEnterpriseId;
  54. $this->areaCode = $areaCode;
  55. parent::__construct($this->onlineEnterpriseId, $onlineUserId);
  56. $this->objDActivity = new DActivity('default');
  57. $this->objDActivity->setTable($this->objDActivity->get_Table() . '_' . $this->onlineEnterpriseId);
  58. $this->objMActivityGoods = new MActivityGoods($this->onlineUserId, $this->onlineEnterpriseId);
  59. //$this->objDActivity->setSearchIndex('activity_search')->setType('activity');
  60. $this->objMSku = new MSku($this->onlineUserId,$this->onlineEnterpriseId);
  61. $this->objDActivityGoodsUserLog = new DActivityGoodsUserLog();
  62. $this->objActivityLimitCache = new ActivityLimitCache($this->onlineEnterpriseId);
  63. }
  64. /**
  65. * 新增
  66. * @param $params
  67. * @return ResultWrapper
  68. */
  69. public function add($params)
  70. {
  71. $details = $params;
  72. $activityGoods = $params['activityGoods'];
  73. unset($params['activityGoods']);
  74. $sql = 'SELECT * FROM qianniao_activity_' . $this->onlineEnterpriseId . ' WHERE deleteStatus=' . StatusCode::$standard . ' AND activityType=' . $params['activityType'] . ' AND enableStatus=' . StatusCode::$standard . ' AND '.$params['startTime'].' >= startTime and '.$params['startTime'].' <= endTime';
  75. $dbResult = $this->objDActivity->query($sql);
  76. if ($dbResult === false) {
  77. return ResultWrapper::fail($this->objDActivity->error(), ErrorCode::$dberror);
  78. }
  79. if (!empty($dbResult)) {
  80. return ResultWrapper::fail('此时段已有启用活动', ErrorCode::$paramError);
  81. }
  82. $this->objDActivity->beginTransaction();
  83. $dbResult = $this->objDActivity->insert($params);
  84. if ($dbResult === false) {
  85. $this->objDActivity->rollBack();
  86. return ResultWrapper::fail($this->objDActivity->error(), ErrorCode::$dberror);
  87. }
  88. foreach ($activityGoods as &$val) {
  89. $val['activityId'] = $dbResult;
  90. }
  91. $activityId = $dbResult;
  92. unset($dbResult);
  93. $dbResult = $this->objMActivityGoods->add($activityGoods, true);
  94. if (!$dbResult->isSuccess()) {
  95. $this->objDActivity->rollBack();
  96. return ResultWrapper::fail($dbResult->getData(), ErrorCode::$dberror);
  97. }
  98. foreach ($activityGoods as $goods) {
  99. $values = explode('|', rtrim(str_repeat($goods['goodsId'] . '|', $goods['activityNum']), '|'));
  100. $this->objActivityLimitCache->lPush($activityId, $goods['goodsId'], $goods['skuId'], $values);
  101. }
  102. $this->objActivityLimitCache->writeActivity($activityId, $details);//缓存活动
  103. //self::updateEsData($activityId, $params);
  104. $this->objDActivity->commit();
  105. return ResultWrapper::success($dbResult);
  106. }
  107. /**
  108. * 更新ES
  109. * @param $id
  110. * @param $params
  111. */
  112. public function updateEsData($id, $params)
  113. {
  114. $esData = [
  115. 'enterpriseId' => $this->onlineEnterpriseId,//enterpriseId,
  116. 'id' => $id,//自增id,
  117. 'activityType' => $params['activityType'],//活动类型
  118. 'title' => $params['title'],//名称
  119. 'remark' => $params['remark'],//客户沟通
  120. 'startTime' => $params['startTime'],//活动开始时间,
  121. 'endTime' => $params['endTime'],//活动结束时间
  122. 'enableStatus' => $params['enableStatus'],
  123. 'images' => json_decode($params['images'], true),
  124. 'useShop' => $params['useShop'],//使用范围
  125. 'customerRange' => $params['customerRange'],//客户范围
  126. 'customerSourceId' => isset($params['customerSourceId']) ? $params['customerSourceId'] : '',//客户id 1,2
  127. 'sort' => isset($params['sort']) ? $params['sort'] : 0,
  128. 'describe' => $params['describe'],
  129. 'createTime' => $params['createTime'],
  130. 'updateTime' => $params['updateTime'],
  131. 'isEnd' => StatusCode::$standard,
  132. 'deleteStatus' => StatusCode::$standard,
  133. 'auditStatus' => StatusCode::$auditStatus['auditing'],
  134. ];
  135. $_id = self::createEsDocumentId($id);
  136. $result = $this->objDActivity->addUpSearchIndexDocument($esData, $_id);
  137. if (isset($result['_shards']) && isset($result['_shards']['successful']) && $result['_shards']['successful'] == 1) {
  138. //echo "es操作成功";
  139. //return;
  140. } else {
  141. //echo "es操作失败";
  142. }
  143. }
  144. /**
  145. * @param $id
  146. * @return string
  147. */
  148. private function createEsDocumentId($id)
  149. {
  150. return 'EnterpriseId_' . $this->onlineEnterpriseId . '_id_' . $id;
  151. }
  152. /**
  153. * 详情
  154. *
  155. * @param $id
  156. * @return ResultWrapper
  157. * @throws \Exception
  158. */
  159. public function getInfo($id)
  160. {
  161. $dbResult = $this->objDActivity->get_by('id', $id);
  162. if ($dbResult === false) {
  163. return ResultWrapper::fail($this->objDActivity->error(), ErrorCode::$dberror);
  164. }
  165. $activityGoods = $this->objMActivityGoods->getActivityGoods(
  166. ['activityId' => $id, 'deleteStatus' => StatusCode::$standard],
  167. 'id,activityId,goodsId,basicGoodsId,skuId,price,shopId,activityNum,limitNum'
  168. );//获取详情数据
  169. if (!$activityGoods->isSuccess()) {
  170. return ResultWrapper::fail($activityGoods->getData(), ErrorCode::$dberror);
  171. }
  172. $allowActivityGoods = self::filterActivityGoods($activityGoods->getData());
  173. $dbResult['activityGoods'] = $allowActivityGoods;
  174. return ResultWrapper::success(self::format($dbResult));
  175. }
  176. /**
  177. * @param $data
  178. * @return mixed
  179. * @throws \Exception
  180. */
  181. private function format($data)
  182. {
  183. if (empty($data)) return $data;
  184. $data['useShopName'] = '';
  185. if (isset($data['useShop'])) {
  186. $data['useShopName'] = ($data['useShop'] == 0) ? ['全店铺'] : array_values(self::getNameByShopId(explode(',', $data['useShop'])));
  187. }
  188. $activityGoods = $data['activityGoods'];
  189. $skuIds = array_column($activityGoods,'skuId');
  190. $objMSku = new MSku($this->onlineUserId,$this->onlineEnterpriseId);
  191. $skuMapRes = $objMSku->getSpecNameBySkuId($skuIds);
  192. $skuMap = [];
  193. if ($skuMapRes->isSuccess()){
  194. $skuMap = $skuMapRes->getData();
  195. }
  196. if (!empty($activityGoods)) {
  197. $objActivityLimitCache = new ActivityLimitCache($this->onlineEnterpriseId);
  198. foreach ($activityGoods as &$goods) {
  199. $goods['surplusNum'] = (int)$objActivityLimitCache->getLen($data['id'], $goods['goodsId'], $goods['skuId']);
  200. $goods['specGroup'] = isset($skuMap[$goods['skuId']]) ? $skuMap[$goods['skuId']]['specGroup'] : [];
  201. }
  202. }
  203. $data['activityGoods'] = $activityGoods;
  204. if (!empty($data['images'])) $data['images'] = json_decode($data['images'], true);
  205. return $data;
  206. }
  207. /**
  208. * 编辑
  209. *
  210. * @param $params
  211. * @param $id
  212. * @param $deleteArray
  213. * @return ResultWrapper
  214. */
  215. public function edit($params, $id, $deleteArray)
  216. {
  217. $details = $params;
  218. $activityGoods = $params['activityGoods'];
  219. unset($params['activityGoods']);
  220. $this->objDActivity->beginTransaction();
  221. $dbResult = $this->objDActivity->update($params, $id);
  222. if ($dbResult === false) {
  223. $this->objDActivity->rollBack();
  224. return ResultWrapper::fail($this->objDActivity->error(), ErrorCode::$dberror);
  225. }
  226. $dbResult = $this->objMActivityGoods->edit($activityGoods, $id, $deleteArray);
  227. if (!$dbResult->isSuccess()) {
  228. $this->objDActivity->rollBack();
  229. return ResultWrapper::fail($this->objDActivity->error(), ErrorCode::$dberror);
  230. }
  231. foreach ($activityGoods as $goods) {
  232. //先删除key
  233. $this->objActivityLimitCache->delKey($id, $goods['goodsId'],$goods['skuId']);
  234. //重新写入
  235. $values = explode('|', rtrim(str_repeat($goods['goodsId'] . '|', $goods['activityNum']), '|'));
  236. $this->objActivityLimitCache->lPush($id, $goods['goodsId'], $goods['skuId'], $values);
  237. }
  238. $this->objActivityLimitCache->writeActivity($id, $details);//缓存活动
  239. //self::updateEsData($id, $params);
  240. $this->objDActivity->commit();
  241. return ResultWrapper::success($dbResult);
  242. }
  243. /**
  244. * 审核
  245. * @param $params
  246. * @return ResultWrapper
  247. */
  248. public function updateAuditStatus($params)
  249. {
  250. $dbResult = $this->objDActivity->update(['auditStatus' => $params['auditStatus']], $params['id']);
  251. if ($dbResult === false) {
  252. return ResultWrapper::fail($this->objDActivity->error(), ErrorCode::$dberror);
  253. }
  254. /*$_id = self::createEsDocumentId($params['id']);
  255. $this->objDActivity->esupdateTypeFieldVaule([
  256. 'auditStatus' => $params['auditStatus'],
  257. ], $_id);*/
  258. return ResultWrapper::success($dbResult);
  259. }
  260. /**
  261. * 启用/禁用
  262. * @param $params
  263. * @return ResultWrapper
  264. */
  265. public function updateEnableStatus($params)
  266. {
  267. if ($params['enableStatus'] == StatusCode::$standard) {
  268. $dbResult = $this->objDActivity->get(['id' => $params['id']]);
  269. if ($dbResult === false) {
  270. return ResultWrapper::fail($this->objDActivity->error(), ErrorCode::$dberror);
  271. }
  272. if (empty($dbResult)) {
  273. return ResultWrapper::fail('活动不存在', ErrorCode::$paramError);
  274. }
  275. $sql = 'SELECT * FROM qianniao_activity_' . $this->onlineEnterpriseId . ' WHERE deleteStatus=' . StatusCode::$standard . ' AND activityType=' . $params['activityType'] . ' AND enableStatus=' . StatusCode::$standard . ' AND ((startTime>=' . $dbResult['startTime'] . ' AND startTime <=' . $dbResult['endTime'] . ') OR (startTime <=' . $dbResult['startTime'] . ' AND endTime>=' . $dbResult['endTime'] . ') OR (endTime>=' . $dbResult['startTime'] . ' AND endTime<=' . $dbResult['endTime'] . '))';
  276. $dbResult = $this->objDActivity->query($sql);
  277. if ($dbResult === false) {
  278. return ResultWrapper::fail($this->objDActivity->error(), ErrorCode::$dberror);
  279. }
  280. if (!empty($dbResult)) {
  281. return ResultWrapper::fail('此时段已有启用活动', ErrorCode::$paramError);
  282. }
  283. }
  284. $dbResult = $this->objDActivity->update(['enableStatus' => $params['enableStatus']], $params['id']);
  285. if ($dbResult === false) {
  286. return ResultWrapper::fail($this->objDActivity->error(), ErrorCode::$dberror);
  287. }
  288. $activity = $this->objActivityLimitCache->getActivity($params['id']);
  289. if (!empty($activity)){
  290. //修改缓存数据
  291. $activity['enableStatus'] = $params['enableStatus'];
  292. $this->objActivityLimitCache->writeActivity($params['id'],$activity);
  293. }
  294. /*$_id = self::createEsDocumentId($params['id']);
  295. $this->objDActivity->esupdateTypeFieldVaule([
  296. 'enableStatus' => $params['enableStatus'],
  297. ], $_id);*/
  298. return ResultWrapper::success($dbResult);
  299. }
  300. /**
  301. * 删除
  302. * @param $id
  303. * @return ResultWrapper
  304. * @throws \Exception
  305. */
  306. public function del($id)
  307. {
  308. $dbResult = $this->objDActivity->update(['deleteStatus' => StatusCode::$delete], $id);
  309. if ($dbResult === false) {
  310. return ResultWrapper::fail($this->objDActivity->error(), ErrorCode::$dberror);
  311. }
  312. $selectParams = [
  313. 'activityId' => $id
  314. ];
  315. $activityGoods = $this->objMActivityGoods->getActivityGoods($selectParams, '*', false);
  316. if (!$activityGoods->isSuccess()) {
  317. return ResultWrapper::fail($activityGoods->getData(), ErrorCode::$dberror);
  318. }
  319. $activityGoods = $activityGoods->getData();
  320. foreach ($activityGoods as $goods) {
  321. //删除key
  322. $this->objActivityLimitCache->delKey($id, $goods['goodsId'], $goods['skuId']);
  323. }
  324. /*$_id = self::createEsDocumentId($id);
  325. $this->objDActivity->esupdateTypeFieldVaule([
  326. 'deleteStatus' => StatusCode::$delete
  327. ], $_id);*/
  328. return ResultWrapper::success($dbResult);
  329. }
  330. /**
  331. * @param $selectParams
  332. * @return ResultWrapper
  333. */
  334. public function getAll($selectParams)
  335. {
  336. $limit = $selectParams['limit'];
  337. unset($selectParams['limit']);
  338. $offset = $selectParams['offset'];
  339. unset($selectParams['offset']);
  340. $where = 'deleteStatus = '.StatusCode::$standard;
  341. if( isset($selectParams['title']) && !empty($selectParams['title']) ){
  342. $where .= ' and title like "%'.$selectParams['title'].'%"';
  343. }
  344. if( isset($selectParams['useShop']) && !empty($selectParams['useShop']) ){
  345. $where .= ' and useShop ='.$selectParams['useShop'];
  346. }
  347. if( isset($selectParams['isEnd']) && !empty($selectParams['isEnd']) ){
  348. $where .= ' and isEnd ='.$selectParams['isEnd'];
  349. }
  350. if( isset($selectParams['enableStatus']) && !empty($selectParams['enableStatus']) ){
  351. $where .= ' and enableStatus ='.$selectParams['enableStatus'];
  352. }
  353. if( isset($selectParams['start']) && !empty($selectParams['start']) ){
  354. $where .= ' and createTime >='.$selectParams['start'];
  355. }
  356. if( isset($selectParams['end']) && !empty($selectParams['end']) ){
  357. $where .= ' and createTime <='.$selectParams['end'];
  358. }
  359. $dbResult = $this->objDActivity->select($where, '*', 'createTime DESC', $limit, $offset);
  360. if ($dbResult === false) {
  361. return ResultWrapper::fail($this->objDActivity->error(), ErrorCode::$dberror);
  362. }
  363. $total = $this->objDActivity->count($selectParams);
  364. $return = [
  365. 'data' => self::formatAll($dbResult),
  366. 'total' => ($total) ? intval($total) : 0,
  367. ];
  368. return ResultWrapper::success($return);
  369. }
  370. /**
  371. * @param $data
  372. * @return mixed
  373. */
  374. private function formatAll($data)
  375. {
  376. if (empty($data)) return $data;
  377. foreach ($data as &$val) {
  378. $val['useShopName'] = ($val['useShop'] == 0) ? ['全店铺'] : array_values(self::getNameByShopId(explode(',', $val['useShop'])));
  379. }
  380. return $data;
  381. }
  382. /**
  383. *
  384. * @param $shopIds
  385. * @return array
  386. */
  387. public function getNameByShopId($shopIds)
  388. {
  389. $objGoodsBasicRelevantCache = new GoodsBasicRelevant($this->onlineEnterpriseId);
  390. $result = [];
  391. foreach ($shopIds as $shopId) {
  392. if (!empty($shopId)) $result[] = $objGoodsBasicRelevantCache->getNameByShopId($shopId);
  393. }
  394. return $result;
  395. }
  396. /**
  397. * 搜索
  398. * @param $selectParams
  399. * @return ResultWrapper
  400. */
  401. public function search($selectParams)
  402. {
  403. $defaultDSL = [
  404. 'from' => $selectParams['offset'],
  405. 'size' => $selectParams['limit'],
  406. 'sort' => [
  407. 'createTime' => [
  408. 'order' => 'desc'
  409. ],
  410. ],
  411. ];
  412. $dsl = [];
  413. $dsl['query']['bool']['must'][] = [
  414. 'term' => ['enterpriseId' => $this->onlineEnterpriseId],
  415. ];
  416. //名称
  417. if (!empty($selectParams['title'])) {
  418. $dsl['query']['bool']['must'][] = [
  419. 'multi_match' => [
  420. 'fields' => ['title'],
  421. 'query' => $selectParams['title'],
  422. 'fuzziness' => 'AUTO',
  423. ],
  424. ];
  425. }
  426. //使用范围
  427. if (!empty($selectParams['useShop'])) {
  428. $dsl['query']['bool']['must'][] = [
  429. 'multi_match' => [
  430. 'fields' => ['useShop'],
  431. 'query' => $selectParams['useShop'],
  432. 'fuzziness' => 'AUTO',
  433. ],
  434. ];
  435. }
  436. //发放方式
  437. if (!empty($selectParams['activityType'])) {
  438. $dsl['query']['bool']['filter'][] =
  439. ['term' => ['activityType' => $selectParams['activityType']]];
  440. }
  441. //审核状态
  442. if (!empty($selectParams['enableStatus'])) {
  443. $dsl['query']['bool']['filter'][] =
  444. ['term' => ['enableStatus' => $selectParams['enableStatus']]];
  445. }
  446. //审核状态
  447. if (!empty($selectParams['auditStatus']) && isset($selectParams['auditStatus'])) {
  448. $dsl['query']['bool']['filter'][] =
  449. ['term' => ['auditStatus' => $selectParams['auditStatus']]];
  450. }
  451. //时间
  452. if (!empty($selectParams['start']) && !empty($selectParams['end'])) {
  453. $dsl['query']['bool']['must'][] = [
  454. 'range' => [
  455. 'createTime' => [
  456. 'gte' => $selectParams['start'],
  457. 'lte' => $selectParams['end'],
  458. ]
  459. ]
  460. ];
  461. } else {
  462. if (!empty($selectParams['start'])) {
  463. $dsl['query']['bool']['must'][] = [
  464. 'range' => [
  465. 'createTime' => [
  466. 'gte' => $selectParams['start'],
  467. ]
  468. ]
  469. ];
  470. }
  471. if (!empty($selectParams['end'])) {
  472. $dsl['query']['bool']['must'][] = [
  473. 'range' => [
  474. 'createTime' => [
  475. 'lte' => $selectParams['end'],
  476. ]
  477. ]
  478. ];
  479. }
  480. }
  481. //活动是否结束
  482. if (!empty($selectParams['isEnd'])) {
  483. $nowTime = time();
  484. if ($selectParams['isEnd'] == StatusCode::$standard) {
  485. //未结束
  486. $dsl['query']['bool']['must'][] = [
  487. 'range' => [
  488. 'startTime' => [
  489. 'gte' => $nowTime,
  490. ]
  491. ]
  492. ];
  493. $dsl['query']['bool']['must'][] = [
  494. 'range' => [
  495. 'endTime' => [
  496. 'lte' => $nowTime,
  497. ],
  498. ]
  499. ];
  500. } elseif ($selectParams['isEnd'] == StatusCode::$delete) {
  501. //已结束
  502. $dsl['query']['bool']['must'][] = [
  503. 'range' => [
  504. 'endTime' => [
  505. 'lte' => $nowTime,
  506. ],
  507. ]
  508. ];
  509. }
  510. }
  511. $dsl = array_merge($defaultDSL, $dsl);
  512. $result = $this->objDActivity->getSearchQueryDsl($dsl);
  513. if (isset($result['status']) && $result['status'] == 400) {
  514. return ResultWrapper::fail('获取数据失败' . $result['error']['reason'], ErrorCode::$apiNotResult);
  515. }
  516. if (!isset($result['hits']) || $result['hits']['total'] == 0) {
  517. return ResultWrapper::success([
  518. 'data' => [],
  519. 'total' => 0
  520. ]);
  521. }
  522. $total = $result['hits']['total'];
  523. $dbResult = $result['hits']['hits'];
  524. $list = [];
  525. foreach ($dbResult as $key => &$value) {
  526. $data = [];
  527. $data = $value['_source'];
  528. $list[] = $data;
  529. }
  530. $return = [
  531. 'data' => self::formatAll($list),
  532. 'total' => ($total) ? intval($total) : 0,
  533. ];
  534. return ResultWrapper::success($return);
  535. }
  536. /**
  537. * 获取活动
  538. * ['goodsId','activityType','customerType']
  539. * @param $selectParams
  540. * @return ResultWrapper
  541. */
  542. public function getActivity($selectParams)
  543. {
  544. $this->objDActivity->setTable('qianniao_activity_goods_'.$this->onlineEnterpriseId );
  545. $nowTime = time();
  546. if (isset($selectParams['customerType']) && !empty($selectParams['customerType'])) {
  547. $sql = 'SELECT a.id as activityId,a.images,a.title,a.startTime,a.endTime,a.remark,a.activityType,g.activityNum,g.limitNum,g.price,g.basicGoodsId,g.id as goodsActivityId,g.skuId,g.goodsId,g.shopId FROM qianniao_activity_' . $this->onlineEnterpriseId . ' as a LEFT JOIN qianniao_activity_goods_' . $this->onlineEnterpriseId . ' as g ON a.id=g.activityId WHERE a.enableStatus=' . StatusCode::$standard . ' AND a.deleteStatus=' . StatusCode::$standard . ' AND a.auditStatus=' . StatusCode::$auditStatus['auditPass'] . ' AND g.deleteStatus=' . StatusCode::$standard . ' AND a.startTime<' . $nowTime . ' AND a.endTime> ' . $nowTime . ' AND (a.customerRange=' . StatusCode::$standard . ' OR FIND_IN_SET(' . $selectParams['customerType'] . ',a.customerSourceId))';
  548. } else {
  549. $sql = 'SELECT a.id as activityId,a.images,a.title,a.startTime,a.endTime,a.remark,a.activityType,g.activityNum,g.limitNum,g.price,g.basicGoodsId,g.id as goodsActivityId,g.skuId,g.goodsId,g.shopId FROM qianniao_activity_' . $this->onlineEnterpriseId . ' as a LEFT JOIN qianniao_activity_goods_' . $this->onlineEnterpriseId . ' as g ON a.id=g.activityId WHERE a.enableStatus=' . StatusCode::$standard . ' AND a.deleteStatus=' . StatusCode::$standard . ' AND a.auditStatus=' . StatusCode::$auditStatus['auditPass'] . ' AND g.deleteStatus=' . StatusCode::$standard . ' AND a.startTime<' . $nowTime . ' AND a.endTime> ' . $nowTime . ' AND (a.customerRange=' . StatusCode::$standard . ')';
  550. }
  551. if (isset($selectParams['skuIds']) && !empty($selectParams['skuIds'])){
  552. $sql .= ' AND g.skuId IN(' . $selectParams['skuIds'] . ')';
  553. }
  554. if (isset($selectParams['goodsId']) && !empty($selectParams['goodsId'])) {
  555. $sql .= ' AND g.goodsId IN(' . $selectParams['goodsId'] . ')';
  556. }
  557. if (isset($selectParams['activityType']) && !empty($selectParams['activityType'])) {
  558. $sql .= ' AND a.activityType=' . $selectParams['activityType'];
  559. }
  560. $dbResult = $this->objDActivity->query($sql);
  561. if ($dbResult === false) {
  562. return ResultWrapper::fail($this->objDActivity->error(), ErrorCode::$dberror);
  563. }
  564. return ResultWrapper::success($dbResult);
  565. }
  566. /**
  567. * 获取秒杀活动
  568. * @return ResultWrapper
  569. * @throws \Exception
  570. */
  571. public function getActivityAll()
  572. {
  573. //首页未登录获取秒杀活动
  574. if (!empty($this->onlineUserId)) {
  575. $objMCustomer = new MCustomer($this->onlineEnterpriseId, $this->onlineUserId);
  576. $dbResult = $objMCustomer->getCustomerInfoByUserCenterId($this->onlineUserId);
  577. if (!$dbResult->isSuccess()) {
  578. return ResultWrapper::fail($dbResult->getData(), ErrorCode::$dberror);
  579. }
  580. $customer = $dbResult->getData();
  581. unset($dbResult);
  582. $selectParams['customerType'] = $customer['type'];
  583. }
  584. $selectParams['activityType'] = StatusCode::$activityType['secKill'];
  585. $dbResult = self::getActivity($selectParams);
  586. if (!$dbResult->isSuccess()) {
  587. return ResultWrapper::fail($dbResult->getData(), ErrorCode::$dberror);
  588. }
  589. $allowActivityGoods = self::filterActivityGoods($dbResult->getData());
  590. $return = [
  591. 'data' => self::formatActivity($allowActivityGoods),
  592. ];
  593. return ResultWrapper::success($return);
  594. }
  595. /**
  596. * @param $data
  597. * @return ResultWrapper
  598. * @throws \Exception
  599. */
  600. public function formatActivity($data)
  601. {
  602. if (empty($data)) return $data;
  603. $objGoodsBasicRelevant = new GoodsBasicRelevant($this->onlineEnterpriseId);
  604. $objMInventory = new MPrice($this->onlineUserId, $this->onlineEnterpriseId);
  605. $selectParam = [];
  606. foreach ($data as &$val) {
  607. if (isset($val['images']) && !empty($val['images'])) $val['activityImages'] = json_decode($val['images'], true);
  608. $val['goodsName'] = $objGoodsBasicRelevant->getNameByBasicId($val['basicGoodsId'], 'title');
  609. $val['images'] = $objGoodsBasicRelevant->getNameByBasicId($val['basicGoodsId'], 'images');
  610. $val['description'] = htmlspecialchars_decode($objGoodsBasicRelevant->getNameByBasicId($val['basicGoodsId'], 'description'));
  611. $selectParam['material'][$val['shopId']][] = $val['goodsId'];
  612. }
  613. $dbResult = $objMInventory->getPrice($selectParam);
  614. if (!$dbResult->isSuccess()) {
  615. return ResultWrapper::fail($dbResult->getData(), ErrorCode::$dberror);
  616. }
  617. //商品价格信息
  618. $goodsArr = [];
  619. foreach ($dbResult->getData() as $shopPriceArr) {
  620. foreach ($shopPriceArr as $goodsId => $goodsSkuArr) {
  621. $goodsArr[$goodsId] = $goodsSkuArr;
  622. }
  623. }
  624. //拼接单位+属性
  625. $skuMapping = [];
  626. $skuResult = $this->objMSku->getSpecNameBySkuId(array_column($data,'skuId'));
  627. if (!$skuResult->isSuccess()){
  628. file_put_contents('/www/wwwroot/logs/api.junhailan.com/MActivity_error.log', date('Y-m-d H:i:s') . '错误信息|sql错误 :' . var_export($skuResult->getData()) . PHP_EOL, FILE_APPEND);
  629. }else{
  630. $skuMapping = $skuResult->getData();
  631. }
  632. unset($val);
  633. foreach ($data as &$val) {
  634. $priceInfo = isset($goodsArr[$val['goodsId']][$val['skuId']]) ? $goodsArr[$val['goodsId']][$val['skuId']] : [];//此商品规格的价格信息
  635. $val['salePrice'] = isset($priceInfo['salePrice']) ? $priceInfo['salePrice'] : '0.00';
  636. $val['unitName'] = isset($skuMapping[$val['skuId']]) ? $skuMapping[$val['skuId']]['unitName'] : '';
  637. $val['specGroup'] = isset($skuMapping[$val['skuId']]) ? $skuMapping[$val['skuId']]['specGroup'] : [];
  638. }
  639. return $data;
  640. }
  641. /**
  642. * 按区域过滤活动商品 (只保留有效商品)
  643. * @param $data
  644. * @return mixed
  645. * @throws \Exception
  646. */
  647. public function filterActivityGoods($data)
  648. {
  649. $goodsIds = array_values(array_column($data, 'goodsId'));
  650. $objMGoods = new MGoods($this->onlineEnterpriseId, true, $this->onlineUserId);
  651. $pageParams = pageToOffset(1, count($data));
  652. $selectParams = [
  653. 'limit' => $pageParams['limit'],
  654. 'offset' => $pageParams['offset'],
  655. 'userCenterId' => $this->onlineUserId,
  656. 'areaCode' => $this->areaCode,
  657. 'goodsIds' => $goodsIds
  658. ];
  659. $result = $objMGoods->search($selectParams);
  660. if (!$result->isSuccess()) {
  661. return $data;
  662. }
  663. $allowGoods = [];
  664. $searchData = $result->getData();
  665. if (empty($searchData) && $this->isFront === true){
  666. //所有商品都不在此区域销售
  667. return [];
  668. }else{
  669. return $data;
  670. }
  671. $searchData = isset($searchData['data']) ? $searchData['data'] : [];
  672. foreach ($searchData as $key => $val) {
  673. $allowGoods[$val['id']] = $val;
  674. }
  675. foreach ($data as $key => $val) {
  676. if (!isset($allowGoods[$val['goodsId']])) {
  677. unset($data[$key]);
  678. continue;
  679. }
  680. //拼接当前商品sku的市场价和原价
  681. foreach ($allowGoods[$val['goodsId']]['skuData'] as $sku) {
  682. if (isset($val['skuId']) && isset($sku['skuId']) && $val['skuId'] == $sku['skuId']) {
  683. $data[$key]['originPrice'] = isset($sku['originPrice']) ? $sku['originPrice'] : 0;//商品原价
  684. $data[$key]['marketPrice'] = $sku['marketPrice'];//商品市场价
  685. $data[$key]['unitName'] = $sku['unitName'];//规格名称
  686. }
  687. }
  688. }
  689. return array_values($data);
  690. }
  691. /**
  692. * Doc: (des="根绝条件获取商品秒杀以及优惠活动价格")
  693. * User: XMing
  694. * Date: 2020/7/10
  695. * Time: 10:18 上午
  696. * @param array $condition
  697. * @return ResultWrapper
  698. */
  699. private function selectCondition(array $condition)
  700. {
  701. $nowTime = time();
  702. $fields = 'a.id as activityId,a.activityType,a.title,a.startTime,a.endTime,
  703. g.goodsId,g.skuId,g.price,g.basicGoodsId,
  704. g.shopId,g.activityNum,g.limitNum,g.haveBuyNum';
  705. $sql = 'select '.$fields.' from qianniao_activity_goods_'.$this->onlineEnterpriseId.' as g
  706. left join qianniao_activity_'.$this->onlineEnterpriseId.' as a
  707. on g.activityId = a.id
  708. where a.deleteStatus = '.StatusCode::$standard.'
  709. and a.enableStatus = '.StatusCode::$standard.'
  710. and a.auditStatus = '.StatusCode::$auditStatus['auditPass'].'
  711. and startTime<'.$nowTime.' and endTime > '.$nowTime;
  712. //店铺筛选
  713. if (isset($condition['shopId']) && !empty($condition['shopId'])){
  714. $sql .= ' and find_in_set('.$condition['shopId'].',a.useShop) ';
  715. }
  716. //客户筛选
  717. if (isset($condition['customerId']) && !empty($condition['customerId'])){
  718. $sql .= ' and (a.customerRange = '.StatusCode::$standard.' or find_in_set('.$condition['customerId'].',a.customerSourceId))';
  719. }
  720. //goodsId搜索
  721. if (isset($condition['goodsIds']) && !empty($condition['goodsIds'])){
  722. $goodsIdsStr = is_array($condition['goodsIds']) ? implode(',',$condition['goodsIds']) : $condition['goodsIds'];
  723. $sql .= ' and g.goodsId in('.$goodsIdsStr.') ';
  724. }
  725. $dbResult = $this->objDActivity->query($sql);
  726. if ($dbResult === false){
  727. return ResultWrapper::fail($this->objDActivity->error(),ErrorCode::$dberror);
  728. }
  729. return ResultWrapper::success($dbResult);
  730. }
  731. /**
  732. * Doc: (des="根据活动ids及客户id获取,活动剩余数量,以及用户剩余购买数量")
  733. * User: XMing
  734. * Date: 2020/7/10
  735. * Time: 5:10 下午
  736. * @param array $condition
  737. * @return ResultWrapper
  738. */
  739. private function selectLimitCondition(array $condition)
  740. {
  741. $fields = 'activityId,shopId,goodsId,skuId,num,customerId';
  742. $sql = 'select '.$fields.' from qianniao_activity_goods_user_log_'.$this->onlineEnterpriseId.'
  743. where shopId = '.$condition['shopId'];
  744. //客户id
  745. if (isset($condition['customerId']) && !empty($condition['customerId'])){
  746. $sql .= ' and customerId = '.$condition['customerId'];
  747. }
  748. //活动ids
  749. if (isset($condition['activityIds']) && !empty($condition['activityIds'])){
  750. $activityIdsStr = is_array($condition['activityIds']) ? implode(',',$condition['activityIds']) : $condition['activityIds'];
  751. $sql .= ' and activityId in('.$activityIdsStr.') ';
  752. }
  753. $dbResult = $this->objDActivity->query($sql);
  754. if ($dbResult === false){
  755. return ResultWrapper::fail($this->objDActivity->error(),ErrorCode::$dberror);
  756. }
  757. return ResultWrapper::success($dbResult);
  758. }
  759. /**
  760. * Doc: (des="计算用户已购数量")
  761. * User: XMing
  762. * Date: 2020/7/10
  763. * Time: 5:07 下午
  764. * @param array $selectParams
  765. * @return ResultWrapper
  766. */
  767. private function getAllowBuyNumByParams(array $selectParams)
  768. {
  769. $returnData = [];
  770. $conditions = [];
  771. foreach ($selectParams['activity'] as $shopId => $activityId){
  772. $returnData[$shopId] = [];
  773. $conditions[$shopId] = [
  774. 'shopId' => $shopId,
  775. 'customerId' => isset($selectParams['customerId']) ? $selectParams['customerId'] : 0,
  776. 'activityIds' => $activityId
  777. ];
  778. }
  779. if (empty($conditions)){
  780. return ResultWrapper::success($returnData);
  781. }
  782. //获取数据
  783. $activityData = [];
  784. foreach ($conditions as $condition){
  785. $result = self::selectLimitCondition($condition);
  786. if (!$result->isSuccess()){
  787. return ResultWrapper::fail($result->getData(),$result->getErrorCode());
  788. }
  789. $activityResult = $result->getData();
  790. $activityData = array_merge($activityData,$activityResult);
  791. }
  792. if (empty($activityData)){
  793. return ResultWrapper::success($returnData);
  794. }
  795. if (isset($selectParams['isCalCart']) && $selectParams['isCalCart'] === true){
  796. //统计购物车中已经加入的活动商品数
  797. }
  798. unset($returnData);
  799. $returnData = [];
  800. foreach ($activityData as $item){
  801. if (!isset($returnData[$item['shopId']][$item['goodsId']][$item['skuId']][$item['activityId']]['num'])){
  802. $returnData[$item['shopId']][$item['goodsId']][$item['skuId']][$item['activityId']]['num'] = 0;
  803. }
  804. $returnData[$item['shopId']][$item['goodsId']][$item['skuId']][$item['activityId']]['num'] = bcadd($returnData[$item['shopId']][$item['goodsId']][$item['skuId']][$item['activityId']]['num'],$item['num'],0);
  805. }
  806. return ResultWrapper::success($returnData);
  807. }
  808. /**
  809. * Doc: (des="通过goodsId,获取商品的活动价格信息")
  810. * User: XMing
  811. * Date: 2020/7/10
  812. * Time: 12:11 下午
  813. *
  814. * result des:
  815. * @activityNum int 活动限购数量
  816. * @limitNum int 用户限购数量
  817. * @haveBuyNum int 活动已购数量
  818. * @userBuyLogNum int 用户已购数量
  819. * @userAllowNum int 用户可够数量
  820. * @activityAllowNum int 活动剩余数量
  821. *
  822. * @param array $selectParams
  823. * @return ResultWrapper
  824. */
  825. public function getActivityPriceByParams(array $selectParams)
  826. {
  827. // 初始化所有活动物料价格
  828. $returnData = [];
  829. $conditions = [];
  830. foreach ($selectParams['material'] as $shopId => $goodsId) {
  831. $returnData[$shopId] = [];
  832. $conditions[$shopId] = [
  833. 'shopId' => $shopId,
  834. 'customerId' => isset($selectParams['customerId']) ? (int) $selectParams['customerId'] : 0,
  835. ];
  836. $conditions[$shopId]['goodsIds'] = $goodsId;
  837. }
  838. if (empty($conditions)){
  839. return ResultWrapper::success($returnData);
  840. }
  841. //获取这批商品活动价格信息,一般情况下只会有一个shopId
  842. $activityData = [];
  843. foreach ($conditions as $shopId => $condition){
  844. $result = self::selectCondition($condition);
  845. if (!$result->isSuccess()){
  846. return ResultWrapper::fail($result->getData(),$result->getErrorCode());
  847. }
  848. $activityResult = $result->getData();
  849. $activityData = array_merge($activityData,$activityResult);
  850. }
  851. if (empty($activityData)){
  852. return ResultWrapper::success($returnData);
  853. }
  854. //将数据的格式统一为,全国价格格式
  855. unset($returnData);
  856. $returnData = [];
  857. unset($conditions);
  858. foreach ($activityData as $item){
  859. $returnData[$item['shopId']][$item['goodsId']][$item['skuId']] = [
  860. 'activityPrice' => $item['price'],
  861. 'goodsId' => $item['goodsId'],
  862. 'basicGoodsId' => $item['basicGoodsId'],
  863. 'skuId' => $item['skuId'],
  864. 'shopId' => $item['shopId'],
  865. 'activityNum' => $item['activityNum'],//活动限购数量
  866. 'limitNum' => $item['limitNum'],//用户限购数量
  867. 'activityId' => $item['activityId'],
  868. 'activityName' => $item['title'],
  869. 'haveBuyNum' => $item['haveBuyNum'],//活动已购数量
  870. ];
  871. $conditions['activity'][$item['shopId']][] = $item['activityId'];
  872. }
  873. //获取用户商品的已购数量
  874. $conditions['customerId'] = isset($selectParams['customerId']) ? $selectParams['customerId'] : 0;
  875. $activityUserLogResult = self::getAllowBuyNumByParams($conditions);
  876. if (!$activityUserLogResult->isSuccess()){
  877. return ResultWrapper::fail($activityUserLogResult->getData(),$activityUserLogResult->getErrorCode());
  878. }
  879. $activityUserLogData = $activityUserLogResult->getData();
  880. //计算活动商品用户剩余可购买数量,活动商品剩余数量
  881. foreach ($returnData as $shopId => $datum){
  882. foreach ($datum as $goodsId => $items){
  883. foreach ($items as $skuId => $item){
  884. //获取此活动用户已购数量
  885. $buyLogNum = isset($activityUserLogData[$shopId][$goodsId][$skuId][$item['activityId']]) ? $activityUserLogData[$shopId][$goodsId][$skuId][$item['activityId']]['num'] : 0;
  886. $returnData[$shopId][$goodsId][$skuId]['userBuyLogNum'] = $buyLogNum;//用户已购数量 (可购数量+已购数量=用户限购数量)
  887. $returnData[$shopId][$goodsId][$skuId]['userAllowNum'] = bcsub($item['limitNum'],$buyLogNum,0);//用户可购数量
  888. $returnData[$shopId][$goodsId][$skuId]['activityAllowNum'] = bcsub($item['activityNum'],$item['haveBuyNum'],0);//活动剩余数量
  889. }
  890. }
  891. }
  892. return ResultWrapper::success($returnData);
  893. }
  894. /**
  895. * Doc: (des="获取活动的详情")
  896. * User: XMing
  897. * Date: 2020/8/5
  898. * Time: 9:35 上午
  899. * @param int $activityId
  900. * @param int $skuId
  901. * @return ResultWrapper
  902. *
  903. */
  904. public function getActivityDetails(int $activityId,int $skuId)
  905. {
  906. $fields = 'a.id,a.deleteStatus,a.auditStatus,a.startTime,a.endTime,goodsId,g.skuId,g.limitNum,g.activityNum,g.haveBuyNum';
  907. $sql = 'SELECT '.$fields.' FROM qianniao_activity_'.$this->onlineEnterpriseId.' as a
  908. LEFT JOIN qianniao_activity_goods_'.$this->onlineEnterpriseId.' as g
  909. ON g.activityId = a.id WHERE
  910. a.id = '.$activityId;
  911. if (!empty($skuId)){
  912. $sql .= ' AND g.skuId = '.$skuId;
  913. }
  914. $activityDetails = $this->objDActivity->query($sql);
  915. if ($activityDetails === false){
  916. return ResultWrapper::fail($this->objDActivity->error(),ErrorCode::$dberror);
  917. }
  918. $activityDetails = empty($activityDetails) ? [] : array_shift($activityDetails);
  919. return ResultWrapper::success($activityDetails);
  920. }
  921. }