PublicRankingForm.php 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010
  1. <?php
  2. /**
  3. * 重庆赤晓店信息科技有限公司
  4. * https://www.chixiaodian.com
  5. * Copyright (c) 2023 赤店商城 All rights reserved.
  6. */
  7. namespace app\modules\admin\models\publicRanking;
  8. use app\models\Option;
  9. use app\constants\OptionSetting;
  10. use app\models\User;
  11. use app\models\SaasUser;
  12. use app\utils\Notice\NoticeSend;
  13. use app\modules\client\models\v1\ShareQrcodeForm;
  14. use app\utils\Baidu\BaiduAiTools;
  15. use app\utils\DeepSeek\DeepSeekAiTools;
  16. use app\models\AccountLog;
  17. use app\models\GivingGiftsOrder;
  18. use app\models\GivingGiftsGoods;
  19. use app\models\Order;
  20. use app\modules\admin\models\VideoShopForm;
  21. use app\modules\admin\models\WechatThirdForm;
  22. use app\utils\Wechat\WechatMini;
  23. use EasyWeChat\Kernel\BaseClient;
  24. use app\models\Promoter;
  25. use app\models\Goods;
  26. use app\models\VideoShopGoodsExt;
  27. use app\models\PublicRankingUser;
  28. use app\models\VideoShopOrderExt;
  29. use app\models\PublicRankingTask;
  30. class PublicRankingForm extends Model {
  31. public $store_id;
  32. public $id;
  33. public $ids;
  34. public $goods_name;
  35. public $supplier_name;
  36. public $goods_id;
  37. public $cat_id;
  38. public $supplier_id;
  39. public $warehouse_id;
  40. public $warehouse_zone_id;
  41. public $is_delete;
  42. public $warning_num;
  43. public $eiId;
  44. public $eipId;
  45. public $nickname;
  46. public $phone;
  47. public $order_no;
  48. public $type;
  49. public $purchase_in_price;
  50. public static function leagueItemStatusName($status = null) {
  51. $arr = [
  52. 1 => '已上架推广',
  53. 2 => '已下架推广',
  54. 4 => '已删除',
  55. 5 => '未达到准入标准',
  56. 10 => '待生效',
  57. ];
  58. if($status === null){
  59. return $arr;
  60. }
  61. return isset($arr[$status]) ? $arr[$status] : '';
  62. }
  63. public static function leagueItemTypeName($status = null) {
  64. $arr = [
  65. 1 => '普通推广商品',
  66. 2 => '定向推广商品',
  67. 3 => '专属推广商品',
  68. ];
  69. if($status === null){
  70. return $arr;
  71. }
  72. return isset($arr[$status]) ? $arr[$status] : '';
  73. }
  74. public function init() {
  75. parent::init();
  76. if (empty($this->store_id)) {
  77. $this->store_id = get_store_id();
  78. }
  79. }
  80. public static function afterOrderSave($order, $insert = 0, $changedAttributes = []) {
  81. try{
  82. $store_id = $order->store_id;
  83. if(!$order->user_id){
  84. return;
  85. }
  86. $orderExt = VideoShopOrderExt::find()->where(['store_id' => $store_id, 'order_id' => $order->id])->one();
  87. if(!$orderExt){
  88. return;
  89. }
  90. $promoter_ids = explode(',', $orderExt->promoter_id);
  91. if($promoter_ids){
  92. $promoter_id = $promoter_ids[0];
  93. if($order->is_sale){
  94. $doTask = PublicRankingTask::doTask($store_id, $order->user_id, $promoter_id, $order);
  95. debug_log([__METHOD__, __LINE__, $store_id, $order->id, $insert, $promoter_id, $doTask ? $doTask->id : $doTask, $changedAttributes], __CLASS__ . '.log');
  96. }
  97. }
  98. } catch (\Exception $ex) {
  99. \Yii::error($ex);
  100. debug_log([__METHOD__, __LINE__, $order->id, $insert, $changedAttributes, $ex->getMessage()], __CLASS__ . '.log');
  101. return [
  102. 'code' => 1,
  103. 'msg' => $ex->getMessage(),
  104. ];
  105. }
  106. }
  107. public static function afterVideoShopOrderExtSave($order, $insert = 0, $changedAttributes = []) {
  108. try{
  109. if (!$insert && isset($changedAttributes['commission_status']) && $order->commission_status == 2) {
  110. //复购
  111. $price2Fugou = self::price2Fugou($order);
  112. debug_log([__METHOD__, __LINE__, '复购', $order->id, $price2Fugou], __CLASS__ . '.log');
  113. }
  114. } catch (\Exception $ex) {
  115. \Yii::error($ex);
  116. debug_log([__METHOD__, __LINE__, $order->id, $ex->getMessage()], __CLASS__ . '.log');
  117. return [
  118. 'code' => 1,
  119. 'msg' => $ex->getMessage(),
  120. ];
  121. }
  122. }
  123. public static function url_callback($store_id = 0, $mini_id = 0) {
  124. $url_callback = '';
  125. if(empty($mini_id)){
  126. return '需要先设置小店信息';
  127. }
  128. if (\Yii::$app instanceof \yii\web\Application){
  129. $url_callback = \Yii::$app->request->hostInfo . '/index.php/wechat/video-shop-order/callback/' . $mini_id;
  130. }
  131. return $url_callback;
  132. }
  133. public static function url_callback_decode($code = '') {
  134. $codeArr = explode('_', $code);
  135. if($codeArr[0] !== 'PublicRanking'){
  136. return false;
  137. }
  138. return [
  139. 'store_id' => $codeArr[1],
  140. ];
  141. }
  142. public static $confs = [];
  143. public static function conf($store_id = 0, $refresh = 0) {
  144. if (isset(self::$confs[$store_id]) && !$refresh) {
  145. return self::$confs[$store_id];
  146. }
  147. $confDef = [
  148. 'is_open' => 0,
  149. //规则
  150. 'PublicRankingRow' => 0, //3人公排(33公排)或2人公排(22公排) ○若已有公排点位,不可修改此项
  151. 'task_count' => 10, //任务单数
  152. 'finder_name' => '', //视频号名字
  153. 'finder_id' => '', //视频号id
  154. 'promoter_id' => '', //达人带货id
  155. 'info_ids' => [], //定向推广id数组,用于自动绑定新达人
  156. //小店配置
  157. 'mini_id' => '',
  158. 'app_id' => '',
  159. 'app_secret' => '',
  160. 'token' => '',
  161. 'encodingAesKey' => '',
  162. //复购
  163. 'price2Fugou' => '', //强制复购金额:佣金达到强制复购金额后,需重新完成任务,保完成后才能获得对应层级奖金
  164. //躺赚
  165. 'auto_price_child_cnt' => '', //躺赚直推人数
  166. 'auto_price_wait_days' => '', //躺赚直推等待天数
  167. ];
  168. $conf = Option::get(OptionSetting::PUBLIC_RANKING_SETTING, $store_id, 'store')['value'];
  169. if ($conf) {
  170. $conf = array_merge($confDef, json_decode($conf, true));
  171. } else {
  172. $conf = $confDef;
  173. }
  174. self::$confs[$store_id] = $conf;
  175. return $conf;
  176. }
  177. public static function confSave($store_id = 0, $config = []) {
  178. $oldConf = self::conf($store_id, 1);
  179. $conf = array_merge($oldConf, $config);
  180. $saveStoreMini = self::saveStoreMini($store_id, $conf);
  181. if($saveStoreMini['code']){
  182. return $saveStoreMini;
  183. }
  184. $conf['mini_id'] = $saveStoreMini['data']['id'];
  185. $set = Option::set(OptionSetting::PUBLIC_RANKING_SETTING, json_encode($conf, JSON_UNESCAPED_UNICODE), $store_id, 'store');
  186. self::conf($store_id, 1);
  187. return [
  188. 'code' => 0,
  189. 'msg' => 'ok',
  190. '$save' => $set,
  191. ];
  192. }
  193. public static function isopen($store_id = 0) {
  194. $conf = self::conf($store_id);
  195. $isopen = $conf['is_open'];
  196. return empty($isopen) ? 0 : 1;
  197. }
  198. //添加小店
  199. public static function saveStoreMini($store_id, $conf) {
  200. $form = new VideoShopForm();
  201. $form->params = [
  202. 'app_id' => $conf['app_id'],
  203. 'app_secret' => $conf['app_secret'],
  204. 'token' => $conf['token'],
  205. 'encodingAesKey' => $conf['encodingAesKey'],
  206. ];
  207. $form->store_id = $store_id;
  208. $res = $form->addShop();
  209. return $res;
  210. }
  211. //添加小店
  212. public static function getStoreMini($store_id, &$conf) {
  213. if(empty($conf['app_id'])){
  214. return null;
  215. }
  216. $form = new WechatThirdForm();
  217. $form->appid = $conf['app_id'];
  218. $form->store_id = $store_id;
  219. $form->fuwu_type = 1;
  220. $res = $form->getMiniList();
  221. $mini = $res['data'][0];
  222. if($res['data'][0]){
  223. $conf['app_secret'] = $mini['app_secret'];
  224. $conf['token'] = $mini['token'];
  225. $conf['encodingAesKey'] = $mini['encodingAesKey'];
  226. }
  227. return $mini;
  228. }
  229. //躺赚
  230. public static function isAutoPriceSuccess($store_id, $user_id) {
  231. $publicRankingUser = PublicRankingUser::findOne(['user_id' => $user_id]);
  232. $conf = self::conf($store_id);
  233. $conf_auto_price_child_cnt = $conf['auto_price_child_cnt'];
  234. $conf_auto_price_wait_days = $conf['auto_price_wait_days'];
  235. if($conf_auto_price_child_cnt <= 0){
  236. return true;
  237. }
  238. if($conf_auto_price_wait_days > 0 && ($publicRankingUser['created_at'] > (time() - 86400 * $conf_auto_price_wait_days))){
  239. return true;
  240. }
  241. $childCnt = PublicRankingUser::find()->where(['user_id' => User::find()->select('id')->where(['old_parent_id' => $user_id])])->count();
  242. if($childCnt >= $conf_auto_price_child_cnt){
  243. return true;
  244. }
  245. return false;
  246. }
  247. //复购
  248. public static function price2Fugou(VideoShopOrderExt $order) {
  249. $store_id = $order->store_id;
  250. $promoter_id = $order->promoter_id;
  251. debug_log([__METHOD__, __LINE__, '检测复购', $store_id, $promoter_id], __CLASS__ . '.log');
  252. $conf = self::conf($store_id);
  253. $conf_price2Fugou = $conf['price2Fugou'];
  254. if($conf_price2Fugou <= 0){
  255. debug_log([__METHOD__, __LINE__, '强制复购金额未配置', $store_id, $promoter_id], __CLASS__ . '.log');
  256. return null;
  257. }
  258. $prom = Promoter::findOne(['store_id' => $store_id, 'promoter_id' => $promoter_id]);
  259. if(!$prom){
  260. debug_log([__METHOD__, __LINE__, '达人未绑定', $store_id, $promoter_id], __CLASS__ . '.log');
  261. return null;
  262. }
  263. $promPriceTotal = VideoShopOrderExt::promoterPriceTotal($store_id, $promoter_id, 0);
  264. if($promPriceTotal >= $conf_price2Fugou){
  265. $t = \Yii::$app->db->beginTransaction();
  266. try {
  267. $updateAll = VideoShopOrderExt::updateAll(['has_fugou' => 1], ['store_id' => $store_id, 'promoter_id' => $promoter_id, 'has_fugou' => 0, 'commission_status' => 2]);
  268. $prom->is_fugou = 1;
  269. if(!$prom->save()){
  270. throw new \Exception(array_shift($prom->getFirstErrors()));
  271. }
  272. $genTaskFugou = PublicRankingTask::genTaskFugou($store_id, $prom->user_id);
  273. $t->commit();
  274. debug_log([__METHOD__, __LINE__, '检测复购', $order->id, $updateAll, $genTaskFugou, $prom->id], __CLASS__ . '.log');
  275. return true;
  276. } catch (\Exception $e) {
  277. $t->rollBack();
  278. \Yii::error($e);
  279. debug_log([__METHOD__, __LINE__, '检测复购', $store_id, $order->id, $e->getMessage()], __CLASS__ . '.log');
  280. }
  281. }
  282. return false;
  283. }
  284. public static function _promoterList($store_id, $pageSize = 10) {
  285. try {
  286. $conf = self::conf($store_id);
  287. if(!$conf['mini_id']){
  288. throw new \Exception('请先配置参数');
  289. }
  290. $url = 'channels/ec/league/promoter/list/get';
  291. $data = [
  292. "page_size" => (int)$pageSize,
  293. ];
  294. $miniProgram = WechatMini::getWechatConfig($store_id, $conf['mini_id'], 1);
  295. $client = new BaseClient($miniProgram);
  296. $res = $client->httpPostJson($url, $data);
  297. if (!$res['errcode'] && !empty($res)) {
  298. // foreach((array)$res['finder_ids'] as &$item){
  299. // $res['finder_list'][] = self::_promoterGet($store_id, '', $item);
  300. // }
  301. foreach((array)$res['promoter_ids'] as &$item){
  302. $res['promoter_list'][] = self::_promoterGet($store_id, $item);
  303. }
  304. return [
  305. 'code' => 0,
  306. 'msg' => 'ok',
  307. 'data' => $res,
  308. ];
  309. }
  310. return [
  311. 'code' => $res['errcode'] ?? 1,
  312. 'msg' => $res['errmsg'] ?? '系统错误',
  313. 'data' => $res,
  314. ];
  315. } catch (\Exception $e) {
  316. \Yii::error($e);
  317. debug_log([__METHOD__, __LINE__, $store_id, $data, $res, $e->getMessage()], __CLASS__ . '.log');
  318. return [
  319. 'code' => $e->getCode() ?: 1,
  320. 'msg' => $e->getMessage() . $e->getLine()
  321. ];
  322. }
  323. }
  324. public static function promoterList($store_id, $params = []) {
  325. $conf = self::conf($store_id);
  326. $query = Promoter::find()->where(['store_id' => $store_id, 'is_delete' => 0]);
  327. $params['promoter_id'] && $query->andWhere(['promoter_id' => $params['promoter_id']]);
  328. $params['finder_id'] && $query->andWhere(['finder_id' => $params['finder_id']]);
  329. if($params['user_name']){
  330. $query->andWhere(['user_id' => User::find()->alias('u')->leftJoin(['su' => SaasUser::tableName()], 'u.binding=su.mobile')->select('u.id')->where(['like', 'su.name', $params['user_name']])]);
  331. }
  332. if($params['mobile']){
  333. $query->andWhere(['user_id' => User::find()->select('id')->where(['like', 'binding', $params['mobile']])]);
  334. }
  335. if($params['time_begin']){
  336. $query->andWhere(['>=', 'created_at', strtotime($params['time_begin'])]);
  337. }
  338. if($params['time_end']){
  339. $query->andWhere(['<=', 'created_at', strtotime($params['time_end'])]);
  340. }
  341. if(isset($params['status']) && $params['status'] > -1){
  342. $query->andWhere(['status' => $params['status']]);
  343. }
  344. $query->orderBy('id DESC');
  345. $data = pagination_make($query);
  346. foreach($data['list'] as &$item){
  347. $item['isPromoterIdSameStoreConf'] = $item['promoter_id'] == $conf['promoter_id'];
  348. $item['user'] = User::findOne($item['user_id']);
  349. $item['saas_user'] = $item['user'] ? SaasUser::findOne(['mobile' => $item['user']['binding']]) : null;
  350. $pInfo = self::_promoterGet($store_id, $item['promoter_id']);
  351. $item['promoterInfo'] = $pInfo;
  352. if($pInfo['data']){
  353. $item['status'] = $pInfo['data']['status'];
  354. }
  355. $item['status_name'] = Promoter::statusName($item['status']);
  356. $item['priceTotal'] = VideoShopOrderExt::promoterPriceTotal($store_id, $item['promoter_id']);
  357. }
  358. return [
  359. 'code' => 0,
  360. 'msg' => 'ok',
  361. 'data' => $data,
  362. 'status_list' => Promoter::statusName(),
  363. ];
  364. }
  365. public static function _promoterGet($store_id, $promoter_id = '', $finder_id = '') {
  366. try {
  367. $finder_id = $promoter_id ? '' : $finder_id;
  368. $conf = self::conf($store_id);
  369. $url = 'channels/ec/league/promoter/get';
  370. $data = [];
  371. $promoter_id && $data['promoter_id'] = (string)$promoter_id;
  372. $finder_id && $data['finder_id'] = (string)$finder_id;
  373. $miniProgram = WechatMini::getWechatConfig($store_id, $conf['mini_id'], 1);
  374. $client = new BaseClient($miniProgram);
  375. $res = $client->httpPostJson($url, $data);
  376. if (!$res['errcode'] && !empty($res)) {
  377. return [
  378. 'code' => 0,
  379. 'msg' => 'ok',
  380. 'data' => $res['promoter'],
  381. ];
  382. }
  383. return [
  384. 'code' => $res['errcode'] ?? 1,
  385. 'msg' => $res['errmsg'] ?? '系统错误',
  386. 'data' => $res,
  387. ];
  388. } catch (\Exception $e) {
  389. \Yii::error($e);
  390. return [
  391. 'code' => $e->getCode() ?: 1,
  392. 'msg' => $e->getMessage() . $e->getLine()
  393. ];
  394. }
  395. }
  396. public static function syncPromoter($store_id, $promoter_id = '') {
  397. try {
  398. $count = 0;
  399. $query = Promoter::find()->where(['store_id' => $store_id]);
  400. if($promoter_id){
  401. $query->andWhere(['promoter_id' => $promoter_id]);
  402. }
  403. $pList = $query->all();
  404. foreach($pList as $p){
  405. $pInfo = self::_promoterGet($store_id, $p->promoter_id);
  406. if(!$pInfo['code']){
  407. $status = $pInfo['data']['status'];
  408. $ucount = Promoter::updateAll(['status' => $status], ['store_id' => $store_id, 'promoter_id' => $p->promoter_id]);
  409. $count += $ucount;
  410. if($status == 2 && $ucount){
  411. self::leagueItemBind($store_id, [$p->promoter_id]);
  412. }
  413. }else{
  414. debug_log([__FUNCTION__, __LINE__, $store_id, $p->promoter_id, $pInfo], __CLASS__);
  415. }
  416. }
  417. return [
  418. 'code' => 0,
  419. 'msg' => '同步成功,修改数量:' . $count,
  420. 'data' => $count,
  421. ];
  422. } catch (\Exception $e) {
  423. \Yii::error($e);
  424. return [
  425. 'code' => $e->getCode() ?: 1,
  426. 'msg' => $e->getMessage() . $e->getLine()
  427. ];
  428. }
  429. }
  430. public static function _promoterAdd($store_id, $promoter_id = '', $finder_id = '') {
  431. try {
  432. $finder_id = $promoter_id ? '' : $finder_id;
  433. $conf = self::conf($store_id);
  434. $url = 'channels/ec/league/promoter/add';
  435. $data = [];
  436. $promoter_id && $data['promoter_id'] = (string)$promoter_id;
  437. $finder_id && $data['finder_id'] = (string)$finder_id;
  438. $miniProgram = WechatMini::getWechatConfig($store_id, $conf['mini_id'], 1);
  439. $client = new BaseClient($miniProgram);
  440. $res = $client->httpPostJson($url, $data);
  441. if (!$res['errcode'] && !empty($res)) {
  442. return [
  443. 'code' => 0,
  444. 'msg' => 'ok',
  445. 'data' => $res,
  446. ];
  447. }
  448. return [
  449. 'code' => $res['errcode'] ?? 1,
  450. 'msg' => $res['errmsg'] ?? '系统错误',
  451. 'data' => $res,
  452. ];
  453. } catch (\Exception $e) {
  454. \Yii::error($e);
  455. return [
  456. 'code' => $e->getCode() ?: 1,
  457. 'msg' => $e->getMessage() . $e->getLine()
  458. ];
  459. }
  460. }
  461. public static function _promoterUpd($store_id, $type, $promoter_id = '', $finder_id = '') {
  462. try {
  463. $finder_id = $promoter_id ? '' : $finder_id;
  464. $conf = self::conf($store_id);
  465. $url = 'channels/ec/league/promoter/upd';
  466. $data = [
  467. 'type' => $type,
  468. ];
  469. $promoter_id && $data['promoter_id'] = (string)$promoter_id;
  470. $finder_id && $data['finder_id'] = (string)$finder_id;
  471. $miniProgram = WechatMini::getWechatConfig($store_id, $conf['mini_id'], 1);
  472. $client = new BaseClient($miniProgram);
  473. $res = $client->httpPostJson($url, $data);
  474. if (!$res['errcode'] && !empty($res)) {
  475. return [
  476. 'code' => 0,
  477. 'msg' => 'ok',
  478. 'data' => $res,
  479. ];
  480. }
  481. return [
  482. 'code' => $res['errcode'] ?? 1,
  483. 'msg' => $res['errmsg'] ?? '系统错误',
  484. 'data' => $res,
  485. ];
  486. } catch (\Exception $e) {
  487. \Yii::error($e);
  488. return [
  489. 'code' => $e->getCode() ?: 1,
  490. 'msg' => $e->getMessage() . $e->getLine()
  491. ];
  492. }
  493. }
  494. public static function _promoterDelete($store_id, $promoter_id = '', $finder_id = '') {
  495. try {
  496. $finder_id = $promoter_id ? '' : $finder_id;
  497. $conf = self::conf($store_id);
  498. $url = 'channels/ec/league/promoter/delete';
  499. $data = [];
  500. $promoter_id && $data['promoter_id'] = (string)$promoter_id;
  501. $finder_id && $data['finder_id'] = (string)$finder_id;
  502. $miniProgram = WechatMini::getWechatConfig($store_id, $conf['mini_id'], 1);
  503. $client = new BaseClient($miniProgram);
  504. $res = $client->httpPostJson($url, $data);
  505. if (!$res['errcode'] && !empty($res)) {
  506. return [
  507. 'code' => 0,
  508. 'msg' => 'ok',
  509. 'data' => $res,
  510. ];
  511. }
  512. return [
  513. 'code' => $res['errcode'] ?? 1,
  514. 'msg' => $res['errmsg'] ?? '系统错误',
  515. 'data' => $res,
  516. 'p' => $data,
  517. ];
  518. } catch (\Exception $e) {
  519. \Yii::error($e);
  520. return [
  521. 'code' => $e->getCode() ?: 1,
  522. 'msg' => $e->getMessage() . $e->getLine()
  523. ];
  524. }
  525. }
  526. public static function promoterAdd($store_id, $user_id, $promoter_id = '', $finder_id = '', $finder_name = '') {
  527. $apiProm = self::_promoterGet($store_id, $promoter_id);
  528. if($apiProm['code']){
  529. return $apiProm;
  530. }
  531. $promoter = $apiProm['data'];
  532. $apiFind = self::_promoterGet($store_id, $finder_id);
  533. if($apiFind['code']){
  534. return $apiFind;
  535. }
  536. if(!in_array($promoter['status'], [1,2])){
  537. $api = self::_promoterAdd($store_id, $promoter_id, $finder_id);
  538. if($api['code']){
  539. return $api;
  540. }
  541. }
  542. $add = Promoter::add($store_id, $user_id, $promoter_id, $finder_id, $finder_name);
  543. self::syncPromoter($store_id, $promoter_id);
  544. return $add;
  545. }
  546. public static function promoterReadd($store_id, $promoter_id = '') {
  547. return self::_promoterAdd($store_id, $promoter_id);
  548. }
  549. public static function promoterUpd($store_id, $type, $promoter_id = '', $finder_id = '') {
  550. $api = self::_promoterUpd($store_id, $type, $promoter_id, $finder_id);
  551. if($api['code']){
  552. return $api;
  553. }
  554. self::syncPromoter($store_id, $promoter_id);
  555. return $api;
  556. }
  557. public static function promoterDelete($store_id, $promoter_id = '', $finder_id = '') {
  558. $api = self::_promoterDelete($store_id, $promoter_id, $finder_id);
  559. if($api['code']){
  560. return $api;
  561. }
  562. self::syncPromoter($store_id, $promoter_id);
  563. return $api;
  564. }
  565. public static function _leagueItemBatchadd($store_id, $type, $list, $promoter_ids = [], $is_forerver = 1, $begin_time = 10, $end_time = 100) {
  566. try {
  567. $conf = self::conf($store_id);
  568. $url = 'channels/ec/league/item/batchadd';
  569. $data = [
  570. 'type' => (int)$type,
  571. 'list' => $list,
  572. 'promoter_ids' => $promoter_ids,
  573. 'is_forerver' => (bool)$is_forerver,
  574. ];
  575. if(!$is_forerver){
  576. $data['begin_time'] = (int)$begin_time;
  577. $data['end_time'] = (int)$end_time;
  578. }
  579. $miniProgram = WechatMini::getWechatConfig($store_id, $conf['mini_id'], 1);
  580. $client = new BaseClient($miniProgram);
  581. $res = $client->httpPostJson($url, $data);
  582. if (!$res['errcode'] && !empty($res)) {
  583. return [
  584. 'code' => 0,
  585. 'msg' => 'ok',
  586. 'data' => $res,
  587. ];
  588. }
  589. return [
  590. 'code' => $res['errcode'] ?? 1,
  591. 'msg' => $res['errmsg'] ?? '系统错误',
  592. 'data' => $res,
  593. ];
  594. } catch (\Exception $e) {
  595. \Yii::error($e);
  596. return [
  597. 'code' => $e->getCode() ?: 1,
  598. 'msg' => $e->getMessage() . $e->getLine()
  599. ];
  600. }
  601. }
  602. public static function _leagueItemUpd($store_id, $type, $operate_type, $product_id = null, $info_id = null, $ratio = null, $exclusive_info = null) {
  603. try {
  604. $conf = self::conf($store_id);
  605. $url = 'channels/ec/league/item/upd';
  606. $data = [
  607. 'type' => (int)$type,
  608. 'operate_type' => (int)$operate_type,
  609. ];
  610. $info_id && $data['info_id'] = (string)$info_id;
  611. $product_id && $data['product_id'] = (string)$product_id;
  612. $ratio && $data['ratio'] = (int)$ratio;
  613. $exclusive_info && $data['exclusive_info'] = $exclusive_info;
  614. $miniProgram = WechatMini::getWechatConfig($store_id, $conf['mini_id'], 1);
  615. $client = new BaseClient($miniProgram);
  616. $res = $client->httpPostJson($url, $data);
  617. if (!$res['errcode'] && !empty($res)) {
  618. return [
  619. 'code' => 0,
  620. 'msg' => 'ok',
  621. 'data' => $res,
  622. 'p' => $data,
  623. ];
  624. }
  625. return [
  626. 'code' => $res['errcode'] ?? 1,
  627. 'msg' => $res['errmsg'] ?? '系统错误',
  628. 'data' => $res,
  629. ];
  630. } catch (\Exception $e) {
  631. \Yii::error($e);
  632. return [
  633. 'code' => $e->getCode() ?: 1,
  634. 'msg' => $e->getMessage() . $e->getLine()
  635. ];
  636. }
  637. }
  638. public static function _leagueItemDelete($store_id, $type, $product_id = null, $info_id = null) {
  639. try {
  640. $conf = self::conf($store_id);
  641. $url = 'channels/ec/league/item/delete';
  642. $data = [
  643. 'type' => (int)$type,
  644. ];
  645. $info_id && $data['info_id'] = (string)$info_id;
  646. $product_id && $data['product_id'] = (string)$product_id;
  647. $miniProgram = WechatMini::getWechatConfig($store_id, $conf['mini_id'], 1);
  648. $client = new BaseClient($miniProgram);
  649. $res = $client->httpPostJson($url, $data);
  650. if (!$res['errcode'] && !empty($res)) {
  651. return [
  652. 'code' => 0,
  653. 'msg' => 'ok',
  654. 'data' => $res,
  655. ];
  656. }
  657. return [
  658. 'code' => $res['errcode'] ?? 1,
  659. 'msg' => $res['errmsg'] ?? '系统错误',
  660. 'data' => $res,
  661. ];
  662. } catch (\Exception $e) {
  663. \Yii::error($e);
  664. return [
  665. 'code' => $e->getCode() ?: 1,
  666. 'msg' => $e->getMessage() . $e->getLine()
  667. ];
  668. }
  669. }
  670. public static function _leagueItemListGet($store_id, $type, $promoter_id = '', $product_id = null, $page_size = 10, $page_index = 1, $need_total_num = 1) {
  671. try {
  672. if($type == 1 && $product_id){
  673. return [
  674. 'code' => 0,
  675. 'data' => [
  676. 'items' => [['product_id' => $product_id]],
  677. ],
  678. ];
  679. }
  680. $conf = self::conf($store_id);
  681. $url = 'channels/ec/league/item/list/get';
  682. $data = [
  683. 'type' => (int)$type,
  684. 'page_size' => (int)$page_size,
  685. ];
  686. $promoter_id && $data['promoter_id'] = (string)$promoter_id;
  687. $product_id && $data['product_id'] = (string)$product_id;
  688. $page_index && $data['page_index'] = (int)$page_index;
  689. $need_total_num && $data['need_total_num'] = (bool)$need_total_num;
  690. $miniProgram = WechatMini::getWechatConfig($store_id, $conf['mini_id'], 1);
  691. $client = new BaseClient($miniProgram);
  692. $res = $client->httpPostJson($url, $data);
  693. if (!$res['errcode'] && !empty($res)) {
  694. return [
  695. 'code' => 0,
  696. 'msg' => 'ok',
  697. 'data' => $res,
  698. 'p' => $data,
  699. ];
  700. }
  701. return [
  702. 'code' => $res['errcode'] ?? 1,
  703. 'msg' => $res['errmsg'] ?? '系统错误',
  704. 'data' => $res,
  705. ];
  706. } catch (\Exception $e) {
  707. \Yii::error($e);
  708. return [
  709. 'code' => $e->getCode() ?: 1,
  710. 'msg' => $e->getMessage() . $e->getLine()
  711. ];
  712. }
  713. }
  714. public static function _leagueItemGet($store_id, $type, $product_id = null, $info_id = null, $page_size = 10, $page_index = 1, $need_total_num = 1, $need_relation = 1) {
  715. try {
  716. $conf = self::conf($store_id);
  717. $url = 'channels/ec/league/item/get';
  718. $data = [
  719. 'type' => (int)$type,
  720. 'page_size' => (int)$page_size,
  721. ];
  722. $info_id && $data['info_id'] = (string)$info_id;
  723. $product_id && $data['product_id'] = (string)$product_id;
  724. $page_index && $data['page_index'] = (int)$page_index;
  725. $need_total_num && $data['need_total_num'] = (bool)$need_total_num;
  726. $need_relation && $data['need_relation'] = (bool)$need_relation;
  727. $miniProgram = WechatMini::getWechatConfig($store_id, $conf['mini_id'], 1);
  728. $client = new BaseClient($miniProgram);
  729. $res = $client->httpPostJson($url, $data);
  730. if (!$res['errcode'] && !empty($res)) {
  731. return [
  732. 'code' => 0,
  733. 'msg' => 'ok',
  734. 'data' => $res['item'],
  735. ];
  736. }
  737. return [
  738. 'code' => $res['errcode'] ?? 1,
  739. 'msg' => $res['errmsg'] ?? '系统错误',
  740. 'data' => $res,
  741. ];
  742. } catch (\Exception $e) {
  743. \Yii::error($e);
  744. return [
  745. 'code' => $e->getCode() ?: 1,
  746. 'msg' => $e->getMessage() . $e->getLine()
  747. ];
  748. }
  749. }
  750. public static function shopProductSelectList($store_id) {
  751. $list = VideoShopGoodsExt::find()->alias('ge')->leftJoin(['g' => Goods::tableName()], 'g.id=ge.goods_id')->where(['ge.store_id' => $store_id])->select('g.name, ge.product_id')->asArray()->all();
  752. return $list;
  753. }
  754. public static function leagueItemList($store_id, $type, $promoter_id = '', $product_id = null, $page_size = 10, $page_index = 1, $need_total_num = 1) {
  755. $api = self::_leagueItemListGet($store_id, $type, $promoter_id, $product_id, $page_size, $page_index, $need_total_num);
  756. if($api['code']){
  757. return $api;
  758. }
  759. $conf = self::conf($store_id);
  760. foreach($api['data']['items'] as &$item){
  761. $item['autoBind'] = in_array($item['info_id'], $conf['info_ids']);
  762. $goods_info = Goods::find()->where(['id' => VideoShopGoodsExt::find()->select('goods_id')->where(['store_id' => $store_id, 'product_id' => $item['product_id']])])->one();
  763. $item['goods_info'] = $goods_info;
  764. $info = self::_leagueItemGet($store_id, $type, $item['product_id'], $item['info_id'])['data'];
  765. if($info['exclusive_info']){
  766. foreach($info['exclusive_info']['promoter_info_list'] as &$pil){
  767. $promoter_id = $pil['promoter_id'];
  768. $prom = Promoter::findOne(['store_id' => $store_id, 'promoter_id' => $promoter_id]);
  769. $user = $prom['user_id'] ? User::findOne($prom['user_id']) : null;
  770. $saasUser = $user ? SaasUser::findOne(['mobile' => $user['binding']]) : null;
  771. $pil['prom'] = $prom;
  772. $pil['user'] = $user;
  773. $pil['saasUser'] = $saasUser;
  774. }
  775. }
  776. $info['status_name'] = self::leagueItemStatusName($info['status']);
  777. $info['type_name'] = self::leagueItemTypeName($info['type']);
  778. $item['info'] = $info;
  779. }
  780. return [
  781. 'code' => 0,
  782. 'msg' => 'ok',
  783. 'data' => $api['data'],
  784. ];
  785. }
  786. public static function leagueItemAutoBind($store_id, $info_id) {
  787. $conf = self::conf($store_id);
  788. if(!in_array($info_id, $conf['info_ids'])){
  789. $conf['info_ids'][] = $info_id;
  790. }else{
  791. $conf['info_ids'] = array_diff($conf['info_ids'], [$info_id]);
  792. }
  793. $conf['info_ids'] = array_unique($conf['info_ids']);
  794. return self::confSave($store_id, ['info_ids' => $conf['info_ids']]);
  795. }
  796. public static function leagueItemBind($store_id, $promoter_ids = []) {
  797. $conf = self::conf($store_id);
  798. $type = 2;
  799. foreach((array)$conf['info_ids'] as $info_id){
  800. $info = self::_leagueItemGet($store_id, $type, '', $info_id)['data'];
  801. if(!$info){
  802. return null;
  803. }
  804. $exclusive_info = ['add_promoter_ids' => $promoter_ids];
  805. if($info['exclusive_info']['promoter_info_list'][0]['is_forerver']){
  806. $exclusive_info['is_forerver'] = true;
  807. }else{
  808. $exclusive_info['begin_time'] = $info['exclusive_info']['promoter_info_list'][0]['begin_time'];
  809. $exclusive_info['end_time'] = $info['exclusive_info']['promoter_info_list'][0]['end_time'];
  810. }
  811. $bind = self::leagueItemUpd($store_id, $type, 1, '', $info_id, $info['ratio'], $exclusive_info);
  812. debug_log([$store_id, $promoter_ids, $info_id, $bind], __CLASS__);
  813. }
  814. return $bind;
  815. }
  816. public static function leagueItemAdd($store_id, $type, $list, $promoter_ids, $is_forerver, $begin_time, $end_time) {
  817. $api = self::_leagueItemBatchadd($store_id, $type, $list, $promoter_ids, $is_forerver, $begin_time, $end_time);
  818. return $api;
  819. }
  820. public static function leagueItemUpd($store_id, $type, $operate_type, $product_id, $info_id, $ratio, $exclusive_info) {
  821. $api = self::_leagueItemUpd($store_id, $type, $operate_type, $product_id, $info_id, $ratio, $exclusive_info);
  822. return $api;
  823. }
  824. public static function leagueItemDelete($store_id, $type, $product_id, $info_id) {
  825. $api = self::_leagueItemDelete($store_id, $type, $product_id, $info_id);
  826. return $api;
  827. }
  828. public static function publicRankingUserList($store_id, $params = []) {
  829. $query = PublicRankingUser::find()->where(['store_id' => $store_id, 'is_delete' => 0]);
  830. if(!empty($params['promoter_id'])){
  831. $query->andWhere(['user_id' => Promoter::find()->select('user_id')->where(['like', 'promoter_id', $params['promoter_id']])]);
  832. }
  833. if($params['user_name']){
  834. $query->andWhere(['user_id' => User::find()->select('id')->where(['like', 'nickname', $params['user_name']])]);
  835. }
  836. if($params['mobile']){
  837. $query->andWhere(['user_id' => User::find()->select('id')->where(['like', 'binding', $params['mobile']])]);
  838. }
  839. if($params['time_begin']){
  840. $query->andWhere(['>=', 'created_at', strtotime($params['time_begin'])]);
  841. }
  842. if($params['time_end']){
  843. $query->andWhere(['<=', 'created_at', strtotime($params['time_end'])]);
  844. }
  845. $query->orderBy('sort');
  846. $data = pagination_make($query);
  847. foreach($data['list'] as &$item){
  848. $item['promoter'] = Promoter::findOne(['user_id' => $item['user_id']]);
  849. $item['user'] = User::findOne($item['user_id']);
  850. $item['saas_user'] = $item['user'] ? SaasUser::findOne(['mobile' => $item['user']['binding']]) : null;
  851. $buyOrderCnt = (int)VideoShopOrderExt::find()->where(['store_id' => $store_id, 'order_id' => Order::find()->select('id')->where(['user_id' => $item['user_id']])])->andWhere(['!=', 'promoter_id', ''])->count();
  852. $item['buy_order_cnt'] = $buyOrderCnt;
  853. $childOrderCnt = $item['promoter'] ? (int)VideoShopOrderExt::find()->where(['store_id' => $store_id, 'promoter_id' => $item['promoter']['promoter_id']])->count() : 0;
  854. $item['child_order_cnt'] = $childOrderCnt;
  855. $item['task'] = PublicRankingTask::findAll(['user_id' => $item['user_id']]);
  856. }
  857. return [
  858. 'code' => 0,
  859. 'msg' => 'ok',
  860. 'data' => $data,
  861. ];
  862. }
  863. public static function publicRankingUserIndex($store_id, $user_id) {
  864. try{
  865. if(!self::isopen($store_id)){
  866. throw new \Exception('商城功能未开启');
  867. }
  868. $user = User::findOne($user_id);
  869. if(!$user['wechat_union_id']){
  870. return [
  871. 'code' => 1,
  872. 'msg' => '缺少unionid,请退出账号重新登陆',
  873. ];
  874. }
  875. $conf = self::conf($store_id);
  876. $prom = Promoter::findOne(['store_id' => $store_id, 'user_id' => $user_id]);
  877. $promPriceTotal = !$prom ? 0 : VideoShopOrderExt::promoterPriceTotal($store_id, $prom['promoter_id']);
  878. $taskIsOver = PublicRankingTask::taskIsOver($store_id, $user_id);
  879. $task1 = PublicRankingTask::findOne(['store_id' => $store_id, 'user_id' => $user_id, 'status' => 1]);
  880. $taskFinshCount = PublicRankingTask::find()->where(['store_id' => $store_id, 'user_id' => $user_id, 'status' => 1])->count();
  881. // $user = User::findOne($user_id);
  882. $publicRankingUser = PublicRankingUser::findOne(['user_id' => $user_id]);
  883. if($publicRankingUser && $publicRankingUser->sort > 1){
  884. $psort = PublicRankingUser::getParentSorts($publicRankingUser->sort, $conf['PublicRankingRow'], 1);
  885. $publicRankingUserParent = PublicRankingUser::findOne(['store_id' => $store_id, 'sort' => $psort]);
  886. $publicRankingUserParentUser = $publicRankingUserParent->user_id ? User::findOne($publicRankingUserParent->user_id) : null;
  887. $publicRankingUserParentSaasUser = $publicRankingUserParentUser ? SaasUser::findOne(['mobile' => $publicRankingUserParentUser->binding]) : null;
  888. }
  889. $parentUser = $user->old_parent_id ? User::findOne($user->old_parent_id) : null;
  890. $parentSaasUser = $parentUser ? SaasUser::findOne(['mobile' => $parentUser->binding]) : null;
  891. $isAutoPriceSuccess = self::isAutoPriceSuccess($store_id, $user_id);
  892. $isPriceSuccess = !$prom->is_fugou && $isAutoPriceSuccess;
  893. $childCnt = PublicRankingUser::find()->where(['user_id' => User::find()->select('id')->where(['old_parent_id' => $user_id])])->count();
  894. return [
  895. 'code' => 0,
  896. 'data' => [
  897. 'conf' => $conf,
  898. 'publicRankingUserParentUser' => $publicRankingUserParentUser,
  899. 'publicRankingUserParentSaasUser' => $publicRankingUserParentSaasUser,
  900. 'parentUser' => $parentUser,
  901. 'parentSaasUser' => $parentSaasUser,
  902. 'publicRankingUser' => $publicRankingUser,
  903. 'user' => $user,
  904. 'saas_user' => get_saas_user(),
  905. 'prom' => $prom,
  906. 'taskIsOver' => $taskIsOver,
  907. 'canToTask' => $publicRankingUser && !$taskIsOver,
  908. 'canBind' => $publicRankingUser && (!$prom || (!in_array($prom['status'], [0,1,2]))) && $task1,
  909. 'promPriceTotal' => $promPriceTotal,
  910. 'taskFinshCount' => $taskFinshCount,
  911. 'isAutoPriceSuccess' => $isAutoPriceSuccess,
  912. 'isPriceSuccess' => $isPriceSuccess,
  913. 'childCnt' => $childCnt,
  914. ],
  915. ];
  916. } catch (\Exception $e) {
  917. \Yii::error($e);
  918. debug_log([__METHOD__, __LINE__, $e->getMessage()], __CLASS__ . '.log');
  919. return [
  920. 'code' => 1,
  921. 'msg' => '操作失败,' . $e->getMessage()
  922. ];
  923. }
  924. }
  925. public static function publicRankingUserIndexTask($store_id, $user_id, $task_id = 0) {
  926. if($task_id){
  927. $task = [
  928. 'code' => 0,
  929. 'data' => PublicRankingTask::findAll(['id' => $task_id]),
  930. ];
  931. }else{
  932. $task = PublicRankingTask::getTask($store_id, $user_id);
  933. if($task['code']){
  934. return $task;
  935. }
  936. }
  937. $conf = self::conf($store_id);
  938. $openTask = 0;
  939. foreach($task['data'] as &$item){
  940. $item = $item->toArray();
  941. $prom = [
  942. 'finder_name' => $conf['finder_name'], //视频号名字
  943. 'finder_id' => $conf['finder_id'], //视频号id
  944. 'promoter_id' => $conf['promoter_id'], //达人带货id
  945. ];
  946. if($item['promoter_id']){
  947. $prom = Promoter::findOne($item['promoter_id']);
  948. }
  949. $item['prom'] = $prom;
  950. $item['openTask'] = 0;
  951. if(!$openTask && $item['status'] == 0){
  952. $openTask = 1;
  953. $item['openTask'] = 1;
  954. }
  955. }
  956. return $task;
  957. }
  958. public static function publicRankingUserIndexPromAdd($store_id, $user_id, $promoter_id, $finder_id, $finder_name) {
  959. $task = self::promoterAdd($store_id, $user_id, $promoter_id, $finder_id, $finder_name);
  960. return $task;
  961. }
  962. }