SecondaryCardRedemptionCodeService.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. <?php
  2. namespace addons\SecondaryCard\common\service;
  3. use addons\SecondaryCard\common\enums\SecondaryCardEnum;
  4. use addons\SecondaryCard\common\models\SecondaryCard;
  5. use addons\SecondaryCard\common\models\SecondaryCardOrder;
  6. use addons\SecondaryCard\common\models\SecondaryCardRedemptionCode;
  7. use common\components\export\CsvTool;
  8. use common\enums\DownloadEnum;
  9. use common\enums\RedisKeyEnum;
  10. use common\enums\StatusEnum;
  11. use common\helpers\LockHelper;
  12. use common\helpers\StringHelper;
  13. use common\models\common\Download;
  14. use common\models\mall\MallAddons;
  15. use common\traits\ErrorTrait;
  16. class SecondaryCardRedemptionCodeService
  17. {
  18. use ErrorTrait;
  19. public static function getList($params)
  20. {
  21. $params['where'][] = ['mall_id' => $params['mall_id']];
  22. $params['where'][] = ['secondary_card_id' => $params['secondary_card_id']];
  23. $params['where'][] = ['status' => [StatusEnum::ENABLED, StatusEnum::DISABLED]];
  24. if (isset($params['is_use']) && $params['is_use'] !== '') {
  25. $params['where'][] = ['is_use' => $params['is_use']];
  26. }
  27. if (!empty($params['code'])) {
  28. $params['where'][] = ['like', 'code', trim($params['code'])];
  29. }
  30. if (!empty($params['remarks'])) {
  31. $params['where'][] = ['like', 'remarks', trim($params['remarks'])];
  32. }
  33. $params['order'] = 'id DESC';
  34. $params['with'] = ['secondaryCard', 'secondaryCardOrder'];
  35. if (!empty($params['sort_column']) && !empty($params['sort_order'])) {
  36. $sort_order = $params['sort_order'] == 'ascending' ? 'asc' : 'desc';
  37. $params['order'] = $params['sort_column'] . ' ' . $sort_order;
  38. }
  39. $pageData = SecondaryCardRedemptionCode::listPage($params, false);
  40. if (!empty($pageData['list'])) {
  41. $o2o_store_ids = [];
  42. $o2o_store_list = [];
  43. foreach ($pageData['list'] as $item) {
  44. switch ($item['create_source_type']) {
  45. case 1:
  46. $o2o_store_ids[] = $item['create_source_id'];
  47. break;
  48. }
  49. }
  50. if (!empty($o2o_store_ids) && MallAddons::isInstall($params['mall_id'], 'Store')) {
  51. $o2o_store_list = SecondaryCardService::getO2OStoreList($o2o_store_ids);
  52. }
  53. $mall_name = \Yii::$app->services->setting->mall->get($params['mall_id'], 'basic.name');
  54. foreach ($pageData['list'] as &$item) {
  55. $item['source'] = '';
  56. $item['order_no'] = $item['secondaryCardOrder']['order_no'] ?? '';
  57. switch ($item['create_source_type']) {
  58. case 0:
  59. $item['source'] = $mall_name;
  60. break;
  61. case 1:
  62. $item['source'] = $o2o_store_list[$item['create_source_id']]['store_name'] ?? '';
  63. break;
  64. }
  65. unset($item['secondaryCardOrder']);
  66. unset($item['secondaryCard']);
  67. }
  68. }
  69. $pageData['export_list'] = SecondaryCardRedemptionCode::getExportFields();
  70. return $pageData;
  71. }
  72. public static function del($params)
  73. {
  74. $lock_key = RedisKeyEnum::suffix(SecondaryCardEnum::LOCK_SECONDARY_CARD, $params['secondary_card_id']);
  75. $identification = uniqid();
  76. $t = \Yii::$app->db->beginTransaction();
  77. try {
  78. if (!LockHelper::lock($lock_key, $identification, 30, 60)) throw new \Exception('当前访问人数过多');
  79. $counts = 1;
  80. if (is_array($params['id'])) {
  81. $counts = count($params['id']);
  82. }
  83. $res = SecondaryCardRedemptionCode::updateAll(['status' => StatusEnum::DELETE], ['id' => $params['id'], 'mall_id' => $params['mall_id']]);
  84. if (empty($res)) {
  85. throw new \Exception('更新失败');
  86. }
  87. $secondary_card = SecondaryCard::findOne(['id' => $params['secondary_card_id'], 'mall_id' => $params['mall_id']]);
  88. $secondary_card->max_times += $counts;
  89. $secondary_card->save();
  90. $t->commit();
  91. LockHelper::uLock($lock_key, $identification);
  92. return true;
  93. } catch (\Exception $e) {
  94. $t->rollBack();
  95. LockHelper::uLock($lock_key, $identification);
  96. return $e->getMessage();
  97. }
  98. }
  99. public static function add($params)
  100. {
  101. $t = \Yii::$app->db->beginTransaction();
  102. $lock_key = RedisKeyEnum::suffix(SecondaryCardEnum::LOCK_SECONDARY_CARD, $params['secondary_card_id']);
  103. $identification = uniqid();
  104. try {
  105. if (!LockHelper::lock($lock_key, $identification, 30, 60)) throw new \Exception('当前访问人数过多');
  106. $secondary_card = SecondaryCard::findOne(['id' => $params['secondary_card_id'], 'mall_id' => $params['mall_id']]);
  107. if (empty($secondary_card)) {
  108. throw new \Exception('次卡不存在');
  109. }
  110. $temp_max_times = $secondary_card->max_times;
  111. $secondary_card->max_times -= $params['num'];
  112. if ($secondary_card->max_times < 0) {
  113. $secondary_card->max_times = 0;
  114. $params['num'] = $temp_max_times;
  115. }
  116. $secondary_card->save();
  117. for ($i = 0; $i < $params['num']; $i++) {
  118. while (true) {
  119. if (!empty($params['code_pre'])) {
  120. $code = $params['code_pre'] . StringHelper::generateRandCode(9);
  121. } else {
  122. $rand = mt_rand(1000, 9999);
  123. $code = StringHelper::generateRandCode(9);
  124. $code = $code . $rand;
  125. }
  126. $res = SecondaryCardRedemptionCode::findOne(['mall_id' => $params['mall_id'], 'code' => $code, 'status' => StatusEnum::ENABLED]);
  127. if (empty($res)) {
  128. break;
  129. }
  130. }
  131. $add_data = [
  132. 'mall_id' => $params['mall_id'],
  133. 'remarks' => $params['remarks'],
  134. 'use_type' => $params['use_type'],
  135. 'secondary_card_id' => $params['secondary_card_id'],
  136. 'create_source_type' => $params['create_source_type'],
  137. 'create_source_id' => $params['create_source_id'],
  138. 'code' => $code,
  139. ];
  140. SecondaryCardRedemptionCode::setData($add_data);
  141. }
  142. $t->commit();
  143. LockHelper::uLock($lock_key, $identification);
  144. return true;
  145. } catch (\Exception $e) {
  146. $t->rollBack();
  147. LockHelper::uLock($lock_key, $identification);
  148. return true;
  149. }
  150. }
  151. public static function exportHandle($data)
  152. {
  153. $download_id = $data['download_id'] ?? 0;
  154. $download = Download::findOne(['id' => $download_id]);
  155. if ($download) {
  156. try {
  157. $params = json_decode($download->params, true);
  158. $filename = $download->name;
  159. $type = $download->type;
  160. $fields = $params['fields'];
  161. $fields_arr = SecondaryCardRedemptionCode::getExportFields();
  162. $have_select_field_arr = [];
  163. foreach ($fields as $value) {
  164. $have_select_field_arr[] = $fields_arr[$value];
  165. }
  166. $csv = new CsvTool();
  167. $csv->filename = $filename;
  168. $csv->file_dirname = DownloadEnum::getTypeStorageDirMap($type);
  169. $csv->export_mode = CsvTool::EXPORT_MODE_ASYNC;
  170. $csv->header = $have_select_field_arr;
  171. $params['order'] = 'id DESC';
  172. if (!empty($params['sort_column']) && !empty($params['sort_order'])) {
  173. $sort_order = $params['sort_order'] == 'ascending' ? 'asc' : 'desc';
  174. $params['order'] = $params['sort_column'] . ' ' . $sort_order;
  175. }
  176. $model = SecondaryCardRedemptionCode::find();
  177. $model->where(['mall_id' => $params['mall_id'], 'secondary_card_id' => $params['secondary_card_id'], 'status' => StatusEnum::ENABLED]);
  178. if (isset($params['is_use']) && $params['is_use'] !== '') {
  179. $model->andWhere(['is_use' => $params['is_use']]);
  180. }
  181. if (!empty($params['code'])) {
  182. $model->andWhere(['like', 'code', trim($params['code'])]);
  183. }
  184. if (!empty($params['remarks'])) {
  185. $model->andWhere(['like', 'remarks', trim($params['remarks'])]);
  186. }
  187. $model->with(['secondaryCard', 'secondaryCardOrder']);
  188. $model->orderBy('id DESC');
  189. if (!empty($params['sort_column']) && !empty($params['sort_order'])) {
  190. $sort_order = $params['sort_order'] == 'ascending' ? 'asc' : 'desc';
  191. $model->orderBy($params['sort_column'] . ' ' . $sort_order);
  192. }
  193. $mall_name = \Yii::$app->services->setting->mall->get($params['mall_id'], 'basic.name');
  194. foreach ($model->batch() as $list) {
  195. $o2o_store_ids = [];
  196. $o2o_store_list = [];
  197. foreach ($list as $item) {
  198. switch ($item['create_source_type']) {
  199. case 1:
  200. $o2o_store_ids[] = $item['create_source_id'];
  201. break;
  202. }
  203. }
  204. if (!empty($o2o_store_ids) && MallAddons::isInstall($params['mall_id'], 'Store')) {
  205. $o2o_store_list = SecondaryCardService::getO2OStoreList($o2o_store_ids);
  206. }
  207. $csv->data = array_map(function ($code_item) use ($fields, $o2o_store_list, $mall_name) {
  208. $row = [];
  209. //遍历所选字段
  210. foreach ($fields as $field) {
  211. if (in_array($field, ['use_time', 'created_at'])) {
  212. $row[] = !empty($code_item[$field]) ? date('Y-m-d H:i:s', $code_item[$field]) : '';
  213. } elseif (in_array($field, ['is_use'])) {
  214. $row[] = $code_item['is_use'] == 1 ? '已使用' : '未使用';
  215. } elseif (in_array($field, ['source'])) {
  216. $source_str = '';
  217. switch ($code_item['create_source_type']) {
  218. case 0:
  219. $source_str = $mall_name;
  220. break;
  221. case 1:
  222. $source_str = $o2o_store_list[$code_item['create_source_id']]['store_name'] ?? '';
  223. break;
  224. }
  225. $row[] = $source_str;
  226. } elseif (in_array($field, ['order_no'])) {
  227. $row[] = $code_item['secondaryCardOrder']['order_no'] ?? '';
  228. } else {
  229. $row[] = !empty($code_item[$field]) ? $code_item[$field] : '';
  230. }
  231. }
  232. return $row;
  233. }, $list);
  234. $csv->export();
  235. }
  236. $csv->updateDown($download, $params['mall_id']);
  237. return true;
  238. } catch (\Exception $e) {
  239. $download->status = 3;
  240. $res = $download->save();
  241. self::setStaticError($e->getMessage());
  242. return false;
  243. }
  244. }
  245. }
  246. public static function exportHandleSync($data)
  247. {
  248. try {
  249. $params = $data;
  250. $fields = $params['fields'];
  251. $fields_arr = SecondaryCardRedemptionCode::getExportFields();
  252. $have_select_field_arr = [];
  253. $post_fields_arr = explode(',', $fields);
  254. foreach ($post_fields_arr as $value) {
  255. $have_select_field_arr[] = $fields_arr[$value];
  256. }
  257. $csv = new CsvTool();
  258. $csv->export_mode = $data['export_mode'];
  259. $csv->filename = $data['filename'];
  260. $csv->export_mode = $data['export_mode'];
  261. $csv->header = $have_select_field_arr;
  262. $params['order'] = 'id DESC';
  263. if (!empty($params['sort_column']) && !empty($params['sort_order'])) {
  264. $sort_order = $params['sort_order'] == 'ascending' ? 'asc' : 'desc';
  265. $params['order'] = $params['sort_column'] . ' ' . $sort_order;
  266. }
  267. $model = SecondaryCardRedemptionCode::find();
  268. $model->where(['mall_id' => $params['mall_id'], 'secondary_card_id' => $params['secondary_card_id'], 'status' => StatusEnum::ENABLED]);
  269. if (isset($params['is_use']) && $params['is_use'] !== '') {
  270. $model->andWhere(['is_use' => $params['is_use']]);
  271. }
  272. if (!empty($params['code'])) {
  273. $model->andWhere(['code' => trim($params['code'])]);
  274. }
  275. if (!empty($params['remarks'])) {
  276. $model->andWhere(['remarks' => trim($params['remarks'])]);
  277. }
  278. $model->with(['secondaryCard', 'secondaryCardOrder']);
  279. $model->orderBy('id DESC');
  280. if (!empty($params['sort_column']) && !empty($params['sort_order'])) {
  281. $sort_order = $params['sort_order'] == 'ascending' ? 'asc' : 'desc';
  282. $model->orderBy($params['sort_column'] . ' ' . $sort_order);
  283. }
  284. $mall_name = \Yii::$app->services->setting->mall->get($params['mall_id'], 'basic.name');
  285. $list = $model->all();
  286. $o2o_store_ids = [];
  287. $o2o_store_list = [];
  288. foreach ($list as $item) {
  289. switch ($item['secondaryCard']['create_source_type']) {
  290. case 1:
  291. $o2o_store_ids[] = $item['create_source_id'];
  292. break;
  293. }
  294. }
  295. if (!empty($o2o_store_ids) && MallAddons::isInstall($params['mall_id'], 'Store')) {
  296. $o2o_store_list = SecondaryCardService::getO2OStoreList($o2o_store_ids);
  297. }
  298. foreach ($list as $code_item) {
  299. $row = [];
  300. //遍历所选字段
  301. foreach ($post_fields_arr as $field) {
  302. if (in_array($field, ['use_time', 'created_at'])) {
  303. $row[] = !empty($code_item[$field]) ? date('Y-m-d H:i:s', $code_item[$field]) : '';
  304. } elseif (in_array($field, ['is_use'])) {
  305. $row[] = $code_item['is_use'] == 1 ? '已使用' : '未使用';
  306. } elseif (in_array($field, ['source'])) {
  307. $source_str = '';
  308. switch ($code_item['secondaryCard']['create_source_type']) {
  309. case 0:
  310. $source_str = $mall_name;
  311. break;
  312. case 1:
  313. $source_str = $o2o_store_list[$code_item['secondaryCard']['create_source_id']]['store_name'] ?? '';
  314. break;
  315. }
  316. $row[] = $source_str;
  317. } elseif (in_array($field, ['order_no'])) {
  318. $row[] = $code_item['secondaryCardOrder']['order_no'] ?? '';
  319. } else {
  320. $row[] = !empty($code_item[$field]) ? $code_item[$field] : '';
  321. }
  322. }
  323. $data[] = $row;
  324. }
  325. $csv->data = $data;
  326. $csv->export();
  327. return true;
  328. } catch (\Exception $e) {
  329. self::setStaticError($e->getMessage());
  330. return false;
  331. }
  332. }
  333. public static function exchangeCode($params)
  334. {
  335. $lock_key = $params['code'];
  336. $identification = uniqid();
  337. $t = \Yii::$app->db->beginTransaction();
  338. try {
  339. if (!LockHelper::lock($lock_key, $identification, 30, 60)) throw new \Exception('当前访问人数过多');
  340. $where = [
  341. ['mall_id' => $params['mall_id']],
  342. ['code' => $params['code']],
  343. ['status' => StatusEnum::ENABLED],
  344. ];
  345. if (!empty($params['secondary_card_id'])) {
  346. $where[] = ['secondary_card_id' => $params['secondary_card_id']];
  347. }
  348. $model = SecondaryCardRedemptionCode::getOne($where, false);
  349. if (empty($model)) throw new \Exception('兑换码不存在');
  350. if (!empty($model['user_id'])) throw new \Exception('兑换码已被别人兑换');
  351. $secondary_card = SecondaryCard::getOne([['id' => $model['secondary_card_id'], 'mall_id' => $params['mall_id']]], false);
  352. if (empty($secondary_card)) throw new \Exception('次卡不存在');
  353. if (empty($secondary_card['is_on_sales'])) throw new \Exception('次卡已下架');
  354. $secondary_card->total_redemption += 1;
  355. $secondary_card->save();
  356. $time = time();
  357. if (!empty($secondary_card['sell_time_start']) && $time < $secondary_card['sell_time_start']) {
  358. throw new \Exception('次卡售卖时间还没开始');
  359. }
  360. if (!empty($secondary_card['sell_time_end']) && $time > $secondary_card['sell_time_end']) {
  361. $secondary_card->is_on_sales = 0;
  362. $secondary_card->save();
  363. throw new \Exception('次卡售卖时间已结束');
  364. }
  365. if ($secondary_card['expire_type'] == SecondaryCardEnum::EXPIRE_TYPE_APPOINT) {
  366. if (strtotime($secondary_card['end_at'] . ' 23:59:59') <= $secondary_card['sell_time_start']) {
  367. throw new \Exception('次卡的有效期结束时间小于次卡售卖的开始时间');
  368. }
  369. }
  370. $order_no = SecondaryCardOrder::getOrderNo();
  371. if ($order_no == false) {
  372. throw new \Exception('生成卡号失败');
  373. }
  374. $params['order_no'] = $order_no;
  375. $params['clerk_code'] = SecondaryCardOrderService::getClerkCode($params['mall_id']);
  376. $params['open_type'] = SecondaryCardEnum::OPEN_TYPE_EXCHANGE;
  377. $params['pay_money'] = 0;
  378. $params['start_time'] = SecondaryCardOrderService::getStartTime($secondary_card['expire_type'], $time, $secondary_card['begin_at']);
  379. $params['expire_time'] = SecondaryCardOrderService::getExpireTime($secondary_card['expire_type'], $time, $secondary_card['end_at'], $secondary_card['expire_day']);
  380. $params['open_time'] = $time;
  381. $params['verifiable_times'] = $secondary_card['verifiable_times'];
  382. $params['use_type'] = $secondary_card['use_type'];
  383. $params['secondary_card_id'] = $model['secondary_card_id'];
  384. $params['create_source_type'] = $model['create_source_type'];
  385. $params['create_source_id'] = $model['create_source_id'];
  386. $secondary_card_order = SecondaryCardOrder::setData($params);
  387. if (empty($secondary_card_order)) {
  388. throw new \Exception(SecondaryCardOrder::getStaticError());
  389. }
  390. $model->user_id = $params['user_id'];
  391. $model->is_use = SecondaryCardEnum::YES_USE;
  392. $model->use_time = $time;
  393. $model->order_no = $order_no;
  394. $model->save();
  395. LockHelper::uLock($lock_key, $identification);
  396. $t->commit();
  397. return ['order_id' => $secondary_card_order->id];
  398. } catch (\Exception $e) {
  399. LockHelper::uLock($lock_key, $identification);
  400. $t->rollBack();
  401. throw new \Exception($e->getMessage());
  402. }
  403. }
  404. }