VerifyCardForm.php 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051
  1. <?php
  2. /**
  3. * 重庆赤晓店信息科技有限公司
  4. * https://www.chixiaodian.com
  5. * Copyright (c) 2023 赤店商城 All rights reserved.
  6. */
  7. namespace app\modules\admin\models;
  8. use app\models\Goods;
  9. use app\models\Md;
  10. use app\models\Shop;
  11. use app\models\VerifyCardLog;
  12. use app\models\VerifyShareLog;
  13. use app\models\VerifyShareUser;
  14. use app\models\Video;
  15. use app\models\User;
  16. use app\models\Store;
  17. use app\models\SaasUser;
  18. use app\models\VerifyCard;
  19. use app\utils\Export;
  20. use app\utils\ExportList;
  21. use app\models\VerifyCardSale;
  22. use app\models\VerifyCardAccount;
  23. use app\models\Order;
  24. use yii\base\Model;
  25. class VerifyCardForm extends Model
  26. {
  27. public $id;
  28. public $store_id;
  29. public $name;
  30. public $total_num;
  31. public $use_num;
  32. public $expire_day;
  33. public $money;
  34. public $price;
  35. public $pic_url;
  36. public $begin_time;
  37. public $end_time;
  38. public $sort;
  39. public $is_delete;
  40. // 12.8新增字段
  41. public $status;
  42. public $account_info;
  43. public $type;
  44. public $date;
  45. public $bg_pic_url;
  46. public $date_type;
  47. public $is_give;
  48. public $content;
  49. public $num;
  50. public $total_price;
  51. public $freight_id;
  52. public $savingsType;
  53. public $goods_ids;
  54. public $video_ids;
  55. public $send_times;
  56. //搜索
  57. public $search_key;
  58. public $search_is_show;
  59. public $search_shop_name;
  60. //导出
  61. public $fields;
  62. public $flag;
  63. public $is_business;
  64. public $business_type;
  65. public $share_user_id;
  66. public $form;
  67. public $user_nickname;
  68. public $user_mobile;
  69. public $verify_person_nickname;
  70. public $md_name;
  71. public $start_time;
  72. public $order_no;
  73. public $for_cash;
  74. public $use_type;
  75. public $export;
  76. public $account;
  77. public $is_unlimited;
  78. const SCENARIO_ADD = 'add';
  79. const SCENARIO_EDIT = 'edit';
  80. const SCENARIO_DEL = 'del';
  81. const SCENARIO_LIST = 'list';
  82. const USER_PLATFORM_TYPE = [
  83. User::USER_FROM_WECHAT => '微信小程序',
  84. User::USER_FROM_ALIPAY => '支付宝',
  85. User::USER_FROM_OFFICIAL_ACCOUNTS => '公众号',
  86. User::USER_FROM_APP => 'app微信',
  87. User::USER_FROM_PHONE => '手机号注册',
  88. User::USER_FROM_BYTEDANCE => '抖音',
  89. ];
  90. const SEDN_TIMES_DEFAULT = 0; // 默认发放次数
  91. /**
  92. * {@inheritdoc}
  93. */
  94. public function rules()
  95. {
  96. return [
  97. [['id', 'store_id', 'total_num', 'expire_day', 'is_delete', 'status', 'type', 'date_type', 'is_give', 'freight_id', 'num', 'savingsType', 'send_times','is_business','business_type','export', 'is_unlimited'], 'integer'],
  98. [['money', 'price', 'total_price', 'for_cash'], 'double'],
  99. [['name','search_shop_name'], 'string', 'max' => 255],
  100. [['goods_ids', 'video_ids', 'account_info', 'flag'], 'string'],
  101. [['pic_url', 'bg_pic_url','content'], 'string', 'max' => 2048],
  102. [['flag'], 'trim'],
  103. [['use_num', 'begin_time', 'end_time', 'date'], 'safe'],
  104. ['is_delete', 'default', 'value'=> VerifyCard::IS_DELETE_NO],
  105. [['name', 'pic_url', 'price', 'expire_day'],'required', 'on'=> [self::SCENARIO_ADD, self::SCENARIO_EDIT]],
  106. [['id'],'required', 'on'=> [self::SCENARIO_DEL, self::SCENARIO_EDIT]],
  107. ['id', 'string', 'on' => self::SCENARIO_DEL],
  108. ['search_key', 'string', 'on' => self::SCENARIO_LIST],
  109. [['fields', 'form'], 'safe'],
  110. [['user_nickname', 'user_mobile', 'verify_person_nickname', 'md_name', 'start_time', 'order_no'], 'safe'],
  111. ];
  112. }
  113. /**
  114. * {@inheritdoc}
  115. */
  116. public function attributeLabels()
  117. {
  118. return [
  119. 'id' => 'ID',
  120. 'store_id' => 'Store ID',
  121. 'name' => '核销卡名称',
  122. 'total_num' => '总次数',
  123. 'use_num' => '核销次数',
  124. 'expire_day' => '有效期',
  125. 'money' => '核销卡单次核销优惠金额',
  126. 'price' => '核销卡价值',
  127. 'pic_url' => '核销卡Logo',
  128. 'begin_time' => '核销卡开始时间',
  129. 'end_time' => '核销卡结束时间',
  130. 'date' => '核销卡起止时间',
  131. 'sort' => '排序',
  132. 'is_delete' => '状态',
  133. 'status' => '核销卡类型:1=生效中,2=已失效',
  134. 'account_info' => '卡密账号信息',
  135. 'type' => '卡券类型:1=核销卡,2=礼品卡,3=储值卡,4=虚拟卡,5=视频卡',
  136. 'bg_pic_url' => '背景图',
  137. 'date_type' => '日期类型',
  138. 'is_give' => '是否转赠:0=否,1=是',
  139. 'content' => '卡券说明',
  140. 'num' => '卡券数量',
  141. 'total_price' => '储值卡金额',
  142. 'freight_id' => '运费模板',
  143. 'savingsType' => '储值卡类型',
  144. 'goods_ids' => '商品id',
  145. 'video_ids' => '视频id',
  146. 'send_times' => '发放次数',
  147. 'is_business' => '是否是商盟',
  148. 'business_type' => '展示位置',
  149. 'for_cash' => '礼品卡折现',
  150. 'is_unlimited' => '核销次数是否无限:0=否;1=是;',
  151. ];
  152. }
  153. public function scenarios()
  154. {
  155. $scenarios = parent::scenarios();
  156. return $scenarios;
  157. }
  158. //获取店铺信息
  159. private function getStoreInfoById($store_id){
  160. $storeInfo = Store::find()->where(['id'=>$store_id,'is_delete'=>0])->asArray()->one();
  161. if($storeInfo && $storeInfo['name']){
  162. return $storeInfo['name'];
  163. }else{
  164. return "店铺暂无名称";
  165. }
  166. }
  167. public function saveVerifyCard()
  168. {
  169. if ($this->validate()) {
  170. if ($this->scenario == self::SCENARIO_EDIT) {
  171. $model = VerifyCard::findOne(['id' => $this->id]);
  172. } else {
  173. $model = new VerifyCard();
  174. }
  175. $model->attributes = $this->attributes;
  176. if($this->is_unlimited == 1) {
  177. $model->total_num = 0;
  178. }
  179. if (!$model->save()) {
  180. return [
  181. 'code' => 1,
  182. 'msg' => $model->getErrorSummary(false)[0]
  183. ];
  184. }
  185. $wayShop = VerifyShareUser::findOne(['verify_card_id' => $model->id]);
  186. if ($wayShop) {
  187. VerifyShareUser::deleteAll(['verify_card_id'=> $model->id]);
  188. }
  189. foreach ($this->share_user_id as $value) {
  190. $way_form = new VerifyShareUser();
  191. $way_form->store_id = $this->store_id;
  192. $way_form->user_id = $value;
  193. $way_form->verify_card_id = $model->id;
  194. $way_form->save();
  195. }
  196. return [
  197. 'code' => 0,
  198. 'msg' => '保存成功'
  199. ];
  200. } else {
  201. // 验证失败:$errors 是一个包含错误信息的数组
  202. return [
  203. 'code' => 1,
  204. "msg" => $this->getErrorSummary(false)[0]
  205. ];
  206. }
  207. }
  208. public function searchVerifyCard()
  209. {
  210. $query = VerifyCard::find()->alias('v');
  211. $query->where(['v.is_delete' => VerifyCard::IS_DELETE_NO])->orderBy("v.sort desc,v.id desc");
  212. if ($this->id) {
  213. $query->andWhere(['id' => $this->id]);
  214. }
  215. if ($this->type > 0) {
  216. $query->andWhere(['type' => $this->type]);
  217. }
  218. if($this->search_shop_name){
  219. $query->leftJoin(['s' => Store::tableName()], 's.id=c.store_id')->andWhere(['like', 's.name', $this->search_shop_name]);
  220. }
  221. // 搜索
  222. if ($this->store_id) {
  223. $query->andWhere(['=','v.store_id', $this->store_id]);
  224. }
  225. if($this->is_business){
  226. $query->andWhere(['v.is_business'=>$this->is_business]);
  227. }else{
  228. $query->andWhere(['v.is_business'=>0]);
  229. }
  230. if ($this->search_key) {
  231. $query->andWhere(['like', 'v.name', $this->search_key]);
  232. }
  233. if ($this->date) {
  234. $query->andWhere(['>=', 'v.created_at', strtotime($this->date[0])]);
  235. $query->andWhere(['<=', 'v.created_at', strtotime($this->date[1])]);
  236. }
  237. // 根据核销卡类型查找数据 未实现
  238. // if ($this->type) {
  239. // $query->andWhere(['=','type', $this->type]);
  240. // }
  241. $list = pagination_make($query);
  242. $storeName = [];
  243. foreach ($list['list'] as &$val) {
  244. if($this->is_business){
  245. //获取店铺名称
  246. if(isset($storeName[$val['store_id']]) && $storeName[$val['store_id']] ){
  247. $val['store_name'] = $storeName[$val['store_id']];
  248. }else{
  249. $store_name = $this->getStoreInfoById($val['store_id']);
  250. $storeName[$val['store_id']] = $store_name;
  251. $val['store_name'] = $store_name;
  252. }
  253. }
  254. $val['created_at'] = date('Y-m-d H:i:s', $val['created_at']);
  255. $val['updated_at'] = date('Y-m-d H:i:s', $val['updated_at']);
  256. $val['begin_time'] = date('Y-m-d H:i:s', $val['begin_time']);
  257. $val['end_time'] = date('Y-m-d H:i:s', $val['end_time']);
  258. $val['goods_ids'] = json_decode($val['goods_ids']);
  259. $val['video_ids'] = json_decode($val['video_ids']);
  260. if (!empty($val['goods_ids'])) {
  261. $val['goodlist'] = Goods::find()->where(['store_id' => $this->store_id, 'is_delete' => 0])
  262. ->andWhere(['in', 'id', $val['goods_ids']])->asArray()->all();
  263. }
  264. if (!empty($val['video_ids'])) {
  265. $val['videolist'] = Video::find()->where(['store_id' => $this->store_id, 'is_delete' => Video::IS_DELETE_NO])
  266. ->andWhere(['in', 'id', $val['video_ids']])->asArray()->all();
  267. }
  268. $share_user = VerifyShareUser::find()->alias('vsu')
  269. ->leftJoin(['u' => User::tableName()], 'u.id=vsu.user_id')
  270. ->where(['verify_card_id' => $val['id']])->select('u.id,u.nickname')->asArray()->all();
  271. $val['share_user'] = $share_user;
  272. }
  273. return [
  274. 'code' => 0,
  275. 'msg' => 'success',
  276. 'data' => [
  277. 'data' => $list['list'],
  278. 'pageNo' => $list['pageNo'],
  279. 'totalCount' => $list['totalCount']
  280. ]
  281. ];
  282. }
  283. public function searchVerifyShareList($id)
  284. {
  285. $query = VerifyShareLog::find()->alias('vsl')
  286. ->leftJoin(['vcs' => VerifyCardSale::tableName()], 'vsl.sale_id=vcs.id')
  287. ->leftJoin(['vc' => VerifyCard::tableName()], 'vsl.verify_card_id=vc.id')
  288. ->leftJoin(['u' => User::tableName()], 'vsl.share_user_id=u.id')
  289. ->leftJoin(['u2' => User::tableName()], 'vcs.user_id=u2.id')
  290. ->where(['vsl.store_id' => get_store_id(), 'vsl.verify_card_id' => $id])
  291. ->select('vc.name as verify_card_name,u.nickname as share_nickname,u2.nickname as lq_nickname,vsl.create_time');
  292. $list = pagination_make($query);
  293. return [
  294. 'code' => 0,
  295. 'msg' => 'success',
  296. 'data' => [
  297. 'data' => $list['list'],
  298. 'pageNo' => $list['pageNo'],
  299. 'totalCount' => $list['totalCount']
  300. ]
  301. ];
  302. }
  303. public function searchVerifyCardOrderGetList()
  304. {
  305. $query = Order::find()->alias('o')
  306. ->innerJoin(['vcs' => VerifyCardSale::tableName()], 'FIND_IN_SET(vcs.id, o.get_verify_id)')
  307. ->innerJoin(['vc' => VerifyCard::tableName()], 'vc.id = vcs.verify_card_id')
  308. ->leftJoin(['u' => User::tableName()], 'u.id = o.user_id')
  309. ->leftJoin(['su' => SaasUser::tableName()], 'u.binding = su.mobile');
  310. $query->andWhere(['o.store_id' => $this->store_id]);
  311. if ($this->id > 0) {
  312. $query->andWhere(['vc.id' => $this->id]);
  313. }
  314. if($this->user_nickname){
  315. $query->andWhere(['like', 'su.name', $this->user_nickname]);
  316. }
  317. if($this->user_mobile){
  318. $query->andWhere(['like', 'su.mobile', $this->user_mobile]);
  319. }
  320. if($this->name){
  321. $query->andWhere(['like', 'vc.name', $this->name]);
  322. }
  323. if($this->order_no){
  324. $query->andWhere(['like', 'o.order_no', $this->order_no]);
  325. }
  326. if (!empty($this->start_time)) {
  327. $query->andWhere(['>' , 'vcs.sale_time', strtotime($this->start_time)]);
  328. }
  329. if (!empty($this->end_time)) {
  330. $query->andWhere(['<' , 'vcs.sale_time', strtotime($this->end_time)]);
  331. }
  332. $query->groupBy('order_id, vc_id');
  333. $query->orderBy('o.id DESC');
  334. $query->select('vcs.sale_time, o.id order_id, o.order_no, o.user_id, su.avatar, su.name, su.mobile, vc.id vc_id, vc.name vc_name, vcs.id vcs_id, count(1) count, GROUP_CONCAT(vcs.id) vcs_id_list');
  335. $list = pagination_make($query);
  336. return [
  337. 'code' => 0,
  338. 'msg' => 'success',
  339. 'data' => $list,
  340. 'q' => $query->createCommand()->getRawSql(),
  341. ];
  342. }
  343. public function searchVerifyCardLogList()
  344. {
  345. $query = VerifyCardLog::find()->alias('vcl')
  346. ->leftJoin(['vcs' => VerifyCardSale::tableName()], 'vcl.sale_id=vcs.id')
  347. ->leftJoin(['vc' => VerifyCard::tableName()], 'vcs.verify_card_id=vc.id')
  348. ->leftJoin(['u' => User::tableName()], 'vcl.user_id=u.id')
  349. ->leftJoin(['su' => SaasUser::tableName()], 'su.mobile=u.binding')
  350. ->where(['vcl.store_id' => get_store_id()])
  351. ->select('vc.price, vcl.id vcl_id, vcs.id vcs_id, vc.name name, vcl.user_id, su.name user_nickname, su.avatar user_avatar, su.mobile user_mobile, vcl.use_time');
  352. $query->orderBy('vcl.id DESC');
  353. if ($this->type > 0) {
  354. $query->andWhere(['vc.type' => $this->type]);
  355. }
  356. if ($this->id > 0) {
  357. $query->andWhere(['vc.id' => $this->id]);
  358. }
  359. if($this->user_nickname){
  360. $query->andWhere(['like', 'su.name', $this->user_nickname]);
  361. }
  362. if($this->user_mobile){
  363. $query->andWhere(['like', 'su.mobile', $this->user_mobile]);
  364. }
  365. if($this->name){
  366. $query->andWhere(['like', 'vc.name', $this->name]);
  367. }
  368. if (!empty($this->start_time)) {
  369. $query->andWhere(['>' , 'vcl.use_time', strtotime($this->start_time)]);
  370. }
  371. if (!empty($this->end_time)) {
  372. $query->andWhere(['<' , 'vcl.use_time', strtotime($this->end_time)]);
  373. }
  374. if($this->type == 1){
  375. $query->leftJoin(['u2' => User::tableName()], 'vcl.verify_person=u2.id')
  376. ->leftJoin(['su2' => SaasUser::tableName()], 'su2.mobile=u2.binding')
  377. ->leftJoin(['md' => Md::tableName()], 'vcl.shop_id=md.id')
  378. ->addSelect('su2.name verify_person_nickname, su2.avatar verify_person_avatar, su2.mobile verify_person_mobile, md.name md_name');
  379. if($this->md_name){
  380. $query->andWhere(['like', 'md.name', $this->md_name]);
  381. }
  382. if($this->verify_person_nickname){
  383. $query->andWhere(['like', 'su2.name', $this->verify_person_nickname]);
  384. }
  385. }
  386. if($this->type == 2){
  387. $query->leftJoin(['o' => Order::tableName()], 'vcs.id = o.verify_card_id')
  388. ->addSelect('o.id order_id, o.order_no');
  389. if($this->order_no){
  390. $query->andWhere(['like', 'o.order_no', $this->order_no]);
  391. }
  392. }
  393. $query->andWhere(['vcl.type' => [VerifyCardLog::WRITE_TYPE_WRITE_OFF, VerifyCardLog::WRITE_TYPE_EXCHANGE]]);
  394. if($this->export = input_params('export', 0)){
  395. $export_list = $query->asArray()->all();
  396. return $this->export($export_list);
  397. }
  398. $list = pagination_make($query);
  399. return [
  400. 'code' => 0,
  401. 'msg' => 'success',
  402. 'data' => $list,
  403. 'q' => $query->createCommand()->getRawSql(),
  404. ];
  405. }
  406. private function export($list)
  407. {
  408. $rows = [[
  409. 'ID',
  410. '用户名称',
  411. '手机号',
  412. '核销卡名称',
  413. '核销门店',
  414. '核销店员名称',
  415. '核销店员手机号',
  416. '核销时间',
  417. ]];
  418. foreach($list as $item){
  419. $r = [
  420. $item['vcl_id'],
  421. $item['user_nickname'],
  422. $item['user_mobile'],
  423. $item['name'],
  424. $item['md_name'],
  425. $item['verify_person_nickname'],
  426. $item['verify_person_mobile'],
  427. $item['use_time']? date('Y-m-d H:i:s', $item['use_time']):'',
  428. ];
  429. $rows[] = $r;
  430. }
  431. $writer = \Spatie\SimpleExcel\SimpleExcelWriter::streamDownload(time() . '.xlsx')->noHeaderRow()
  432. ->addRows($rows)->toBrowser();
  433. }
  434. public function verifyTmp()
  435. {
  436. $row = [
  437. // '账号',
  438. // '密码',
  439. ];
  440. $id = $this->id;
  441. $vc = VerifyCard::findOne($id);
  442. if($vc['form']){
  443. $form = json_decode($vc['form'], true);
  444. foreach($form['list'] as $item){
  445. $row[] = $item['name'];
  446. }
  447. }
  448. $rows = [$row];
  449. $writer = \Spatie\SimpleExcel\SimpleExcelWriter::streamDownload(time() . '.xlsx')->noHeaderRow()
  450. ->addRows($rows)->toBrowser();
  451. }
  452. public function delVerifyCard()
  453. {
  454. if ($this->validate()) {
  455. if ($this->scenario !== self::SCENARIO_DEL) {
  456. return [
  457. 'code' => 1,
  458. 'msg' => '删除失败'
  459. ];
  460. }
  461. $model = VerifyCard::findOne(['id' => $this->id]);
  462. $model->is_delete = VerifyCard::IS_DELETE_YES;
  463. if (!$model || !$model->save()) {
  464. return [
  465. 'code' => 1,
  466. 'msg' => $model->getErrorSummary(false)[0]
  467. ];
  468. }
  469. return [
  470. 'code' => 0,
  471. 'msg' => '删除成功'
  472. ];
  473. // 所有输入数据都有效 all inputs are valid
  474. } else {
  475. // 验证失败:$errors 是一个包含错误信息的数组
  476. return [
  477. 'code' => 1,
  478. "msg" => $this->getErrorSummary(false)[0]
  479. ];
  480. }
  481. }
  482. public function getAccountInfo()
  483. {
  484. try {
  485. if (empty($this->id)) {
  486. throw new \Exception("ID不能为空");
  487. }
  488. $query = VerifyCardAccount::find()->where([
  489. 'store_id' => get_store_id(),
  490. 'card_id' => $this->id,
  491. ])
  492. ->orderBy('id DESC');//->asArray()->all();
  493. $page = pagination_make($query);
  494. $data['list'] = $page['list'];
  495. $data['pageNo'] = $page['pageNo'];
  496. $data['totalCount'] = $page['totalCount'];
  497. foreach ($data['list'] as $k => $item) {
  498. $sale_card = VerifyCardSale::find()->where(['account_id' => $item['id']])->select('id,status as sale_status')->orderBy('id DESC')->asArray()->one();
  499. // status 是核销卡领取状态 sale_status是领取后的使用状态
  500. $data['list'][$k]['sale_status'] = empty($sale_card) ? 0 :$sale_card['sale_status'];
  501. if (!empty($sale_card)) {
  502. $VerifyCardLog = VerifyCardLog::find()->where(['sale_id' => $sale_card['id']])->select('id, shop_id, verify_person, use_time,saas_verify_person')->asArray()->all();
  503. if (!empty($VerifyCardLog)) {
  504. foreach ($VerifyCardLog as &$log_item) {
  505. $log_item['use_time'] = date("Y-m-d H:i:s", $log_item['use_time']);
  506. if (!empty($log_item['shop_id'])) {
  507. $shop = Md::findOne($log_item['shop_id']);
  508. $log_item['shop_id'] = $shop->name ?: "";
  509. }
  510. if(empty($log_item['verify_person'])){
  511. $saasUser = SaasUser::find()->where(['id' => $log_item['saas_verify_person']])->select('id, name')->one();
  512. if (!empty($saasUser)) {
  513. $log_item['verify_person'] = $saasUser->name;
  514. }
  515. }else{
  516. $user = User::find()->where(['id' => $log_item['verify_person']])->select('id, nickname')->one();
  517. if (!empty($user)) {
  518. $log_item['verify_person'] = $user->nickname;
  519. }
  520. }
  521. }
  522. $data['list'][$k]['card_log'][] = $log_item;
  523. }
  524. }
  525. }
  526. return [
  527. 'code' => 0,
  528. 'msg' => 'success',
  529. 'data' => $data,
  530. ];
  531. } catch (\Exception $e) {
  532. return [
  533. 'code' => 1,
  534. "msg" => $e->getMessage()
  535. ];
  536. }
  537. }
  538. /**
  539. * 获取卡券详情
  540. * @return array
  541. * @throws \yii\base\Exception
  542. */
  543. public function verifyDetail() {
  544. if ($this->id) {
  545. // 卡券详情
  546. $data = VerifyCard::find()->where(['id' => $this->id, 'store_id' => $this->store_id])->asArray()->one();
  547. $data['begin_time'] = date('Y-m-d H:i:s', $data['begin_time']);
  548. $data['end_time'] = date('Y-m-d H:i:s', $data['end_time']);
  549. $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']);
  550. $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']);
  551. $query = VerifyCardAccount::find()->where([
  552. 'store_id' => $this->store_id,
  553. 'card_id' => $this->id,
  554. ])->select('account, password, status, id');//->asArray()->all();
  555. $page = pagination_make($query);
  556. $data['account_info']['list'] = $page['list'];
  557. $data['account_info']['pageNo'] = $page['pageNo'];
  558. $data['account_info']['totalCount'] = $page['totalCount'];
  559. $data['goods_ids'] = json_decode($data['goods_ids'], true);
  560. $data['video_ids'] = json_decode($data['video_ids'], true);
  561. $data['use_num'] = $data['use_num'] == '' ? 0 : $data['use_num'];
  562. //系统后台 核销卡详情,显示具体核销 门店信息、员工信息、核销时间(精确到秒)的信息
  563. foreach ($data['account_info']['list'] as &$item) {
  564. $sale_card = VerifyCardSale::find()->where(['account_id' => $item['id']])->select('id')->asArray()->one();
  565. // status 是核销卡领取状态 sale_status是领取后的使用状态
  566. $item['sale_status'] = empty($sale_card) ? 0 :$sale_card['sale_status'];
  567. if (!empty($sale_card)) {
  568. $VerifyCardLog = VerifyCardLog::find()->where(['sale_id' => $sale_card['id']])->select('id, shop_id, verify_person, use_time,saas_verify_person')->asArray()->all();
  569. if (!empty($VerifyCardLog)) {
  570. foreach ($VerifyCardLog as &$log_item) {
  571. $log_item['use_time'] = date("Y-m-d H:i:s", $log_item['use_time']);
  572. if (!empty($log_item['shop_id'])) {
  573. $shop = Md::findOne($log_item['shop_id']);
  574. $log_item['shop'] = $shop->name ?: "";
  575. }
  576. if(empty($log_item['verify_person'])){
  577. $saasUser = SaasUser::find()->where(['id' => $log_item['saas_verify_person']])->select('id, name')->one();
  578. $log_item['verify_person'] = $saasUser->name;
  579. }else{
  580. $User = User::find()->where(['id' => $log_item['verify_person']])->select('id, nickname')->asArray()->one();
  581. $log_item['verify_person'] = $User->nickname;
  582. }
  583. }
  584. $item['card_log'] = $VerifyCardLog;
  585. }
  586. }
  587. }
  588. // 卡券类型
  589. if (!empty($data['goods_ids'])) {
  590. $data['goodlist'] = Goods::find()->where(['store_id' => $this->store_id, 'is_delete' => 0])
  591. ->andWhere(['in', 'id', $data['goods_ids']])->asArray()->all();
  592. }
  593. if (!empty($data['video_ids'])) {
  594. $data['videolist'] = Video::find()->where(['store_id' => $this->store_id, 'is_delete' => Video::IS_DELETE_NO])
  595. ->andWhere(['in', 'id', $data['video_ids']])->asArray()->all();
  596. }
  597. // 卡券领取记录
  598. $query = VerifyCardSale::find()->alias('vc')
  599. ->leftJoin(['u' => User::tableName()], 'vc.user_id = u.id')
  600. ->leftJoin(['su' => SaasUser::tableName()], 'su.mobile = u.binding')
  601. ->where(['vc.store_id' => $this->store_id, 'vc.is_delete' => VerifyCardSale::IS_DELETE_NO, 'vc.verify_card_id' => $this->id]);
  602. $query->select('vc.*');
  603. if($this->user_nickname){
  604. $query->andWhere(['like', 'su.name', $this->user_nickname]);
  605. }
  606. if($this->user_mobile){
  607. $query->andWhere(['like', 'u.binding', $this->user_mobile]);
  608. }
  609. if (!empty($this->start_time)) {
  610. $query->andWhere(['>' , 'vc.sale_time', strtotime($this->start_time)]);
  611. }
  612. if (!empty($this->end_time)) {
  613. $query->andWhere(['<' , 'vc.sale_time', strtotime($this->end_time)]);
  614. }
  615. $query->orderBy('vc.id DESC');
  616. $list = pagination_make($query);
  617. foreach ($list['list'] as &$val) {
  618. $user = User::find()->where(['id' => $val['user_id']])->select('binding, avatar_url, nickname, platform')->asArray()->one();
  619. if(!$user){ continue; }
  620. $sassuser = SaasUser::find()->where(['mobile' => $user['binding']])->select('name, avatar')->asArray()->one();
  621. $val['avatar_url'] = !empty($sassuser['avatar']) ? $sassuser['avatar'] : $user['avatar_url'];
  622. $val['nickname'] = !empty($sassuser['name']) ? $sassuser['name'] : $user['nickname'];
  623. $val['mobile'] = $user['binding'];
  624. $val['platform'] = self::USER_PLATFORM_TYPE[$user['platform']];
  625. $val['card_info'] = [];
  626. if ($val['account_id'] > 0) {
  627. $val['card_info'] = VerifyCardAccount::findOne($val['account_id']);
  628. }
  629. $val['created_at']= date('Y-m-d H:i:s', $val['created_at']);
  630. }
  631. } else {
  632. return [
  633. 'code' => 1,
  634. 'msg' => '参数错误',
  635. ];
  636. }
  637. $list = [
  638. 'data' => $list['list'],
  639. 'pageNo' => $list['pageNo'],
  640. 'totalCount' => $list['totalCount'],
  641. ];
  642. if($data['send_times'] != $list['totalCount']){
  643. $c = VerifyCard::find()->where(['id' => $this->id, 'store_id' => $this->store_id])->one();
  644. $c->send_times = $list['totalCount'];
  645. $c->save();
  646. $data['send_times'] = $list['totalCount'];
  647. }
  648. return [
  649. 'code' => 0,
  650. 'msg' => 'success',
  651. 'data' => $data,
  652. 'list' => $list,
  653. ];
  654. }
  655. public static function getVerifyCardList(){
  656. return VerifyCard::find()->where(['is_delete' => VerifyCard::IS_DELETE_NO])->orderBy(['sort desc, id desc'])->select('*')->asArray()->all();
  657. }
  658. // 生成卡密
  659. public function generateAccount()
  660. {
  661. $verifyCard = VerifyCard::findOne($this->id);
  662. if (!$verifyCard) {
  663. return [
  664. 'code' => 1,
  665. 'msg' => '卡券不存在',
  666. ];
  667. }
  668. if ($this->num > 0) {
  669. for ($i = 0; $i < $this->num; $i++) {
  670. try {
  671. $account = new VerifyCardAccount();
  672. $account->store_id = $this->store_id;
  673. $account->card_id = $this->id;
  674. $account->account = 'TX'. mt_rand(10000000, 99999999);
  675. $account->password = $this->makeCardPassword();
  676. $account->status = VerifyCardAccount::STATUS_UNUSED;
  677. $account->save();
  678. } catch (\Throwable $throwable) {}
  679. }
  680. $count = VerifyCardAccount::find()->where([
  681. 'store_id' => $this->store_id,
  682. 'card_id' => $this->id,
  683. ])->count();
  684. $verifyCard->num = $count;
  685. $verifyCard->save();
  686. return [
  687. 'code' => 0,
  688. 'msg' => '生成成功',
  689. ];
  690. } else {
  691. return [
  692. 'code' => 1,
  693. 'msg' => '数量必须大于0',
  694. ];
  695. }
  696. }
  697. // 生成卡密
  698. public function makeCardPassword()
  699. {
  700. $code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  701. $rand = $code[rand(0, 25)]
  702. . strtoupper(dechex(date('m')))
  703. . date('d') . substr(time(), -5)
  704. . substr(microtime(), 2, 5)
  705. . sprintf('%02d', rand(0, 99));
  706. for (
  707. $a = md5($rand, true),
  708. $s = '0123456789ABCDEFGHIJKLMNOPQRSTUV',
  709. $d = '',
  710. $f = 0;
  711. $f < 8;
  712. $g = ord($a[$f]),
  713. $d .= $s[($g ^ ord($a[$f + 8])) - $g & 0x1F],
  714. $f++
  715. ) ;
  716. return $d;
  717. }
  718. public function changePass($id, $password) {
  719. $pass = trim($password);
  720. if(strlen($pass) <= 2){
  721. return [
  722. 'code' => 1,
  723. 'msg' => '密码格式不正确',
  724. ];
  725. }
  726. $account_info = VerifyCardAccount::findOne($id);
  727. $account_info->password = $pass;
  728. $save = $account_info->save();
  729. return [
  730. 'code'=> $save ? 0 : 1,
  731. 'msg' => $save ? '成功' : '失败',
  732. ];
  733. }
  734. public function vcAccountSave($list) {
  735. try{
  736. foreach($list as $i => $item){
  737. if($item['id']){
  738. $account_info = VerifyCardAccount::findOne($item['id']);
  739. $account_info->account = $item['account'];
  740. $pass = trim($item['password']);
  741. if(strlen($pass) <= 2){
  742. throw new \Exception('密码格式不正确');
  743. }
  744. $account_info->password = $pass;
  745. }else{
  746. $account_info = new VerifyCardAccount();
  747. $account_info->store_id = $this->store_id;
  748. $account_info->card_id = $item['card_id'];
  749. $account_info->account = 'TX'. mt_rand(10000000, 99999999);
  750. $account_info->password = $this->makeCardPassword();
  751. }
  752. $item['form'] && $account_info->form = json_encode($item['form'], true);
  753. $save = $account_info->save();
  754. if(!$save){
  755. throw new \Exception(array_shift($account_info->getFirstErrors()));
  756. }
  757. $verifyCard = VerifyCard::findOne($item['card_id']);
  758. $dbcount = VerifyCardAccount::find()->where(['card_id' => $verifyCard->id])->count();
  759. $verifyCard->num = $dbcount;
  760. $verifyCard->save();
  761. }
  762. } catch (\Exception $e) {
  763. return [
  764. 'code'=> 1,
  765. 'msg' => '出现错误,成功' . $i . '条数据,错误位置:卡号,' . $item['account'] . ',错误原因,' . $e->getMessage(),
  766. ];
  767. }
  768. return [
  769. 'code'=> 0,
  770. 'msg' => '操作成功',
  771. ];
  772. }
  773. //导入卡密
  774. public function upload() {
  775. set_time_limit(0);
  776. $verifyCard = VerifyCard::findOne($this->id);
  777. if (!$verifyCard) {
  778. return [
  779. 'code' => 1,
  780. 'msg' => '卡券不存在',
  781. ];
  782. }
  783. $filename = $_FILES['excel']['name'];
  784. $tmpname = $_FILES['excel']['tmp_name'];
  785. $path = \Yii::$app->basePath . '/web/temp/';
  786. if(!is_dir($path)){
  787. mkdir($path);
  788. }
  789. $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
  790. if (($ext != 'xlsx') && ($ext != 'xls')) {
  791. return [
  792. 'code' => 1,
  793. 'msg' => '请上传excel文件'
  794. ];
  795. }
  796. $file = time() . $this->store_id . '.' . $ext;
  797. $uploadfile = $path . $file;
  798. move_uploaded_file($tmpname, $uploadfile);
  799. $rows = \Spatie\SimpleExcel\SimpleExcelReader::create($uploadfile)
  800. ->getRows();
  801. $arr = [];
  802. $rows->each(function (array $item) use ($verifyCard, &$arr) {
  803. try{
  804. if (isset($item['账号']) && isset($item['密码']) && !empty($item['账号']) && !empty($item['账号'])) {
  805. $account = new VerifyCardAccount();
  806. $account->store_id = $verifyCard->store_id;
  807. $account->card_id = $verifyCard->id;
  808. $account->account = (string)$item['账号'];
  809. $account->password = (string)$item['密码'];
  810. $res = $account->save();
  811. if($res){
  812. $arr[] = $res;
  813. }
  814. }
  815. if($verifyCard['form']){
  816. $form = json_decode($verifyCard['form'], true);
  817. if($form){
  818. $account = new VerifyCardAccount();
  819. $account->store_id = $verifyCard->store_id;
  820. $account->card_id = $verifyCard->id;
  821. $account->account = 'TX'. mt_rand(10000000, 99999999);
  822. $account->password = $this->makeCardPassword();
  823. foreach($form['list'] as &$k){
  824. $k['default'] = $item[$k['name']];
  825. }
  826. $account->form = json_encode($form);
  827. $res = $account->save();
  828. if($res){
  829. $arr[] = $res;
  830. }
  831. }
  832. }
  833. } catch (\Exception $e){
  834. debug_log($e->getMessage());
  835. }
  836. });
  837. $count = count($arr);
  838. $dbcount = VerifyCardAccount::find()->where(['card_id' => $verifyCard->id])->count();
  839. $verifyCard->num = $dbcount;
  840. $verifyCard->save();
  841. @unlink($uploadfile);
  842. return [
  843. 'code' => $count ? 0 : 1,
  844. 'msg' => "共导入{$count}条数据"
  845. ];
  846. }
  847. /* begin 2024/11/16 14:48:52 id1126开发需求:新增储值卡消费记录 WPing丶 */
  848. // 2025年7月12日14:13:25调整,解决补丁git冲突
  849. public function searchCardPayLogList()
  850. {
  851. $query = VerifyCardAccount::find()->alias('vca')
  852. ->leftJoin(['vcs' => VerifyCardSale::tableName()], 'vca.id=vcs.account_id OR vcs.account_id IS NULL')
  853. ->leftJoin(['vc' => VerifyCard::tableName()], 'vca.card_id=vc.id')
  854. ->leftJoin(['vcl' => VerifyCardLog::tableName()], 'vcl.sale_id=vcs.id')
  855. ->leftJoin(['u' => User::tableName()], 'vcl.user_id=u.id')
  856. ->leftJoin(['su' => SaasUser::tableName()], 'su.mobile=u.binding')
  857. ->select([
  858. 'vc.total_price as price',
  859. 'vcl.id AS vcl_id',
  860. 'IFNULL(vcs.id, 0) AS vcs_id', // 默认值为0
  861. 'vc.name AS name',
  862. 'vcl.user_id',
  863. 'su.name AS user_nickname',
  864. 'su.avatar AS user_avatar',
  865. 'su.mobile AS user_mobile',
  866. 'vcl.use_time',
  867. 'vcl.use_price',
  868. 'vcl.use_order_ids',
  869. 'vca.account'
  870. ]);
  871. $query->orderBy('vcl.id DESC');
  872. // 搜索条件
  873. if ($this->user_nickname) {
  874. $query->andWhere(['like', 'su.name', $this->user_nickname]);
  875. }
  876. if ($this->account) {
  877. $query->andWhere(['like', 'vca.account', $this->account]);
  878. }
  879. if ($this->user_mobile) {
  880. $query->andWhere(['like', 'su.mobile', $this->user_mobile]);
  881. }
  882. if ($this->name) {
  883. $query->andWhere(['like', 'vc.name', $this->name]);
  884. }
  885. if (!empty($this->start_time)) {
  886. $query->andWhere(['>', 'vcl.use_time', strtotime($this->start_time)]);
  887. }
  888. if (!empty($this->end_time)) {
  889. $query->andWhere(['<', 'vcl.use_time', strtotime($this->end_time)]);
  890. }
  891. if ($this->use_type == 1) {
  892. $query->andWhere(['vcl.use_price' => 0]);
  893. }
  894. if ($this->use_type == 2) {
  895. $query->andWhere(['>', 'vcl.use_price', 0]);
  896. $query->andWhere(['vcl.is_complete' => 0]);
  897. }
  898. if ($this->use_type == 3) {
  899. $query->andWhere(['vcl.is_complete' => 1]);
  900. }
  901. if ($this->use_type == 4) {
  902. $query->andWhere(['IS', 'vcs.id', null]);
  903. }
  904. $query->andWhere(['or', ['vcl.type' => [VerifyCardLog::WRITE_TYPE_WRITE_OFF, VerifyCardLog::WRITE_TYPE_EXCHANGE]], ['vcl.type' => null]]);
  905. $list = pagination_make($query);
  906. foreach ($list['list'] as $k => &$item) {
  907. $item['order_count'] = !$item['use_order_ids'] ? 0 :count(explode(',', $item['use_order_ids']));
  908. $item['card_balance'] = bcsub($item['price'], $item['use_price'], 2);
  909. }
  910. // 获取可导出数据
  911. $f = new ExportList();
  912. $exportList = $f->getList();
  913. if($this->export){
  914. return $this->LogExport($list['list']);
  915. }
  916. return [
  917. 'code' => 0,
  918. 'msg' => 'success',
  919. 'data' => $list,
  920. ];
  921. }
  922. private function LogExport($list) {
  923. $rows = [[
  924. 'ID',
  925. '会员信息',
  926. '手机号',
  927. '储值卡卡号',
  928. '储值卡名称',
  929. '储值卡金额',
  930. '卡内余额',
  931. '已用余额',
  932. '使用订单数量',
  933. '关联订单ID',
  934. '使用状态',
  935. '激活时间',
  936. ]];
  937. foreach($list as $item) {
  938. if($item['use_order_ids']) {
  939. $order_no = implode(',', Order::find()->where(['id' => explode(',', $item['use_order_ids'])])->select('order_no')->column());
  940. }
  941. if($item['user_id']) {
  942. if($item['use_price'] == 0) {
  943. $use_type = '未使用';
  944. } elseif($item['use_price'] == $item['price']) {
  945. $use_type = '已用完';
  946. } else {
  947. $use_type = '使用中';
  948. }
  949. } else {
  950. $use_type = '未激活';
  951. }
  952. $r = [
  953. $item['vcl_id'],
  954. $item['user_nickname'],
  955. $item['user_mobile'],
  956. $item['account'],
  957. $item['name'],
  958. $item['price'],
  959. $item['card_balance'],
  960. $item['use_price'],
  961. $item['order_count'],
  962. $order_no,
  963. $use_type,
  964. $item['use_time'] ? date('Y-m-d H:i:s',$item['use_time']) : '/',
  965. ];
  966. $rows[] = $r;
  967. }
  968. // array_unshift($list, $rows);
  969. $writer = \Spatie\SimpleExcel\SimpleExcelWriter::streamDownload(time() . '.xlsx')->noHeaderRow()
  970. ->addRows($rows)->toBrowser();
  971. }
  972. /* end */
  973. }