Coupon.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. <?php namespace App\Http\Controllers\Admin;
  2. use App\Http\Requests\Admin\Coupon as Request;
  3. use App\Models\AdminUser;
  4. use App\Models\Coupon as Model;
  5. use App\Models\CouponProduct;
  6. use App\Models\CouponRebate;
  7. use App\Models\Custom;
  8. use App\Models\CustomCoupon;
  9. use App\Models\Product;
  10. use App\Models\FilesManager;
  11. use Illuminate\Support\Facades\DB;
  12. /**
  13. * 优惠券管理
  14. *
  15. * @author 刘相欣
  16. *
  17. */
  18. class Coupon extends Auth{
  19. protected function _initialize(){
  20. parent::_initialize();
  21. $this->assign('breadcrumb1','营销管理');
  22. $this->assign('breadcrumb2','优惠券管理');
  23. }
  24. /**
  25. * 首页列表
  26. *
  27. * */
  28. public function index(Model $Model,AdminUser $AdminUser,CustomCoupon $CustomCoupon){
  29. // 接受参数
  30. $code = request('coupon_code','');
  31. $status = request('status');
  32. $startTime = request('start_time','');
  33. $endTime = request('end_time','');
  34. // 编码转ID
  35. $id = $code ? $Model->codeToId($code) : 0;
  36. // 查询条件
  37. $map = [];
  38. // 编码ID
  39. if( $id ) $map[] = ['id','=',$id];
  40. if( $startTime ) $map[] = ['start_time','>=',strtotime($startTime)];
  41. if( $endTime ) $map[] = ['end_time','<=',strtotime($endTime)];
  42. if( !is_null($status) ) $map[] = ['status','=',$status];
  43. // 查询数据
  44. $list = $Model->query()->where($map)->orderByDesc('id')->paginate(request('limit',config('page_num',10)))->appends(request()->all());
  45. // 计算各个优惠券的数量
  46. $customTotal = $CustomCoupon->whereIn('coupon_id',array_column($list->toArray()['data'],'id'))->groupBy('coupon_id')->select([DB::raw('count(*) as total'),'coupon_id'])->pluck('total','coupon_id')->toArray();
  47. // 循环处理数据
  48. foreach ($list as $key => $value) {
  49. // id转编号
  50. $value['coupon_code']= $Model->idToCode($value['id']);
  51. // id转编号
  52. $value['admin_name'] = $AdminUser->getOne($value['admin_uid'],'username');
  53. // 过期时间
  54. $value['exp_time'] = $Model->getExpTime($value['exp_time']);
  55. // 如果过期时间
  56. if( $value['status'] == 0 && ( $value['exp_time']>0 && $value['exp_time']< time() ) ) {
  57. // 设置过期状态
  58. $Model->setStatusByExpire();
  59. // 状态设置
  60. $value['status'] =3;
  61. }
  62. // id转编号
  63. $value['custom_total'] = isset($customTotal[$value['id']]) ? $customTotal[$value['id']] : 0;
  64. // 重组
  65. $list[$key] = $value;
  66. }
  67. // 分配数据
  68. $this->assign('empty', '<tr><td colspan="20">~~暂无数据</td></tr>');
  69. $this->assign('list', $list);
  70. // 加载模板
  71. return $this->fetch();
  72. }
  73. /**
  74. * 添加
  75. *
  76. * */
  77. public function add( Request $request, Model $Model,Product $Product,Custom $Custom,FilesManager $FilesManager,CouponRebate $CouponRebate,CustomCoupon $CustomCoupon,CouponProduct $CouponProduct){
  78. if( request()->isMethod('post') ){
  79. // 验证参数
  80. $request->scene('add')->validate();
  81. // 组合数据
  82. $data['name'] = request('name',0);
  83. $data['rebate_type'] = request('rebate_type',0);
  84. $data['std_pay'] = request('std_pay',0);
  85. $data['rebate'] = request('rebate',0);
  86. $data['issue_total'] = request('issue_total',0);
  87. $data['start_time'] = request('start_time',date('Y-m-d'));
  88. $data['end_time'] = request('end_time','');
  89. $data['type_id'] = request('type_id',1);
  90. $data['is_appt'] = request('is_appt',1);
  91. // 根据是否上传了商品范围文件
  92. if( $data['type_id'] == 1 && !request()->hasFile('product_file') ) return json_send(['code'=>'error','msg'=>'请上传指定商品范围']);
  93. // 根据是否上传了客户范围文件
  94. if( $data['is_appt'] == 1 && !request()->hasFile('custom_file') ) return json_send(['code'=>'error','msg'=>'请上传指定客户范围']);
  95. // 转换时间,默认现在现在生效
  96. $data['start_time'] = $data['start_time'] ? strtotime($data['start_time']) : time();
  97. // 转换时间,默认无结束时间
  98. $data['end_time'] = $data['end_time'] ? strtotime($data['end_time'].' 23:59:59') : 0;
  99. // 判断有效时间类型。获取不同的过期时间
  100. $data['exp_time'] = request('exp_type',0) == 1 ? request('exp_days',0) : $data['end_time'];
  101. // 赠品ID
  102. $rebateId = 0;
  103. // 如果是赠品表的话。处理赠品逻辑
  104. if( $data['rebate_type'] == 3 ) {
  105. // 产品编码
  106. $rebateId = $Product->codeToId($data['rebate']);
  107. // 赠品ID不存在
  108. if( !$rebateId ) return json_send(['code'=>'error','msg'=>'赠品编码格式有误']);
  109. // 设置为0,避免数据异常
  110. $data['rebate'] = 0;
  111. }
  112. // 商品范围
  113. $products = [];
  114. // 如果是商品范围
  115. if( $data['type_id'] == 1 ) {
  116. // 读取文件获取指定的商品范围
  117. $products = $FilesManager->excelToCode(request()->file('product_file'),$Product);
  118. // 产品范围不存在
  119. if( !$products ) return json_send(['code'=>'error','msg'=>'请上传可用的商品范围']);
  120. // 商品数量
  121. if( count($products) > 1000 ) return json_send(['code'=>'error','msg'=>'可用的商品范围请勿超过1000']);
  122. }
  123. // 客户范围
  124. $customs = [];
  125. // 如果是客户范围
  126. if( $data['is_appt'] == 1 ) {
  127. // 读取文件获取指定的客户范围
  128. $customs = $FilesManager->excelToCode(request()->file('custom_file'),$Custom);
  129. // 客户范围不存在
  130. if( !$customs ) return json_send(['code'=>'error','msg'=>'请上传可用的客户范围']);
  131. // 客户数量
  132. if( count($customs) > 10000 ) return json_send(['code'=>'error','msg'=>'客户范围请勿超过10000']);
  133. }
  134. // 组合数据,写入订单表,子表
  135. DB::beginTransaction();
  136. try {
  137. // 写入
  138. $id = $Model->add($data);
  139. // 提示新增失败
  140. if( !$id ) {
  141. // 回滚
  142. DB::rollBack();
  143. // 提示失败
  144. return json_send(['code'=>'error','msg'=>'新增失败']);
  145. }
  146. // 当前时间
  147. $time = time();
  148. // 如果有商品范围
  149. if( $products ) {
  150. // 循环商品
  151. foreach ($products as $key => $value) {
  152. // 时间处理
  153. $value = ['coupon_id'=>$id,'product_id'=>$value,'insert_time'=>$time,'update_time'=>$time];
  154. // 重组
  155. $products[$key] = $value;
  156. }
  157. // 写入数据
  158. $result = $CouponProduct->insert($products);
  159. // 提示新增失败
  160. if( !$result ) {
  161. // 回滚
  162. DB::rollBack();
  163. // 提示失败
  164. return json_send(['code'=>'error','msg'=>'商品范围写入失败']);
  165. }
  166. }
  167. // 如果是赠品
  168. if( $rebateId ) {
  169. // 写入数据
  170. $result = $CouponRebate->add(['coupon_id'=>$id,'product_id'=>$rebateId,'rebate_num'=>1]);
  171. // 提示新增失败
  172. if( !$result ) {
  173. // 回滚
  174. DB::rollBack();
  175. // 提示失败
  176. return json_send(['code'=>'error','msg'=>'赠品结果写入失败']);
  177. }
  178. }
  179. // 如果有客户范围
  180. if( $customs ) {
  181. // 分块,每1000一批写入
  182. foreach (array_chunk($customs,1000) as $chunk) {
  183. // 循环客户
  184. foreach ($chunk as $key => $value) {
  185. // 时间处理
  186. $value = ['coupon_id'=>$id,'custom_uid'=>$value,'exp_time'=>$Model->getExpTime($data['exp_time']),'insert_time'=>$time,'update_time'=>$time];
  187. // 重组
  188. $chunk[$key] = $value;
  189. }
  190. // 写入数据
  191. $result = $CustomCoupon->insert($chunk);
  192. // 提示新增失败
  193. if( !$result ) {
  194. // 回滚
  195. DB::rollBack();
  196. // 提示失败
  197. return json_send(['code'=>'error','msg'=>'客户范围写入失败']);
  198. }
  199. }
  200. }
  201. // 提交
  202. DB::commit();
  203. } catch (\Throwable $th) {
  204. // 回滚
  205. DB::rollBack();
  206. // 提示失败
  207. return json_send(['code'=>'error','msg'=>'内部错误,请重试','data'=>['error'=>$th->getMessage()]]);
  208. }
  209. // 记录行为
  210. $this->addAdminHistory(admin('uid'),$Model->getTable(),$id,1,[],$data);
  211. // 告知结果
  212. return json_send(['code'=>'success','msg'=>'新增成功','action'=>'add']);
  213. }
  214. // 分配数据
  215. $this->assign('crumbs','新增');
  216. // 加载模板
  217. return $this->fetch();
  218. }
  219. /**
  220. * 编辑
  221. *
  222. * */
  223. public function edit( Request $request, Model $Model,Product $Product,Custom $Custom,FilesManager $FilesManager,CouponRebate $CouponRebate,CustomCoupon $CustomCoupon,CouponProduct $CouponProduct){
  224. // 接收参数
  225. $id = request('id',0);
  226. // 查询数据
  227. $oldData = $Model->where(['id'=>$id])->first();
  228. // 修改
  229. if(request()->isMethod('post')){
  230. // 验证参数
  231. $request->scene('edit')->validate();
  232. // 组合数据
  233. $data['name'] = request('name',0);
  234. $data['rebate_type'] = request('rebate_type',0);
  235. $data['std_pay'] = request('std_pay',0);
  236. $data['rebate'] = request('rebate',0);
  237. $data['issue_total'] = request('issue_total',0);
  238. $data['start_time'] = request('start_time',date('Y-m-d'));
  239. $data['end_time'] = request('end_time','');
  240. $data['type_id'] = request('type_id',1);
  241. $data['is_appt'] = request('is_appt',1);
  242. // 转换时间,默认现在现在生效
  243. $data['start_time'] = $data['start_time'] ? strtotime($data['start_time']) : time();
  244. // 转换时间,默认无结束时间
  245. $data['end_time'] = $data['end_time'] ? strtotime($data['end_time'].' 23:59:59') : 0;
  246. // 判断有效时间类型。获取不同的过期时间
  247. $data['exp_time'] = request('exp_type',0) == 1 ? request('exp_days',0) : $data['end_time'];
  248. // 折扣不能超过10
  249. if( $data['rebate_type'] == 2 && $data['rebate'] > 9.99 ) return json_send(['code'=>'error','msg'=>'不能设置大于9.99折']);
  250. // 赠品ID
  251. $rebateId = 0;
  252. // 如果是赠品表的话。处理赠品逻辑
  253. if( $data['rebate_type'] == 3 ) {
  254. // 产品编码
  255. $rebateId = $Product->codeToId($data['rebate']);
  256. // 赠品ID不存在
  257. if( !$rebateId ) return json_send(['code'=>'error','msg'=>'赠品编码格式有误']);
  258. // 设置为0,避免数据异常
  259. $data['rebate'] = 0;
  260. }
  261. // 商品范围
  262. $products = [];
  263. // 如果是商品范围,并且上传了文件
  264. if( $data['type_id'] == 1 && request()->hasFile('product_file')) {
  265. // 读取文件获取指定的商品范围
  266. $products = $FilesManager->excelToCode(request()->file('product_file'),$Product);
  267. // 产品范围不存在
  268. if( !$products ) return json_send(['code'=>'error','msg'=>'请上传可用的商品范围']);
  269. // 商品数量
  270. if( count($products) > 1000 ) return json_send(['code'=>'error','msg'=>'可用的商品范围请勿超过1000']);
  271. }
  272. // 客户范围
  273. $customs = [];
  274. // 如果是客户范围,并且上传了文件
  275. if( $data['is_appt'] == 1 && request()->hasFile('custom_file') ) {
  276. // 读取文件获取指定的客户范围
  277. $customs = $FilesManager->excelToCode(request()->file('custom_file'),$Custom);
  278. // 客户范围不存在
  279. if( !$customs ) return json_send(['code'=>'error','msg'=>'请上传可用的客户范围']);
  280. // 客户数量
  281. if( count($customs) > 10000 ) return json_send(['code'=>'error','msg'=>'客户范围请勿超过10000']);
  282. }
  283. // 组合数据,写入订单表,子表
  284. DB::beginTransaction();
  285. try {
  286. // 写入
  287. $result = $Model->edit($id,$data);
  288. // 提示新增失败
  289. if( !$result ) {
  290. // 回滚
  291. DB::rollBack();
  292. // 提示失败
  293. return json_send(['code'=>'error','msg'=>'新增失败']);
  294. }
  295. // 如果是赠品券
  296. if( $rebateId ) {
  297. // 查询旧的
  298. $oldRebateId = $CouponRebate->query()->where([['coupon_id','=',$id],['product_id','=',$rebateId]])->value('id');
  299. // 如果旧的与新的不一致
  300. if( $oldRebateId != $rebateId ) {
  301. // 删除旧的
  302. $CouponRebate->query()->where([['coupon_id','=',$id],['product_id','=',$rebateId]])->delete();
  303. // 有旧的修改,无则添加新的
  304. $result = $oldRebateId ? $CouponRebate->edit($oldRebateId,['product_id'=>$rebateId,'rebate_num'=>1]) : $CouponRebate->add(['coupon_id'=>$id,'product_id'=>$rebateId,'rebate_num'=>1]);
  305. // 提示新增失败
  306. if( !$result ) {
  307. // 回滚
  308. DB::rollBack();
  309. // 提示失败
  310. return json_send(['code'=>'error','msg'=>'赠品结果写入失败']);
  311. }
  312. }
  313. }
  314. // 当前时间
  315. $time = time();
  316. // 如果有商品范围
  317. if( $products ) {
  318. // 循环商品
  319. foreach ($products as $key => $value) {
  320. // 时间处理
  321. $value = ['coupon_id'=>$id,'product_id'=>$value,'insert_time'=>$time,'update_time'=>$time];
  322. // 重组
  323. $products[$key] = $value;
  324. }
  325. // 写入数据
  326. $result = $CouponProduct->insert($products);
  327. // 提示新增失败
  328. if( !$result ) {
  329. // 回滚
  330. DB::rollBack();
  331. // 提示失败
  332. return json_send(['code'=>'error','msg'=>'商品范围写入失败']);
  333. }
  334. }
  335. // 如果有客户范围
  336. if( $customs ) {
  337. // 分块,每1000一批写入
  338. foreach (array_chunk($customs,1000) as $chunk) {
  339. // 循环客户
  340. foreach ($chunk as $key => $value) {
  341. // 时间处理
  342. $value = ['coupon_id'=>$id,'custom_uid'=>$value,'exp_time'=>$Model->getExpTime($data['exp_time']),'insert_time'=>$time,'update_time'=>$time];
  343. // 重组
  344. $chunk[$key] = $value;
  345. }
  346. // 写入数据
  347. $result = $CustomCoupon->insert($chunk);
  348. // 提示新增失败
  349. if( !$result ) {
  350. // 回滚
  351. DB::rollBack();
  352. // 提示失败
  353. return json_send(['code'=>'error','msg'=>'客户范围写入失败']);
  354. }
  355. }
  356. }
  357. // 提交
  358. DB::commit();
  359. } catch (\Throwable $th) {
  360. // 回滚
  361. DB::rollBack();
  362. // 提示失败
  363. return json_send(['code'=>'error','msg'=>'内部错误,请重试','data'=>['error'=>$th->getMessage()]]);
  364. }
  365. // 记录行为
  366. $this->addAdminHistory(admin('uid'),$Model->getTable(),$id,2,[],$data);
  367. // 告知结果
  368. return json_send(['code'=>'success','msg'=>'修改成功','action'=>'edit']);
  369. }
  370. // 如果是没有数据
  371. if( !$oldData ) return $this->error('查无数据');
  372. // 如果是赠品表的话。处理赠品逻辑
  373. if( $oldData['rebate_type'] == 3 ) {
  374. // 产品编码
  375. $rebateId = $CouponRebate->getProductByCouponId($oldData['id']);
  376. // 产品ID
  377. $rebateId = isset($rebateId[0]['product_id']) ? $Product->idToCode($rebateId[0]['product_id']) : '';
  378. // 设置为0,避免数据异常
  379. $oldData['rebate'] = $rebateId;
  380. }
  381. // 有效期,时间戳或者时间为0表示的时间段,否则表示领取后N天
  382. $oldData['exp_type'] = $oldData['exp_time'] > 1000 ? 2 : 1;
  383. // 分配数据
  384. $this->assign('oldData',$oldData);
  385. $this->assign('crumbs','修改');
  386. // 加载模板
  387. return $this->fetch();
  388. }
  389. /**
  390. * 状态
  391. *
  392. * */
  393. public function set_status( Request $request, Model $Model,CustomCoupon $CustomCoupon ){
  394. // 验证参数
  395. $request->scene('set_status')->validate();
  396. // 接收参数
  397. $id = request('id',0);
  398. $status = request('status',0);
  399. // 查询数据
  400. $result = $Model->edit($id,['status'=>$status]);
  401. // 提示新增失败
  402. if( !$result ) return json_send(['code'=>'error','msg'=>'设置失败']);
  403. // 查询数据
  404. $result = $CustomCoupon->setStatusByCouponId($id,$status);
  405. // 提示新增失败
  406. if( !$result ) return json_send(['code'=>'error','msg'=>'同步设置失败']);
  407. // 记录行为
  408. $this->addAdminHistory(admin('uid'),$Model->getTable(),$id,2,[],['status'=>$status]);
  409. // 告知结果
  410. return json_send(['code'=>'success','msg'=>'设置成功','path'=>'']);
  411. }
  412. }