SettleBoxReturn.php 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. <?php
  2. declare (strict_types = 1);
  3. namespace app\api\command;
  4. use app\common\model\BoxMidHandleModel;
  5. use app\common\model\MoneyLogModel;
  6. use app\common\model\ScoreLogModel;
  7. use app\common\model\SubmeterModel;
  8. use app\common\model\UserModel;
  9. use think\console\Command;
  10. use think\console\Input;
  11. use think\console\Output;
  12. use think\facade\Db;
  13. use utils\RedisCache;
  14. /**
  15. * 空袋结算退回 by wes 每天晚上21点后运行1次
  16. * Class SettleBoxReturn
  17. * @package app\api\command
  18. */
  19. class SettleBoxReturn extends Command
  20. {
  21. protected $cacheTime = 86400; // 一天
  22. protected function configure()
  23. {
  24. $this->setName('settle_box_return')
  25. ->setDescription('the settle_box_return command');
  26. }
  27. /**
  28. * 处理分表
  29. * @param Input $input
  30. * @param Output $output
  31. * @return int
  32. */
  33. protected function execute(Input $input, Output $output)
  34. {
  35. $cacheKey = "caches:boxReturn:".date('YmdHi');
  36. if(RedisCache::get($cacheKey.'_lock')){
  37. echo json_encode(['code'=>'error','msg'=>'请不要频繁提交,正在结算中稍后再试~','date'=>date('Y-m-d H:i:s')])."\n";
  38. return false;
  39. }
  40. if(date('H:i') <= '08:00' || (date('H:i')>'14:00' && date('H:i')<'15:00')||(date('H:i')>'19:00' && date('H:i') < '20:00')){
  41. echo json_encode(['code'=>'error','msg'=>'不在结算时间段9:00~14:00/15:00~19:00/20:00~24:00内~','date'=>date('Y-m-d H:i:s')])."\n";
  42. return false;
  43. }
  44. RedisCache::setnx($cacheKey.'_lock', date('Y-m-d H:i:s'), rand(5, 10));
  45. Db::startTrans();
  46. try {
  47. $startTime = microtime(true);
  48. if($result = $this->settleBoxReturn()){
  49. $endTime = microtime(true);
  50. $runTime = round(($endTime-$startTime)/1000, 3).'秒';
  51. $result['time'] = $runTime;
  52. echo json_encode($result, 256)."\n";
  53. Db::commit();
  54. }
  55. } catch (\Exception $e) {
  56. Db::rollback();
  57. $log = ['msg'=> $e->getMessage(),'trace'=>$e->getTrace(),'date'=>date('Y-m-d H:i:s')];
  58. RedisCache::set($cacheKey."_fail", $log, 5 * 3600);
  59. echo json_encode(['code'=>'error','msg'=>$e->getMessage(),'date'=>date('Y-m-d H:i:s')], 256)."\n";
  60. }
  61. return true;
  62. }
  63. /**
  64. * 结算空袋退回
  65. */
  66. public function settleBoxReturn()
  67. {
  68. // 空袋盒子
  69. $startTime = microtime(true);
  70. $date = date('Y-m-d H:i:s');
  71. $boxList = BoxMidHandleModel::where('box_settle_time','<=', $date)
  72. ->where(['goods_id'=>0,'status'=>1,'is_delete'=>2])
  73. ->field('id,h_sn,uid,rid,pay_type')
  74. ->order('uid')
  75. ->limit(2000)
  76. ->select();
  77. $boxList = $boxList? $boxList->toArray() : [];
  78. if(empty($boxList)){
  79. return ['code'=>500,'msg'=>'暂无数据处理','sql'=>BoxMidHandleModel::getLastSql(),'date'=>$date];
  80. }
  81. $scoreCount = $moneyCount = 0;
  82. $moneyLogs = $scoreLogs = $catchIds = [];
  83. $cacheKey = "caches:boxReturn:".date('YmdHi').'_';
  84. foreach ($boxList as $key=> $item){
  85. $boxMid = isset($item['id'])? $item['id'] : 0;
  86. // $rid = isset($item['rid'])? $item['rid'] : 0;
  87. $uid = isset($item['uid'])? $item['uid'] : 0;
  88. $payType = isset($item['pay_type'])? $item['pay_type'] : 0;
  89. $boxMoney = env('boxsetting.ONE_BOX_PRICE', 288);
  90. // 退回积分或余额
  91. $userInfo = UserModel::where('id', $uid)->field('score,money')->find();
  92. $userMoney = isset($userInfo['money'])? floatval($userInfo['money']) : 0;
  93. $userScore = isset($userInfo['score'])? intval($userInfo['score']) : 0;
  94. if($payType == 1){
  95. if(!UserModel::where('id', $uid)->inc('score', intval($boxMoney))->update()){
  96. RedisCache::set($cacheKey."{$uid}:{$boxMid}_error", ['msg'=>"退回用户[{$uid}]积分失败",'box'=> $item,'user'=>$userInfo,'date'=>$date], 7200);
  97. sr_throw("退回用户[{$uid}]积分失败");
  98. }
  99. $log = [
  100. 'uid'=>$uid,
  101. 'type'=> 2,
  102. 'score'=> $boxMoney,
  103. 'create_at'=> sr_getcurtime(time()),
  104. 'state'=> 1,
  105. 'before_score'=> $userScore,
  106. 'after_score'=> intval($userScore + $boxMoney),
  107. 'from_id'=> $boxMid,
  108. 'uid2'=> 0,
  109. 'remark'=> "空袋退回"
  110. ];
  111. $scoreLogs[] = $log;
  112. RedisCache::set($cacheKey."score_{$uid}:{$boxMid}_catch", ['msg'=>"退回用户[{$uid}]积分处理",'log'=>$log,'box'=> $item,'user'=>$userInfo,'date'=>$date], 7200);
  113. $scoreCount++;
  114. }
  115. // 退回余额
  116. else if($payType == 2){
  117. if(!UserModel::where('id', $uid)->inc('money', floatval($boxMoney))->update()){
  118. RedisCache::set($cacheKey."{$uid}:{$boxMid}_error", ['msg'=>"退回用户[{$uid}]余额失败",'box'=> $item,'user'=>$userInfo,'date'=>$date], 7200);
  119. sr_throw("退回用户[{$uid}]余额失败");
  120. }
  121. $log = [
  122. 'uid' => $uid,
  123. 'type' => 3,
  124. 'money' => $boxMoney,
  125. 'create_at' => sr_getcurtime(time()),
  126. 'state' => 1,
  127. 'before_money' => $userMoney,
  128. 'after_money' => floatval($userMoney + $boxMoney),
  129. 'from_id' => $boxMid,
  130. 'uid2' => 0,
  131. 'remark' => "空袋退回"
  132. ];
  133. $moneyLogs[] = $log;
  134. RedisCache::set($cacheKey."money_{$uid}:{$boxMid}_catch", ['msg'=>"退回用户[{$uid}]余额处理",'log'=>$log,'box'=> $item,'user'=>$userInfo,'date'=>$date], 7200);
  135. $moneyCount++;
  136. }
  137. $catchIds[] = $boxMid;
  138. }
  139. if($catchIds && !BoxMidHandleModel::whereIn('id', $catchIds)->update(['status'=> 2,'updated_time'=> $date])){
  140. sr_throw('处理盒子状态更新错误');
  141. }
  142. if(empty($scoreLogs) && empty($moneyLogs)){
  143. sr_throw('没有成功退回的盒子');
  144. }
  145. if($scoreLogs && !ScoreLogModel::insertAll(array_values($scoreLogs))){
  146. sr_throw('退还积分处理失败');
  147. }
  148. if($moneyLogs && !MoneyLogModel::insertAll(array_values($moneyLogs))){
  149. sr_throw('退还余额处理失败');
  150. }
  151. $endTime = microtime(true);
  152. $runTime = round(($endTime-$startTime)/1000, 3).'秒';
  153. RedisCache::set($cacheKey."_result", ['total'=> count($boxList),'score'=>count($scoreLogs),'money'=>count($moneyLogs),'time'=> $runTime], 3600);
  154. return ['code'=>200, 'msg'=>"成功退还".count($boxList)."个盒子,余额{$moneyCount}个,积分{$scoreCount}个",'time'=>$runTime,'date'=> $date];
  155. }
  156. }