ChannelSettle.php 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905
  1. <?php
  2. /**
  3. * 渠道结算单管理相关控制器
  4. */
  5. namespace app\admin\controller;
  6. use app\common\library\MakeReportGo;
  7. use app\common\model\Channel;
  8. use app\common\model\Admin as AdminModel;
  9. use app\common\model\Setting;
  10. use app\common\library\MakeReport;
  11. use app\common\library\FileUpload;
  12. use think\Db;
  13. use think\Exception;
  14. class ChannelSettle extends Admin
  15. {
  16. protected $redis; //redis的句柄对象
  17. /**
  18. * 不进行父类的登录验证,所以增加构造方法重写了父类的初始化方法
  19. */
  20. protected function _initialize()
  21. {
  22. parent::_initialize();
  23. $this->redis = \think\Cache::store('default')->handler();
  24. }
  25. /**
  26. * 渠道结算单列表
  27. */
  28. public function index()
  29. {
  30. $settle_type = input('settle_type',0,'intval');
  31. $first_audit_status = input('first_audit_status',0,'intval');
  32. $second_audit_status = input('second_audit_status',0,'intval');
  33. $begin_time = input('start','','trim');
  34. $end_time = input('end','','trim');
  35. $channelModel = new Channel;
  36. $where = [];
  37. //渠道名
  38. if(input('request.channel_id')!='')
  39. {
  40. $where['a.channel_id'] = input('request.channel_id',0,'intval');
  41. }
  42. //区服类型
  43. if(input('request.settle_type')!=''){
  44. $where['a.settle_type'] = $settle_type;
  45. }
  46. //一级审核状态
  47. if(input('request.first_audit_status')!=''){
  48. $where['a.first_audit_status'] = $first_audit_status;
  49. }
  50. //二级审核状态
  51. if(input('request.second_audit_status')!=''){
  52. $where['a.second_audit_status'] = $second_audit_status;
  53. }
  54. //申请开始时间和结束时间不为空时
  55. if ($begin_time != '' && $end_time != '') {
  56. $where['a.create_time'] = [
  57. ['>=', strtotime($begin_time)],
  58. ['<=', strtotime($end_time . ' 23:59:59')],
  59. ];
  60. } //开始时间不为空时
  61. elseif ($begin_time != '') {
  62. $where['a.create_time'] = ['>=', strtotime($begin_time)];
  63. } //结束时间不为空时
  64. elseif ($end_time != '') {
  65. $where['a.create_time'] = ['<=', strtotime($end_time . ' 23:59:59')];
  66. }
  67. $channelList = $channelModel->getAllByCondition('id,name',['level'=>1,'flag'=>3],'name asc');
  68. if (request()->isAjax() && input('download')) {
  69. $sql = model('ChannelDivideSettle')->alias('a')
  70. ->join('nw_channel c','a.channel_id=c.id','left')
  71. ->field('a.*,c.name as channel_name')
  72. ->where($where)
  73. ->order('a.create_time desc')
  74. ->fetchSql(true)->select();
  75. if((new MakeReportGo())->addTask('admin.settleIndex',$sql,session_id())){
  76. $this->success('报表生成的任务已经提交, 报表生成完成后,会及时通知您,请耐心稍等');
  77. }
  78. else{
  79. $this->error('报表生成任务不可重复提交,如遇到无法导出情况,建议修改查询条件解除当前状态,提交重新生成报表任务!');
  80. }
  81. }
  82. $param = input('request.'); //分页带条件
  83. $list = model('ChannelDivideSettle')->alias('a')
  84. ->join('nw_channel c','a.channel_id=c.id','left')
  85. ->field('a.*,c.name as channel_name')
  86. ->where($where)
  87. ->order('a.create_time desc')
  88. ->paginate(10,false,array('query' => $param));
  89. // 获取分页显示的HTML
  90. $page = $list->render();
  91. $this->assign('channel_list',$channelList);
  92. $this->assign('list', $list);
  93. $this->assign('page', $page);
  94. $this->assign('start', $begin_time);
  95. $this->assign('end', $end_time);
  96. return $this->fetch();
  97. }
  98. /**
  99. * 二级结算单审核列表
  100. */
  101. public function checklist()
  102. {
  103. $settle_type = input('settle_type',0,'intval');
  104. $settle_period = input('settle_period',0,'intval');
  105. $second_audit_status = input('second_audit_status',0,'intval');
  106. $begin_time = input('start','','trim');
  107. $end_time = input('end','','trim');
  108. $channelModel = new Channel;
  109. $where = [];
  110. $where['a.first_audit_status'] = 1;
  111. //渠道名
  112. if(input('request.channel_id')!='')
  113. {
  114. $where['a.channel_id'] = input('request.channel_id',0,'intval');
  115. }
  116. //区服类型
  117. if(input('request.settle_type')!=''){
  118. $where['a.settle_type'] = $settle_type;
  119. }
  120. //结算方式
  121. if(input('request.settle_period')!=''){
  122. $where['a.settle_period'] = $settle_period;
  123. }
  124. //二级审核状态
  125. if(input('request.second_audit_status') != ''){
  126. $where['a.second_audit_status'] = $second_audit_status;
  127. }
  128. //申请开始时间和结束时间不为空时
  129. if ($begin_time != '' && $end_time != '') {
  130. $where['a.create_time'] = [
  131. ['>=', strtotime($begin_time)],
  132. ['<=', strtotime($end_time . ' 23:59:59')],
  133. ];
  134. } //开始时间不为空时
  135. elseif ($begin_time != '') {
  136. $where['a.create_time'] = ['>=', strtotime($begin_time)];
  137. } //结束时间不为空时
  138. elseif ($end_time != '') {
  139. $where['a.create_time'] = ['<=', strtotime($end_time . ' 23:59:59')];
  140. }
  141. $channelList = $channelModel->getAllByCondition('id,name',['level'=>1,'flag'=>3],'name asc');
  142. if (request()->isAjax() && input('download')) {
  143. $sql = model('ChannelDivideSettle')->alias('a')
  144. ->join('nw_channel c','a.channel_id=c.id','left')
  145. ->field('a.*,c.name as channel_name')
  146. ->where($where)
  147. ->order('a.create_time desc')
  148. ->fetchSql(true)->select();
  149. if((new MakeReportGo())->addTask('admin.settleCheckList',$sql,session_id())){
  150. $this->success('报表生成的任务已经提交, 报表生成完成后,会及时通知您,请耐心稍等');
  151. }
  152. else{
  153. $this->error('报表生成任务不可重复提交,如遇到无法导出情况,建议修改查询条件解除当前状态,提交重新生成报表任务!');
  154. }
  155. }
  156. $param = input('request.'); //分页带条件
  157. $list = model('ChannelDivideSettle')->alias('a')
  158. ->join('nw_channel c','a.channel_id=c.id','left')
  159. ->field('a.*,c.name as channel_name')
  160. ->where($where)
  161. ->order('a.create_time desc')
  162. ->paginate(10,false,array('query' => $param));
  163. // 获取分页显示的HTML
  164. $page = $list->render();
  165. $this->assign('channel_list',$channelList);
  166. $this->assign('list', $list);
  167. $this->assign('page', $page);
  168. $this->assign('start', $begin_time);
  169. $this->assign('end', $end_time);
  170. return $this->fetch();
  171. }
  172. //一级审核
  173. public function audit()
  174. {
  175. if (request()->isAjax()) {
  176. $id = input('id',0,'intval');
  177. $beizhu = input('beizhu','','trim');
  178. $status = input('status','0','intval');
  179. if(empty($id)){
  180. $this->error('ID不能为空');
  181. }
  182. if($status<>1 && $status<>2){
  183. $this->error('非法审核状态');
  184. }
  185. $settleInfo = model('ChannelDivideSettle')->where(['id' => $id])->find();
  186. if(empty($settleInfo)){
  187. $this->error('结算单不存在');
  188. }
  189. else if($settleInfo['first_audit_status']<>0){
  190. $this->error('该结算单已经一级审核过,不能再进行审核');
  191. }
  192. if($status == $settleInfo['first_audit_status']){
  193. $this->error('您未更改订单状态,请选择要更改的状态');
  194. }
  195. //检查账号
  196. if(!$settleInfo['channel_id']){
  197. $this->error('结算单异常:无归属渠道');
  198. }
  199. $channelInfo = model('Channel')->where(['id'=>$settleInfo['channel_id']])->find();
  200. if (empty($channelInfo)){
  201. $this->error('结算单异常:结算单归属渠道不存在');
  202. }
  203. else if($channelInfo['level'] <> 1){
  204. $this->error('结算单异常:结算单归属渠道层级有误');
  205. }
  206. $auditData = array();
  207. $auditData['id'] = $id;
  208. $auditData['first_audit_status'] = $status;
  209. $auditData['first_audit_time'] = NOW_TIMESTAMP;
  210. $auditData['first_audit_remark'] = $beizhu;
  211. $auditData['first_audit_admin_name'] = session('USERNAME');
  212. Db::startTrans();
  213. try {
  214. if($status==2){ //审核不通过,退回
  215. $result = model('ChannelDivideSettle')->where(['id'=>$id,'first_audit_status'=>array('in',[0])])->update($auditData);
  216. if (!$result) {
  217. throw new Exception("更改结算单状态失败");
  218. }
  219. //恢复订单为未结算
  220. $updPayData = array();
  221. $updPayData['settle_channel_id'] = 0;
  222. $updPayData['settle_id'] = 0;
  223. $updPayData['settle_update_time'] = 0;
  224. $updResult = model('Pay')->where(['settle_id'=>$settleInfo['id'],'settle_channel_id'=>$settleInfo['channel_id']])->update($updPayData);
  225. if ( !$updResult) {
  226. throw new Exception("更新订单为未结算失败");
  227. }
  228. $this->insertLog($this->current_node, "渠道结算单一级审核,结算单ID:".$settleInfo['id'].",审核状态:审核不通过",172);
  229. }
  230. else if($status==1){ //一级审核通过
  231. $result = model('ChannelDivideSettle')->where(['id'=>$id,'first_audit_status'=>array('in',[0])])->update($auditData);
  232. if (!$result) {
  233. throw new Exception("更改结算单状态失败");
  234. }
  235. $this->insertLog($this->current_node, "渠道结算单一级审核,结算单ID:".$settleInfo['id'].",审核状态:审核通过",172);
  236. }
  237. Db::commit();
  238. } catch (\Exception $e) {
  239. Db::rollback();
  240. $this->error("添加失败: " . $e->getMessage());
  241. }
  242. $this->success('审核成功');
  243. }
  244. else{
  245. $this->error('非法请求');
  246. }
  247. }
  248. //二级审核
  249. public function secondAudit()
  250. {
  251. if (request()->isAjax()) {
  252. $id = input('id',0,'intval');
  253. $beizhu = input('beizhu','','trim');
  254. $status = input('status','0','intval');
  255. if(empty($id)){
  256. $this->error('ID不能为空');
  257. }
  258. if($status<>1 && $status<>2){
  259. $this->error('非法审核状态');
  260. }
  261. $settleInfo = model('ChannelDivideSettle')->where(['id' => $id])->find();
  262. if(empty($settleInfo)){
  263. $this->error('结算单不存在');
  264. }
  265. else if($settleInfo['first_audit_status'] <> 1){
  266. $this->error('结算单一级审核未通过,不能进行审核');
  267. }
  268. else if($settleInfo['second_audit_status'] <> 0){
  269. $this->error('结算单审核已审核过,不能再进行审核');
  270. }
  271. if($status == $settleInfo['second_audit_status']){
  272. $this->error('您未更改订单状态,请选择要更改的状态');
  273. }
  274. //检查账号
  275. if(!$settleInfo['channel_id']){
  276. $this->error('结算单异常:无归属渠道');
  277. }
  278. $channelInfo = model('Channel')->where(['id'=>$settleInfo['channel_id']])->find();
  279. if (empty($channelInfo)){
  280. $this->error('结算单异常:结算单归属公会不存在');
  281. }
  282. else if($channelInfo['level'] <> 1){
  283. $this->error('结算单异常:结算单归属公会层级有误');
  284. }
  285. if($status==1){
  286. if($settleInfo['settle_method'] == 2){ //审核外放渠道结算单
  287. if(!$channelInfo['parent_id']){
  288. $this->error('结算单异常:结算单公会账号无所属商务!');
  289. }
  290. $parentChannelInfo = model("Channel")->field("id,name,level,parent_id,status,channel_tg_type")->where(['id'=>$channelInfo['parent_id']])->find();
  291. if(empty($parentChannelInfo)){
  292. $this->error('结算单公会账号所属商务不存在,请确认结算审核单是否有误');
  293. }
  294. else if($parentChannelInfo['channel_tg_type'] <> 1){
  295. $this->error('结算单公会账号所属商务为非外部投放渠道,请确认结算申请是否有误!');
  296. }
  297. $relChannelInfo = model("ChannelInfo")->where(['channel_id'=>$channelInfo['parent_id']])->find();
  298. if(!$relChannelInfo){
  299. $this->error('外部投放渠道结算审核,请先通知所属商务补充完身份认证相关信息后再进行操作');
  300. }
  301. $channelInfoApply = model("ChannelInfo")->field("id,channel_id,real_name,apply_status,type,person_id,zfb_account,bank_ban_mobile,bank_number,bank_province_city,bank_name,bank_open_name,bank_open_number")->where(['channel_id'=>$channelInfo['parent_id'],'apply_status'=>1])->find();
  302. if(empty($channelInfoApply)){
  303. $this->error('外部投放渠道结算审核,所属商务的身份认证尚未认证通过,不能进行操作');
  304. }
  305. }
  306. }
  307. $auditData = array();
  308. $auditData['id'] = $id;
  309. $auditData['second_audit_status'] = $status;
  310. $auditData['second_audit_time'] = NOW_TIMESTAMP;
  311. $auditData['second_audit_remark'] = $beizhu;
  312. $auditData['second_audit_admin_name'] = session('USERNAME');
  313. Db::startTrans();
  314. try {
  315. if($status==1){ //审核通过
  316. //添加账户金额变动信息
  317. $detData = array();
  318. $detData['channel_id'] = $channelInfo['id'];
  319. $detData['channel_name'] = $channelInfo['name'];
  320. $detData['change_amount'] = $settleInfo['total_divide_amt'];
  321. $detData['account_type'] = 2; //结算账户
  322. $detData['type'] = 8; //结算收入
  323. $detData['out_orderid'] = $settleInfo['orderid'];
  324. $detData['create_time'] = NOW_TIMESTAMP;
  325. $insertDetId = model('ChannelAccountDet')->insertGetId($detData);
  326. if ( !$insertDetId) {
  327. throw new Exception("添加账户变动明细失败");
  328. }
  329. $updData = array();
  330. $updData['js_amount'] = Db::raw("js_amount+".$settleInfo['total_divide_amt']);
  331. $updData['update_time'] = time();
  332. $updResult = model('Channel')->where(['id'=>$channelInfo['id']])->update($updData);
  333. if (!$updResult) {
  334. throw new Exception("账户金额变动失败");
  335. }
  336. $result = model('ChannelDivideSettle')->where(['id'=>$id,'first_audit_status'=>array('in',[1]),'second_audit_status'=>array('in',[0])])->update($auditData);
  337. if ($result === false) {
  338. throw new Exception("更改结算单状态失败");
  339. }
  340. if($settleInfo['settle_method'] == 2){ //审核外放渠道结算单
  341. //指定时间内,禁止重复下单
  342. if(!requestDuplicateCheck('channel_withdraw_duplicate_'.$settleInfo['channel_id'],10)){
  343. throw new Exception("结算审核通过完成自动提现时请求过多,请于10s以后,再次进行提现操作");
  344. }
  345. $orderid = 'W'.makeOrderid();
  346. $withdrawData = array();
  347. $withdrawData['orderid'] = $orderid;
  348. $withdrawData['channel_id'] = $channelInfo['id'];
  349. $withdrawData['channel_name'] = $channelInfo['name'];
  350. $withdrawData['withdraw_amt'] = $settleInfo['total_divide_amt'];
  351. $withdrawData['remark'] = '外部投放公会提现';
  352. $withdrawData['status'] = 1;
  353. $withdrawData['create_time'] = time();
  354. $withdrawData['audit_time'] = time();
  355. $withdrawData['audit_remark'] = '外部投放公会提现自动审核通过';
  356. $withdrawData['audit_admin_name'] = session('USERNAME');
  357. $withdrawData['real_name'] = $channelInfoApply['real_name'];
  358. $withdrawData['person_id'] = $channelInfoApply['person_id'];
  359. $withdrawData['zfb_account'] = $channelInfoApply['zfb_account'];
  360. $withdrawData['bank_ban_mobile']= $channelInfoApply['bank_ban_mobile'];
  361. $withdrawData['bank_number'] = $channelInfoApply['bank_number'];
  362. $withdrawData['bank_province_city'] = $channelInfoApply['bank_province_city'];
  363. $withdrawData['bank_name'] = $channelInfoApply['bank_name'];
  364. $withdrawData['bank_open_name'] = $channelInfoApply['bank_open_name'];
  365. $withdrawData['bank_open_number'] = $channelInfoApply['bank_open_number'];
  366. $insertWithdrawId = model("ChannelWithdraw")->insert($withdrawData);
  367. if(!$insertWithdrawId){
  368. throw new Exception("创建提现订单失败! ");
  369. }
  370. $detData = array();
  371. $detData['channel_id'] = $channelInfo['id'];
  372. $detData['channel_name'] = $channelInfo['name'];
  373. $detData['change_amount'] = -$settleInfo['total_divide_amt'];
  374. $detData['account_type'] = 2; //结算账户
  375. $detData['type'] = 9; //提现
  376. $detData['out_orderid'] = $orderid;
  377. $detData['create_time'] = NOW_TIMESTAMP;
  378. $insertDetId = model('ChannelAccountDet')->insertGetId($detData);
  379. if ( !$insertDetId) {
  380. throw new Exception("添加账户变动明细失败");
  381. }
  382. $updData = array();
  383. $updData['js_amount'] = Db::raw("js_amount-".$settleInfo['total_divide_amt']);
  384. $updData['update_time'] = time();
  385. $updResult = model('Channel')->where(['id'=>$channelInfo['id'],'js_amount'=>array('egt',$settleInfo['total_divide_amt'])])->update($updData);
  386. if (!$updResult) {
  387. throw new Exception("账户金额变动失败");
  388. }
  389. $this->redis->del('channel_withdraw_duplicate_'.$settleInfo['channel_id']);
  390. }
  391. $this->insertLog($this->current_node, "外部投放渠道结算单审核,结算单ID:".$settleInfo['id'].",审核状态:审核通过",172);
  392. }
  393. else if($status==2){ //接单已刷单改状态
  394. $result = model('ChannelDivideSettle')->where(['id'=>$id,'first_audit_status'=>array('in',[1]),'second_audit_status'=>array('in',[0])])->update($auditData);
  395. if ($result === false) {
  396. throw new Exception("更改结算单状态失败");
  397. }
  398. //恢复订单为未结算
  399. $updPayData = array();
  400. $updPayData['settle_channel_id'] = 0;
  401. $updPayData['settle_id'] = 0;
  402. $updPayData['settle_update_time'] = 0;
  403. $updResult = model('Pay')->where(['settle_id'=>$settleInfo['id'],'settle_channel_id'=>$settleInfo['channel_id']])->update($updPayData);
  404. if ( !$updResult) {
  405. throw new Exception("更新订单为未结算失败");
  406. }
  407. $this->insertLog($this->current_node, "渠道结算单审核,结算单ID:".$settleInfo['id'].",审核状态:审核不通过",172);
  408. }
  409. Db::commit();
  410. } catch (\Exception $e) {
  411. Db::rollback();
  412. $this->error("添加失败: " . $e->getMessage());
  413. }
  414. $adminInfo = model('ChannelAdmin')->where(['channel_id'=>$settleInfo['channel_id'],'mobile'=>['neq','']])->find();
  415. if (!empty($adminInfo) && $adminInfo['mobile']){
  416. $result = (new \app\common\library\Sms)->sendSettleAuditInfo($channelInfo['name'], $adminInfo['mobile'], $settleInfo['orderid'], $status);
  417. }
  418. $this->success('审核成功');
  419. }
  420. else{
  421. $this->error('非法请求');
  422. }
  423. }
  424. /**
  425. * 渠道结算单列表
  426. */
  427. public function detail()
  428. {
  429. $settleId = input('settleId',0,'intval');
  430. if(!$settleId){
  431. $this->error('请选择结算单ID');
  432. }
  433. $where = array();
  434. $where['id'] = $settleId;
  435. $settleInfo = model("ChannelDivideSettle")->where($where)->field("id,orderid,total_amount,total_divide_amt,remark")->find();
  436. if(!$settleInfo){
  437. $this->error('该结算单不存在或您不能查看');
  438. }
  439. $where = array();
  440. $where['p.settle_id'] = $settleId;
  441. // var_dump($where);
  442. $settleDetInfo = model("ChannelDivideSettleDet")->alias('p')
  443. ->join('cy_game g', 'p.game_id = g.id','left')
  444. ->field("p.game_id AS game_id,g.name as game_name,p.pay_amt,p.ratio,p.divide_amt,p.coupon_amount_amt,p.actual_amount")
  445. ->where($where)
  446. ->select();
  447. $param = input('request.'); //分页带条件
  448. $where = array();
  449. $where['p.settle_id'] = $settleId;
  450. $detPaylist = model("ChannelDivideSettleDetPay")->alias('p')
  451. ->join('cy_game g', 'p.game_id = g.id','left')
  452. ->field("p.orderid,p.username,p.create_time,p.game_id AS game_id,g.name as game_name,p.amount AS amount,p.divide_amt,p.ratio,p.serverid,p.servername,p.rolename,p.coupon_amount,p.actual_amount")
  453. ->where($where)
  454. ->order('p.create_time desc')
  455. ->paginate(10,false,array('query' => $param));
  456. // 获取分页显示的HTML
  457. $page = $detPaylist->render();
  458. $this->assign('settleInfo',$settleInfo);
  459. $this->assign('settleDetInfo',$settleDetInfo);
  460. $this->assign('detPaylist',$detPaylist);
  461. $this->assign('page', $page);
  462. return $this->fetch('detail');
  463. }
  464. /**
  465. * 二级审核详情
  466. */
  467. public function secondDetail()
  468. {
  469. $this->detail();
  470. return $this->fetch('detail');
  471. }
  472. /**
  473. * 未结算数据
  474. */
  475. public function unsettle()
  476. {
  477. $settle_type = input('settle_type',0,'intval');
  478. $begin_time = input('start','','trim');
  479. $end_time = input('end','','trim');
  480. $channel_id = input('channel_id',0,'intval');
  481. //渠道名
  482. if($channel_id){
  483. $ShowDataList = 1;
  484. $where = [];
  485. $where['p.status'] = 1;
  486. $where['p.settle_id'] = array('eq',0);
  487. $channelIds = get_child_channel_arr($channel_id);
  488. array_push($channelIds,$channel_id);
  489. $where['p.channel_id'] = ['in',$channelIds];
  490. //区服类型
  491. if(input('request.settle_type')!=''){
  492. $where['g.game_kind'] = $settle_type;
  493. }
  494. //申请开始时间和结束时间不为空时
  495. if ($begin_time != '' && $end_time != '') {
  496. $where['p.create_time'] = [
  497. ['>=', strtotime($begin_time)],
  498. ['<=', strtotime($end_time . ' 23:59:59')],
  499. ];
  500. } //开始时间不为空时
  501. elseif ($begin_time != '') {
  502. $where['p.create_time'] = ['>=', strtotime($begin_time)];
  503. } //结束时间不为空时
  504. elseif ($end_time != '') {
  505. $where['p.create_time'] = ['<=', strtotime($end_time . ' 23:59:59')];
  506. }
  507. $where['g.id'] = ['in', model('game')->getTakingGame($channel_id)];
  508. $GameChannelData = Db::table('cy_pay')->alias('p')
  509. ->join('cy_game g', 'p.gameid = g.id','inner')
  510. ->join('nw_game_channel_divide d','p.gameid = d.game_id and d.channel_id='.$channel_id,'left')
  511. ->field("p.gameid AS game_id,g.name as game_name,g.channel_split_ratio,count(*) as pay_cnt,SUM(p.amount) AS pay_amt,d.id as ratio_id,d.ratio,SUM(p.real_amount) AS pay_real_amt,SUM(p.real_ptb) AS pay_real_ptb,SUM(p.coupon_amount) as coupon_amount_amt")
  512. ->where($where)
  513. ->group('p.gameid')
  514. ->select();
  515. $retData = array();
  516. $total_amt = $divide_amt = $total_cnt = $total_coupon_amount_amt = 0;
  517. foreach ( $GameChannelData as &$det ) {
  518. if(intval($det['ratio_id'])){
  519. $ratio_id = $det['ratio_id'];
  520. $ratio = floatval($det['ratio']);
  521. }
  522. else{
  523. $ratio_id = 0;
  524. $ratio = floatval($det['channel_split_ratio']);
  525. }
  526. if(!$ratio){
  527. $this->jsonResult('', 0, '您尚有游戏未配置分成比例,请先联系平台设置');
  528. }
  529. else{
  530. $det['ratio_id'] = $ratio_id;
  531. $det['ratio'] = $ratio;
  532. $total_cnt += floatval($det['pay_cnt']);
  533. $total_amt += floatval($det['pay_amt']);
  534. $total_coupon_amount_amt += floatval($det['coupon_amount_amt']);
  535. $divide_amt += floatval(intval(($det['pay_amt']-$det['coupon_amount_amt']) * $det['ratio']) / 100);
  536. $det['divide_amt'] = floatval(intval(($det['pay_amt']-$det['coupon_amount_amt']) * $det['ratio']) / 100);
  537. }
  538. }
  539. $settle = array();
  540. $settle['total_amount'] = $total_amt;
  541. $settle['divide_amount'] = $divide_amt;
  542. $settle['total_cnt'] = $total_cnt;
  543. $settle['total_coupon_amount_amt'] = $total_coupon_amount_amt;
  544. $param = input('request.'); //分页带条件
  545. $detPaylist = Db::table('cy_pay')->alias('p')
  546. ->join('cy_game g', 'p.gameid = g.id','inner')
  547. ->join('nw_game_channel_divide d','p.gameid = d.game_id and d.channel_id='.$channel_id,'left')
  548. ->field("p.orderid AS orderid,p.gameid AS game_id,g.name as game_name,p.amount AS amount,round((p.amount-p.coupon_amount)*(case when d.id then d.ratio else g.channel_split_ratio end)/100,2) AS divide_amt,case when d.id then d.id else '0' end as ratio_id,case when d.id then d.ratio else g.channel_split_ratio end as ratio,p.real_amount AS real_amount,p.real_ptb AS real_ptb,p.serverid,p.servername,p.rolename,p.userid,p.username,p.create_time,p.coupon_amount")
  549. ->where($where)
  550. ->order("p.id desc")
  551. ->paginate(10,false,array('query' => $param));
  552. // var_dump($detPaylist);
  553. // 获取分页显示的HTML
  554. $page = $detPaylist->render();
  555. $this->assign('settle', $settle);
  556. $this->assign('settleDet', $GameChannelData);
  557. $this->assign('detPaylist', $detPaylist);
  558. $this->assign('page', $page);
  559. }
  560. else{
  561. $ShowDataList = 0;
  562. }
  563. $channelModel = new Channel;
  564. $channelList = $channelModel->getAllByCondition('id,name',['level'=>1,'flag'=>3],'name asc');
  565. $this->assign('channel_list',$channelList);
  566. $this->assign('start', $begin_time);
  567. $this->assign('end', $end_time);
  568. $this->assign('ShowDataList', $ShowDataList);
  569. return $this->fetch();
  570. }
  571. public function downSettleMonthData(){
  572. if(input('download')==2){
  573. $month = date('Y-m',mktime(0,0,0,date('m'),01)-1);
  574. $where = array();
  575. $where['a.month'] = $month;
  576. $list = Db::table('nw_channel_month_data')->alias('a')
  577. ->join('nw_channel c','a.channel_id=c.id','left')
  578. ->field('a.id,a.month,a.channel_id,a.unsettle_amt,a.settle_apply_amt,a.unwithdraw_amt,a.withdraw_apply_amt,(a.unsettle_amt+a.settle_apply_amt+a.unwithdraw_amt+a.withdraw_apply_amt) as total_amt,c.name as channel_name,a.create_time,a.update_time')
  579. ->where($where)
  580. ->order('a.create_time desc')
  581. ->select();
  582. $title = "会长上月末数据-".date('YmdHis');
  583. if(!$list){
  584. $this->error('暂无数据');
  585. }
  586. $this->downloadexls($list,$title,'settleMonthData');
  587. exit();
  588. }
  589. else{
  590. $this->error('参数错误!');
  591. }
  592. }
  593. /**
  594. * 外放推广结算处理
  595. */
  596. public function doSettle()
  597. {
  598. if ($this->request->isPost()) {
  599. $channel_id = input('channel_id',0,'intval'); //流水
  600. $total_amount = input('total_amount',0,'floatval'); //流水
  601. $divide_amount = input('divide_amount',0,'floatval'); //分成金额
  602. $total_cnt = input('total_cnt',0,'intval'); //结算订单笔数
  603. $begin_date = input('begin_date','','trim'); //开始时间
  604. $end_date = input('end_date','','trim'); //开始时间
  605. $settle_type = input('settle_type','','intval'); //区服类型
  606. $remark = '外放推广手动结算处理'; //备注
  607. if(!$channel_id){
  608. $this->jsonResult('', 0, '请选择要结算的公会账号');
  609. }
  610. if(!in_array($settle_type,[1,2])){
  611. $this->jsonResult('', 0, '请选择区服类型');
  612. }
  613. if(!$begin_date || !$end_date){
  614. $this->jsonResult('', 0, '请选择结算周期');
  615. }
  616. if(!$total_amount || !$divide_amount || !$total_cnt){
  617. $this->jsonResult('', 0, '没有可结算单的订单');
  618. }
  619. if($settle_type==1){
  620. $orderid = 'ZFS'.makeOrderid();
  621. }
  622. else if($settle_type==2){
  623. $orderid = 'HFS'.makeOrderid();
  624. }
  625. else{
  626. $this->jsonResult('', 0, '区服类型异常,请选择正确的区服类型!!');
  627. }
  628. $channelInfo = model("Channel")->field("id,name,parent_id,level,cps_settle_period,mcps_settle_period,status")->where(['id'=>$channel_id,'level'=>1])->find();
  629. if(empty($channelInfo)){
  630. $this->jsonResult('', 0, '公会账号异常,请选择正确的公会账号');
  631. }
  632. //只能结算外放的公会
  633. $parentChannelInfo = model("Channel")->field("id,name,level,cps_settle_period,mcps_settle_period,status,channel_tg_type")->where(['id'=>$channelInfo['parent_id'],'level'=>0])->find();
  634. if(empty($parentChannelInfo)){
  635. $this->jsonResult('', 0, '公会所属商务账号异常');
  636. }
  637. else if($parentChannelInfo['channel_tg_type']<>1){
  638. $this->jsonResult('', 0, '非外放商务下公会不能使用该功能');
  639. }
  640. /*
  641. $channelInfoApply = model("ChannelInfo")->field("id,channel_id,real_name,apply_status,type")->where(['channel_id'=>$parentChannelInfo['id'],'apply_status'=>1])->find();
  642. if(empty($channelInfoApply)){
  643. $this->jsonResult('', 0, '该公会所属商务的身份尚未认证通过,不能进行结算');
  644. }
  645. */
  646. $fromTime = strtotime($begin_date);
  647. $toTime = strtotime($end_date)+60*60*24-1;
  648. $where = array();
  649. $where['p.status'] = 1;
  650. $where['p.create_time'] = [
  651. ['>=', $fromTime],
  652. ['<=', $toTime],
  653. ];
  654. //所有下级渠道(包括自己)
  655. $channelIds = get_child_channel_arr($channel_id);
  656. array_push($channelIds,$channel_id);
  657. $where['p.channel_id'] = ['in',$channelIds];
  658. $where['p.settle_id'] = array('eq',0);
  659. // var_dump($where);
  660. $GameChannelData = Db::table('cy_pay')->alias('p')
  661. ->join('cy_game g', 'p.gameid = g.id and g.game_kind='.$settle_type,'inner')
  662. ->join('nw_game_channel_divide d','p.gameid = d.game_id and d.channel_id='.$channel_id,'left')
  663. ->field("p.gameid AS game_id,g.name as game_name,g.channel_split_ratio,min(p.create_time) as begin_time,max(p.create_time) as end_time,count(*) as pay_cnt,SUM(p.amount) AS pay_amt,d.id as ratio_id,d.ratio,SUM(p.real_amount) AS pay_real_amt,SUM(p.real_ptb) AS pay_real_ptb")
  664. ->where($where)
  665. ->group('p.gameid')
  666. ->select();
  667. $retData = array();
  668. // echo Db::table('cy_pay')->getLastSql()."----sql-----------<br>";
  669. $totalAmount = $divideAmount = $totalCnt = 0;
  670. $beginTime = time();
  671. $endTime = 0;
  672. foreach ( $GameChannelData as &$det ) {
  673. if(intval($det['ratio_id'])){
  674. $ratio_id = $det['ratio_id'];
  675. $ratio = floatval($det['ratio']);
  676. }
  677. else{
  678. $ratio_id = 0;
  679. $ratio = floatval($det['channel_split_ratio']);
  680. }
  681. if(!$ratio){
  682. $this->jsonResult('', 0, '您尚有游戏未配置分成比例,请先联系平台设置');
  683. }
  684. else{
  685. $det['ratio_id'] = $ratio_id;
  686. $det['ratio'] = $ratio;
  687. $totalCnt += floatval($det['pay_cnt']);
  688. $totalAmount += floatval($det['pay_amt']);
  689. $divideAmount += floatval(intval($det['pay_amt'] * $det['ratio']) / 100);
  690. $det['divide_amt'] = floatval(intval($det['pay_amt'] * $det['ratio']) / 100);
  691. if($beginTime > $det['begin_time']){
  692. $beginTime = $det['begin_time'];
  693. }
  694. if($endTime < $det['end_time']){
  695. $endTime = $det['end_time'];
  696. }
  697. }
  698. }
  699. reset($GameChannelData);
  700. if(!$totalAmount || !$divideAmount || !$totalCnt){
  701. $this->jsonResult('', 0, '您已没有可结算的订单');
  702. }
  703. if(abs($totalAmount-$total_amount)>0.01 || $totalCnt<>$total_cnt || abs($divideAmount-$divide_amount)>0.01){
  704. $this->jsonResult('', 0, '结算数据与后台计算数据不一致,请重新核对后再提交');
  705. }
  706. //指定时间内,禁止重复下单
  707. if(!requestDuplicateCheck('channel_settle_duplicate_'.$channel_id,10)){
  708. $this->jsonResult('', 0, '结算请求过多,请于10s以后,再次进行结算操作');
  709. }
  710. $detPaylist = Db::table('cy_pay')->alias('p')
  711. ->join('cy_game g', 'p.gameid = g.id and g.game_kind='.$settle_type,'inner')
  712. ->join('nw_game_channel_divide d','p.gameid = d.game_id and d.channel_id='.$channel_id,'left')
  713. ->field("p.id as payid,p.orderid AS orderid,p.gameid AS game_id,p.userid,p.username,g.name as game_name,g.channel_split_ratio,p.channel_id,p.amount AS amount,(p.amount*(case when d.id then d.ratio else g.channel_split_ratio end)/100) AS divide_amt,case when d.id then d.id else '0' end as ratio_id,case when d.id then d.ratio else g.channel_split_ratio end as ratio,p.real_amount AS real_amount,p.real_ptb AS real_ptb,p.create_time,p.serverid,p.servername,p.rolename")
  714. ->where($where)
  715. ->select();
  716. // 启动事务
  717. Db::startTrans();
  718. try{
  719. $settleData = array();
  720. $settleData['orderid'] = $orderid;
  721. $settleData['settle_type'] = $settle_type;
  722. $settleData['channel_id'] = $channel_id;
  723. $settleData['channel_name'] = $channelInfo['name'];
  724. $settleData['total_amount'] = $totalAmount;
  725. $settleData['total_divide_amt'] = $divideAmount;
  726. $settleData['begin_time'] = $beginTime;
  727. $settleData['end_time'] = $endTime;
  728. $settleData['remark'] = $remark;
  729. $settleData['create_time'] = time();
  730. $settleData['first_audit_status'] = 1;
  731. $settleData['first_audit_time'] = time();
  732. $settleData['settle_period'] = 1;
  733. $insertSettleId = model('ChannelDivideSettle')->insertGetId($settleData);
  734. if ( !$insertSettleId) {
  735. throw new Exception("添加结算单失败");
  736. }
  737. while(list($key,$val)=@each($GameChannelData)){
  738. $detData = array();
  739. $detData['settle_id'] = $insertSettleId;
  740. $detData['divide_id'] = $val['ratio_id'];
  741. $detData['begin_time'] = $val['begin_time'];
  742. $detData['end_time'] = $val['end_time'];
  743. $detData['game_id'] = $val['game_id'];
  744. $detData['channel_id'] = $channel_id;
  745. $detData['ratio'] = $val['ratio'];
  746. $detData['pay_cnt'] = $val['pay_cnt'];
  747. $detData['pay_amt'] = floatval($val['pay_amt']);
  748. $detData['pay_real_amt'] = floatval($val['pay_real_amt']);
  749. $detData['pay_real_ptb'] = floatval($val['pay_real_ptb']);
  750. $detData['divide_amt'] = floatval($val['divide_amt']);
  751. $detData['create_time'] = time();
  752. ${'insertDet'.$val['game_id'].'ID'} = model('ChannelDivideSettleDet')->insertGetId($detData);
  753. if ( !${'insertDet'.$val['game_id'].'ID'}) {
  754. throw new Exception("添加结算单明细失败");
  755. }
  756. }
  757. $orderIds = array();
  758. while(list($key,$val)=@each($detPaylist)){
  759. $orderIds[] = $val['payid'];
  760. // echo ${'insertDet'.$val['game_id'].'ID'}."---insertDet".$val['game_id']."ID'--------<br>";
  761. $detPayData['settle_id'] = $insertSettleId;
  762. $detPayData['settle_det_id'] = ${'insertDet'.$val['game_id'].'ID'};
  763. $detPayData['orderid'] = $val['orderid'];
  764. $detPayData['game_id'] = $val['game_id'];
  765. $detPayData['channel_id'] = $val['channel_id'];
  766. $detPayData['ratio'] = $val['ratio'];
  767. $detPayData['userid'] = $val['userid'];
  768. $detPayData['username'] = $val['username'];
  769. $detPayData['amount'] = floatval($val['amount']);
  770. $detPayData['real_amount'] = floatval($val['real_amount']);
  771. $detPayData['real_ptb'] = floatval($val['real_ptb']);
  772. $detPayData['divide_amt'] = floatval($val['divide_amt']);
  773. $detPayData['serverid'] = trim($val['serverid']);
  774. $detPayData['servername'] = trim($val['servername']);
  775. $detPayData['rolename'] = trim($val['rolename']);
  776. $detPayData['create_time'] = $val['create_time'];
  777. $detPayData['add_time'] = time();
  778. // var_dump($detPayData);
  779. $insertDetPayId = model('ChannelDivideSettleDetPay')->insertGetId($detPayData);
  780. if ( !$insertDetPayId) {
  781. throw new Exception("添加结算订单明细失败");
  782. }
  783. }
  784. $updPayData = array();
  785. $updPayData['settle_channel_id'] = $channel_id;
  786. $updPayData['settle_id'] = $insertSettleId;
  787. $updPayData['settle_update_time'] = time();
  788. /*
  789. $gameids = model('Game')->where(['game_kind'=>2])->column('id');
  790. $where['p.gameid']= array('IN',$gameids);
  791. */
  792. $where['p.id']= array('IN',$orderIds);
  793. $updResult = model('Pay')->alias('p')->where($where)->update($updPayData);
  794. if ( !$updResult) {
  795. throw new Exception("更新订单为已结算失败");
  796. }
  797. $this->redis->del('channel_settle_duplicate_'.$channel_id);
  798. // 提交事务
  799. Db::commit();
  800. } catch (\Exception $e) {
  801. // 回滚事务
  802. Db::rollback();
  803. $this->jsonResult('', 0, '结算申请生成失败'.$e->getMessage());
  804. }
  805. $result['orderid'] = $orderid;
  806. $this->jsonResult($result, 20000, '结算申请生成成功');
  807. exit;
  808. }
  809. else{
  810. $this->jsonResult('', 0, '非法请求');
  811. exit;
  812. }
  813. }
  814. }