OrderController.php 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800
  1. <?php
  2. /**
  3. * 订单相关
  4. * @author x.b
  5. *
  6. */
  7. declare(strict_types=1);
  8. namespace Modules\Manage\Controllers;
  9. use App\Constants\ChangeLogConstant;
  10. use App\Constants\CommonConstant;
  11. use App\Constants\OrderConstrant;
  12. use App\Model\CoinsOrderModel;
  13. use App\Model\PaymentModel;
  14. use App\Model\VipCardModel;
  15. use App\Model\VipOrderModel;
  16. use App\Repositories\ChangeLogRepository;
  17. use App\Repositories\Criterias\ChangeLogCriteria;
  18. use App\Repositories\Criterias\OrderLimitCriteria;
  19. use App\Repositories\OrderRepository as OrderRepository;
  20. use App\Model\UserModel;
  21. use App\Model\VipOrderModel as Model;
  22. use App\Repositories\Service\CommonService;
  23. use App\Repositories\Service\QueueService;
  24. use Carbon\Carbon;
  25. use Hyperf\DbConnection\Db;
  26. use Hyperf\Validation\Contract\ValidatorFactoryInterface;
  27. use Modules\Manage\Responses\OrderChangeListResponse;
  28. class OrderController extends BaseController
  29. {
  30. // 临时-写死,急上线,后续配置为动态的
  31. public $payment_data = [
  32. 'white_shark' => '大白鲨',
  33. ];
  34. /**
  35. * 订单列表
  36. * @return mixed
  37. * @example param_json_data string:
  38. * {"handshake":"","data":{"page":1,"page_size":5,"search":{"order_sn":"","nick":"","user_id":"","user_code":"","device_type":"","status":"","pay_gate_way":"","is_admin_action":"","vip_title":"","stime":"","otime":"","stime_pay":"","otime_pay":""},"order":"created_at","order_sort":"desc"}}
  39. * @deprecated 目前,从 支付方式id 等价于 查询出支付通道! pay_gate_way
  40. */
  41. public function list()
  42. {
  43. $inputData = $this->getJsonData();
  44. $page = isset($inputData['page']) ? (int)$inputData['page'] : 1;
  45. $page_size = isset($inputData['page_size']) ? (int)$inputData['page_size'] : 20;
  46. $select = [
  47. 'vip_order.*',
  48. 'user.nick',
  49. 'user.id AS user_id',
  50. 'user.code AS user_code',
  51. 'user.device_type'
  52. ];
  53. $model = Model::query();
  54. $order_key = isset($inputData['order']) ? $inputData['order'] : 'id';
  55. $order_value = isset($inputData['order_sort']) ? $inputData['order_sort'] : 'desc';
  56. if (!$order_key) {
  57. $order_key='id'; //不要信任前端,他可能会传个空字符串过来!
  58. }
  59. if (!$order_value) {
  60. $order_value = 'desc';
  61. }
  62. // order_sn订单号,status 订单状态, pay_gate_way 支付方式ID(支付方式/支付通道), device_type设备类型,stime 订单创建时间-开始, otime 订单创建时间-结束, stime_pay 订单支付时间-开始, otime_pay 订单支付时间结束 is_admin_action 后台是否查到处理
  63. // nick 用户表-用户名,user_id 用户表-用户ID, user_code 用户表-用户邀请码,
  64. $search = isset($inputData['search']) ? $inputData['search'] : array();
  65. if ($search) {
  66. foreach ($search as $k => $v) {
  67. if (!strlen((string)$v)) {
  68. continue;
  69. }
  70. switch ($k) {
  71. case "nick": // 用户表-昵称
  72. $model->where('user.'.$k, 'like', "{$v}%");
  73. break;
  74. case "user_code": // 用户表-邀请码
  75. $model->where('user.'.$k, $v);
  76. break;
  77. case "order_sn": // 订单号
  78. $model->where('vip_order.'.$k, 'like', "{$v}%");
  79. break;
  80. case "stime": // 自定义-订单开始日期
  81. $model->where('vip_order.created_at', '>=', $v);
  82. break;
  83. case "otime": // 自定义-订单结束日期
  84. $model->where('vip_order.created_at', '<=', Carbon::parse($v)->endOfDay()->toDateTimeString());
  85. break;
  86. case "stime_pay": // 自定义-订单支付开始日期
  87. $model->where('vip_order.pay_time', '>=', $v);
  88. break;
  89. case "otime_pay": // 自定义-订单支付结束日期
  90. $model->where('vip_order.pay_time', '<=', $v);
  91. break;
  92. default:
  93. $model->where('vip_order.'.$k, $v);
  94. }
  95. }
  96. }
  97. $result = $model->select($select)
  98. ->leftJoin('user', 'vip_order.user_id', '=', 'user.id')
  99. ->orderBy((string)$order_key, (string)$order_value)
  100. ->paginate($page_size, ['*'], 'page', $page);
  101. $payment = make(OrderRepository::class)->all(['name', 'pay_code'])->keyBy('pay_code');
  102. return json_success($result);
  103. }
  104. /**
  105. * 订单列表 - 支付方式/支付通道列表(下拉选项)
  106. * @return object
  107. * @example param_json_data string nobody
  108. */
  109. public function paymentData()
  110. {
  111. //return json_success(make(OrderRepository::class)->getPaymentData());
  112. $data = [
  113. 'pay_gate_way' => [],
  114. ];
  115. $items = PaymentModel::query()->orderBy('id', 'DESC')->get();
  116. if ($items->count()) {
  117. foreach ($items as $item) {
  118. $data['pay_gate_way'][] = [
  119. 'id' => $item->id,
  120. 'name' => $item->name,
  121. ];
  122. }
  123. }
  124. // 特殊处理,兼容目前前端的对接数据
  125. // $r = $this->payment_data;
  126. // $data = array();
  127. // foreach ($r as $k => $v) {
  128. // $data[] = [
  129. // 'id' => $k,
  130. // 'name' => $v,
  131. // ];
  132. // }
  133. return json_success($data);
  134. }
  135. /**
  136. * 订单列表 - 购买内容(下拉选项)
  137. * @return object
  138. * @example param_json_data string nobody
  139. */
  140. public function vipTitleData()
  141. {
  142. $data = [];
  143. $items = VipCardModel::query()->orderBy('sort', 'DESC')->get(['id', 'title']);
  144. if ($items->count()) {
  145. foreach ($items as $item) {
  146. $data[] = [
  147. 'id' => $item->id,
  148. 'name' => $item->title,
  149. ];
  150. }
  151. }
  152. /*$select = ['vip_title'];
  153. $r = Model::query()
  154. ->select($select)
  155. ->groupBy('vip_title')
  156. ->get();
  157. $data = array();
  158. foreach ($r as $k => $v) {
  159. $data[] = [
  160. 'id' => $k,
  161. 'name' => $v->vip_title,
  162. ];
  163. }*/
  164. return json_success($data);
  165. }
  166. /**
  167. * 补单
  168. * @param ValidatorFactoryInterface $validatorFactory
  169. * @return mixed
  170. * @example param_json_data string: {"handshake":"","data":{"order_sn":"YV202002242305189073","trade_no":"xx支付单号","repair_remark":"xx补单备注"}}
  171. * 处理逻辑:vip_order 订单表标示已付款和付款日期; collections 表创建收款单记录, user表添加会员日期,
  172. * 成功之后,在mongodb中创建一个 补单记录。
  173. * 备注: 不需要去内调回调接口,不要验签!
  174. */
  175. public function again(ValidatorFactoryInterface $validatorFactory)
  176. {
  177. $inputData = $this->getJsonData();
  178. $rules = [
  179. 'order_sn' => 'required|string',
  180. 'trade_no' => 'required|string', //支付单号
  181. 'repair_remark' => 'required|string', //补单备注
  182. ];
  183. $validator = $validatorFactory->make($inputData, $rules);
  184. if ($validator->fails()) {
  185. return json_fail($validator->errors()->first());
  186. }
  187. $order_sn = $inputData['order_sn'];
  188. $trade_no = $inputData['trade_no'];
  189. $repair_remark = isset($inputData['repair_remark']) ? $inputData['repair_remark'] : '';
  190. $order_info = make(OrderRepository::class)->getOrderInfo($order_sn);
  191. if (!$order_info) {
  192. return json_fail('订单不存在');
  193. }
  194. // if ($order_info['pay_time']) {
  195. // return json_fail('此订单已处理,请勿重复操作!');
  196. // }
  197. if ($order_info['status'] == 1) {
  198. return json_fail('此订单已处理,请勿重复操作!!');
  199. }
  200. $user_info = UserModel::query()
  201. ->where('id', $order_info['user_id'])
  202. ->first();
  203. //处理补单
  204. if (!make(OrderRepository::class)->again($order_sn, $trade_no, $repair_remark)) {
  205. return json_fail('处理失败');
  206. }
  207. // 创建管理员日志
  208. $oldItem = clone $user_info;
  209. $newitem = UserModel::query()
  210. ->where('id', $order_info['user_id'])
  211. ->first();
  212. $oldItem2 = clone $order_info;
  213. $newitem2 = make(OrderRepository::class)->getOrderInfo($order_sn);
  214. //返佣计算 异步
  215. make(QueueService::class)->rebateTwoUserJob([ 'user_id' =>$newitem2->user_code, 'amount' => $newitem2->real_amount]);
  216. $logSubject = "补单,用户id:{$user_info['id']},来源订单号:{$order_sn}";
  217. $logSvalue = $oldItem->id;
  218. $logDbData = [
  219. 'after_items' => [
  220. $newitem->toArray(),
  221. $newitem2->toArray(),
  222. ],
  223. 'before_items' => [
  224. $oldItem->toArray(),
  225. $oldItem2->toArray(),
  226. ],
  227. ];
  228. $this->log($logSubject, $logSvalue, $logDbData);
  229. return json_success('', '处理成功');
  230. }
  231. /**
  232. * 每日充值(统计列表) ( v1 版本, 后续项目空闲 v2优化-会单独新设一个表,然后服务器定时任务去查一次,再往新表存下统计数据 )
  233. * @param ValidatorFactoryInterface $validatorFactory
  234. * @return mixed
  235. * @example param_json_data string:
  236. * {"handshake":"","data":{"search":{"pay_gate_way":"","stime":"","otime":""}}}
  237. *
  238. * {"handshake":"","data":{"search":{"pay_gate_way":"","stime":"2020-02-01","otime":"2020-02-28"}}}
  239. *
  240. * {"handshake":"","data":{"search":{"pay_gate_way":"","stime":"2020-02-01","otime":"2020-02-28"}}}
  241. */
  242. public function dayList()
  243. {
  244. $inputData = $this->getJsonData();
  245. $search = isset($inputData['search']) ? $inputData['search'] : array();
  246. $stime = isset($search['stime']) ? $search['stime'] : ''; // 传参如: 2020-2-20
  247. if (!$stime) {
  248. //$stime = date('Y-m-d'); // 今天日期
  249. $stime = date('Y-m-1'); // 此月1号
  250. }
  251. $otime = isset($search['otime']) ? Carbon::parse($search['otime'])->endOfDay()->toDateTimeString() : ''; // 传参如: 2020-2-22
  252. if (!$otime) {
  253. $otime = date('Y-m-d', strtotime("+1 day")); //明天日期
  254. }
  255. $pay_gate_way = isset($search['pay_gate_way']) ? $search['pay_gate_way'] : '';
  256. // 查询所有数据统计
  257. if ($pay_gate_way) {
  258. $sql = "SELECT LEFT (created_at,10) AS created_date,count(*) AS order_all,sum(order_amount) AS order_amount_all,sum(real_amount) AS real_amount_all,pay_gate_way FROM vip_order WHERE pay_gate_way=? AND created_at>=? AND created_at<=? GROUP BY pay_gate_way,created_date ORDER BY created_date DESC,pay_gate_way ASC";
  259. $order_data_all = Db::select($sql, [$pay_gate_way, $stime, $otime]);
  260. } else {
  261. $sql = "SELECT LEFT (created_at,10) AS created_date,count(*) AS order_all,sum(order_amount) AS order_amount_all,sum(real_amount) AS real_amount_all,pay_gate_way FROM vip_order WHERE created_at>=? AND created_at<=? GROUP BY pay_gate_way,created_date ORDER BY created_date DESC,pay_gate_way ASC";
  262. $order_data_all = Db::select($sql, [$stime, $otime]);
  263. }
  264. if (!$order_data_all) {
  265. $order_data_all=array();
  266. } else {
  267. $order_data_all = json_decode(json_encode($order_data_all), true);
  268. }
  269. // 仅查支付成功的数据统计
  270. if ($pay_gate_way) {
  271. $sql = "SELECT LEFT (created_at,10) AS created_date,count(*) AS order_all,sum(order_amount) AS order_amount_all,sum(real_amount) AS real_amount_all,pay_gate_way FROM vip_order WHERE pay_gate_way=? AND status=1 AND created_at>=? AND created_at<=? GROUP BY pay_gate_way,created_date ORDER BY created_date DESC,pay_gate_way ASC";
  272. $order_data_pay = Db::select($sql, [$pay_gate_way, $stime, $otime]);
  273. } else {
  274. $sql = "SELECT LEFT (created_at,10) AS created_date,count(*) AS order_all,sum(order_amount) AS order_amount_all,sum(real_amount) AS real_amount_all,pay_gate_way FROM vip_order WHERE status=1 AND created_at>=? AND created_at<=? GROUP BY pay_gate_way,created_date ORDER BY created_date DESC,pay_gate_way ASC";
  275. $order_data_pay = Db::select($sql, [$stime, $otime]);
  276. }
  277. if (!$order_data_pay) {
  278. $order_data_pay=array();
  279. } else {
  280. $order_data_pay = json_decode(json_encode($order_data_pay), true);
  281. }
  282. // 开始业务处理和统计 ( 当前是v1版(不提供分页,便于统计),后续 优化时 由 服务器做个定时任务,比如早上1点,定时去查询统计昨日的数据后 往 指定的新表 记录统计后的数据;后台在直接从新表中原样展示数据(可提供分页) )
  283. $order_data_pay_action = array();
  284. if ($order_data_pay) {
  285. foreach ($order_data_pay as $v) {
  286. $order_data_pay_action[$v['pay_gate_way']][] = $v;
  287. }
  288. }
  289. // 组装数据: (日期,支付方式ID,支付通道,创建订单数,成功订单量,订单金额,成功金额,成功率% )
  290. $data = array();
  291. foreach ($order_data_all as $v) {
  292. $action_order_data_pay_info = self::actionOrderDataPayInfo($v['pay_gate_way'], $v['created_date'], $order_data_pay_action);
  293. $order_all_pay = isset($action_order_data_pay_info['order_all']) ? $action_order_data_pay_info['order_all'] : 0;
  294. $real_amount_all_pay = isset($action_order_data_pay_info['real_amount_all']) ? $action_order_data_pay_info['real_amount_all'] : 0;
  295. $conversion = round((round($order_all_pay / $v['order_all'], 4) * 100), 2);
  296. $data[] = array(
  297. 'created_date' => $v['created_date'],
  298. 'pay_gate_way' => $v['pay_gate_way'],
  299. 'order_all' => $v['order_all'], //创建订单数
  300. 'order_all_pay' => $order_all_pay, //成功订单量
  301. 'real_amount_all' => $v['real_amount_all'], //订单金额(以实付金额为准,咨询过 田七 ), order_amount_all 为订单原始金额
  302. 'real_amount_all_pay' => $real_amount_all_pay, //真实支付的金额(以实付金额为准,咨询过 田七 )-用户已付款的
  303. 'conversion' => $conversion, //转化率:(成功订单量 / 创建订单数)%
  304. );
  305. }
  306. return json_success($data);
  307. }
  308. /**
  309. * @param $pay_gate_way
  310. * @param $created_date
  311. * @param $order_data_pay_action
  312. * @return array
  313. */
  314. protected function actionOrderDataPayInfo($pay_gate_way = '', $created_date = '', $order_data_pay_action = array())
  315. {
  316. if (isset($order_data_pay_action[$pay_gate_way])) {
  317. foreach ($order_data_pay_action[$pay_gate_way] as $kk => $vv) {
  318. if ($vv['created_date'] == $created_date) {
  319. return $vv;
  320. break;
  321. }
  322. }
  323. return array();
  324. } else {
  325. return array();
  326. }
  327. }
  328. /**
  329. * 每日用户成功率(统计列表) ( v1 版本, 后续项目空闲 v2优化-会单独新设一个表,然后服务器定时任务去查一次,再往新表存下统计数据 )
  330. * @param ValidatorFactoryInterface $validatorFactory
  331. * @return mixed
  332. * @example param_json_data string:
  333. * {"handshake":"","data":{"search":{"stime":"","otime":""}}}
  334. *
  335. * {"handshake":"","data":{"search":{"stime":"2020-02-01","otime":"2020-02-28"}}}
  336. *
  337. * {"handshake":"","data":{"search":{"stime":"2020-02-01","otime":"2020-02-28"}}}
  338. */
  339. public function dayListUser()
  340. {
  341. set_time_limit(0);
  342. $inputData = $this->getJsonData();
  343. $search = isset($inputData['search']) ? $inputData['search'] : array();
  344. $stime = isset($search['stime']) ? $search['stime'] : ''; // 传参如: 2020-2-20
  345. if (!$stime) {
  346. $stime = date('Y-m-1'); // 此月1号
  347. }
  348. $otime = isset($search['otime']) ? Carbon::parse($search['otime'])->endOfDay()->toDateTimeString() : ''; // 传参如: 2020-2-22
  349. if (!$otime) {
  350. $otime = Carbon::tomorrow()->endOfDay()->toDateTimeString(); //明天日期
  351. }
  352. $select = [
  353. Db::raw('LEFT (created_at,10) AS created_date'), //创建时间,转xxxx-xx-xx
  354. 'order_sn',
  355. 'user_id', // 用户id
  356. 'order_amount', // 订单金额
  357. 'real_amount', // 实付金额
  358. 'status', // 0待支付1已支付2已取消
  359. 'pay_time', // 付款时间
  360. 'trade_no', // 支付单号
  361. ];
  362. // 查询所有数据
  363. $result = VipOrderModel::query()
  364. ->select($select)
  365. ->where('created_at', '>=', $stime)
  366. ->where('created_at', '<=', $otime)
  367. ->orderByRaw('created_date desc')
  368. ->get()
  369. ->toArray();
  370. // 业务处理统计开始: $data_default 为容器变量,勿赋值,切记!
  371. $data_default = [
  372. 'created_date' => '', // 2020-02-21
  373. 'order_all' => 0, // 100 创建订单数
  374. 'order_all_pay' => 0, // 50 支付订单数
  375. 'user_all' => 0, // 30 下单用户量
  376. 'user_all_pay' => 0, // 10 支付用户量
  377. 'amount_all' => 0, // 订单金额(以实付金额为准,咨询过 田七 ), order_amount_all 为订单原始金额
  378. 'amount_all_pay' => 0, // 真实支付的金额(以实付金额为准,咨询过 田七 )-用户已付款的
  379. 'user_all_uid_data' => [], // 用户ID集合 - 便于统计用户量
  380. 'user_all_pay_uid_data' => [], // 付款的用户ID集合 - 便于统计用户量
  381. 'real_order' => 0, // 订单成功率 = 支付订单/创建订单 (单位%)
  382. 'real_user' => 0, // 用户成功率 = 支付用户/下单用户 (单位%)
  383. 'real_other' => 0, // 支付订单数/下单用户量 (单位个,保留小数点2位)
  384. ];
  385. $data = [];
  386. if (!$result) {
  387. return json_success($data);
  388. }
  389. $_now_created_date = '';
  390. $k_max = count($result) - 1; // 下标
  391. foreach ($result as $k => $v) {
  392. if (!$_now_created_date) { // 初始
  393. $_now_created_date = $v['created_date'];
  394. $i = 0;
  395. $data[$i] = $data_default;
  396. $data[$i]['created_date'] = $_now_created_date;
  397. }
  398. if ($_now_created_date != $v['created_date']) {
  399. $_now_created_date = $v['created_date']; //第2日时
  400. $y = $i;
  401. $i++;
  402. $data[$i] = $data_default;
  403. $data[$i]['created_date'] = $_now_created_date;
  404. // 计算各成功率(上一天数据)
  405. $data[$y] = self::actionReal($data[$y]);
  406. }
  407. $data[$i]['order_all']++;
  408. $data[$i]['amount_all'] += $v['real_amount'];
  409. if (!in_array($v['user_id'], $data[$i]['user_all_uid_data'])) {
  410. $data[$i]['user_all_uid_data'][] = $v['user_id']; //同个ID用户仅算1个用户
  411. }
  412. if ($v['status']==1) { // 付款成功的
  413. $data[$i]['order_all_pay']++;
  414. $data[$i]['amount_all_pay'] += $v['real_amount'];
  415. if (!in_array($v['user_id'], $data[$i]['user_all_pay_uid_data'])) {
  416. $data[$i]['user_all_pay_uid_data'][] = $v['user_id']; //同个ID用户仅算1个用户
  417. }
  418. }
  419. //处理特殊情况-最后条数据时
  420. if ($k==$k_max) {
  421. $y = $i;
  422. $data[$y] = self::actionReal($data[$y]);
  423. }
  424. }
  425. return json_success($data);
  426. }
  427. /**
  428. * 内用 - 业务计算各种成功率 ( 已封装好,勿动 )
  429. * @author x.b
  430. * @example self::dayListUser()方法在内调这里,业务统计处理
  431. */
  432. private function actionReal($data = array())
  433. {
  434. if (!$data) {
  435. return $data;
  436. }
  437. $data['user_all'] = count($data['user_all_uid_data']);
  438. $data['user_all_pay'] = count($data['user_all_pay_uid_data']);
  439. $data['real_order'] = round((round($data['order_all_pay'] / $data['order_all'], 4) * 100), 2);
  440. $data['real_user'] = round((round($data['user_all_pay'] / $data['user_all'], 4) * 100), 2);
  441. $data['real_other'] = round($data['order_all_pay'] / $data['user_all'], 2); // 单位:个,表示平均1个人实付多少单
  442. // 测试OK-清除业务用户ID集合,此字段不需要返回给H5
  443. unset($data['user_all_uid_data']);
  444. unset($data['user_all_pay_uid_data']);
  445. return $data;
  446. }
  447. /**
  448. * 用户查单列表 ( 返回结构 与 订单列表 一致, 唯一区别: 这里是强制过滤用户已上传支付凭证的)
  449. * @param ValidatorFactoryInterface $validatorFactory
  450. * @return mixed
  451. * @example param_json_data string:
  452. * {"handshake":"","data":{"page":1,"page_size":5,"search":{"order_sn":"","nick":"","user_id":"","user_code":"","device_type":"","status":"","pay_gate_way":"","is_admin_action":"","stime":"","otime":"","stime_pay":"","otime_pay":""},"order":"created_at","order_sort":"desc"}}
  453. * @deprecated 目前,从 支付方式id 等价于 查询出支付通道! pay_gate_way
  454. */
  455. public function userOrderList(ValidatorFactoryInterface $validatorFactory)
  456. {
  457. $inputData = $this->getJsonData();
  458. $page = isset($inputData['page']) ? (int)$inputData['page'] : 1;
  459. $page_size = isset($inputData['page_size']) ? (int)$inputData['page_size'] : 20;
  460. $select = [
  461. 'vip_order.*',
  462. 'user.nick',
  463. 'user.id AS user_id',
  464. 'user.code AS user_code',
  465. 'user.device_type'
  466. ];
  467. $model = Model::query();
  468. $order_key = isset($inputData['order']) ? $inputData['order'] : 'id';
  469. $order_value = isset($inputData['order_sort']) ? $inputData['order_sort'] : 'desc';
  470. if (!$order_key) {
  471. $order_key='id'; //不要信任前端,他可能会传个空字符串过来!
  472. }
  473. if (!$order_value) {
  474. $order_value = 'desc';
  475. }
  476. // order_sn订单号,status 订单状态, pay_gate_way (支付方式/支付通道), stime 订单创建时间-开始, otime 订单创建时间-结束, stime_pay 订单支付时间-开始, otime_pay 订单支付时间结束 is_admin_action 后台是否查到处理
  477. // nick 用户表-用户名,user_id 用户表-用户ID, user_code 用户表-用户邀请码,
  478. $search = isset($inputData['search']) ? $inputData['search'] : array();
  479. if ($search) {
  480. foreach ($search as $k => $v) {
  481. if (!strlen((string)$v)) {
  482. continue;
  483. }
  484. $operator = '=';
  485. if ($k == 'user_channel_id' && $v == 'official') {
  486. $v = '';
  487. }
  488. switch ($k) {
  489. case "nick": // 用户表-用户名
  490. case "user_code": // 用户表-用户邀请码
  491. $model->where('user.'.$k, 'like', "{$v}%");
  492. break;
  493. case "user_id": // 用户表-用户ID
  494. $model->where('user.id', 'like', "{$v}%");
  495. break;
  496. case "stime": // 自定义-订单开始日期
  497. $model->where('vip_card.created_at', '>=', $v);
  498. break;
  499. case "otime": // 自定义-订单结束日期
  500. $model->where('vip_card.created_at', '<=', Carbon::parse($v)->endOfDay()->toDateTimeString());
  501. break;
  502. case "stime_pay": // 自定义-订单支付开始日期
  503. $model->where('vip_card.pay_time', '>=', $v);
  504. break;
  505. case "otime_pay": // 自定义-订单支付结束日期
  506. $model->where('vip_card.pay_time', '<=', $v);
  507. break;
  508. default:
  509. $model->where('vip_order.'.$k, $operator, $v);
  510. }
  511. }
  512. }
  513. $model->where('vip_order.is_user_proof', '1'); // 强制过滤,用户已经上传支付凭证的数据
  514. $result = $model->select($select)
  515. ->leftJoin('user', 'vip_order.user_id', '=', 'user.id')
  516. ->orderBy((string)$order_key, (string)$order_value)
  517. ->paginate(
  518. $page_size,
  519. ['*'],
  520. 'page',
  521. $page
  522. );
  523. //处理图片路径
  524. foreach ($result as $v) {
  525. $payproof_imgs_lists = array();
  526. $img = explode(',', $v->payproof_imgs);
  527. $payproof_imgs_lists = $img;
  528. // foreach ($img as $i) {
  529. // $payproof_imgs_lists[] = make(CommonService::class)->getImageUrl($i, true);
  530. // }
  531. $v->payproof_imgs_list = $payproof_imgs_lists;
  532. $v->pay_type = OrderConstrant::$messages[$v->pay_type];
  533. $v->pay_gate_way = $v->pay_gate_way;
  534. }
  535. return json_success($result);
  536. }
  537. /**
  538. * 用户查单列表-标记为 已查单
  539. * @param ValidatorFactoryInterface $validatorFactory
  540. * @return mixed
  541. * @example param_json_data string: {"handshake":"","data":{"order_sn":"YV202002242305189073"}}
  542. */
  543. public function setUserOrder(ValidatorFactoryInterface $validatorFactory)
  544. {
  545. $inputData = $this->getJsonData();
  546. $rules = [
  547. 'order_sn' => 'required',
  548. ];
  549. $validator = $validatorFactory->make($inputData, $rules);
  550. if ($validator->fails()) {
  551. return json_fail($validator->errors()->first());
  552. }
  553. $order_sn = $inputData['order_sn'];
  554. $order_info = make(OrderRepository::class)->getOrderInfo($order_sn);
  555. if (!$order_info) {
  556. return json_fail('订单不存在');
  557. }
  558. if ($order_info['is_admin_action']) {
  559. return json_fail('此订单已标示为已查单,请勿重复操作');
  560. }
  561. $r = make(OrderRepository::class)->setAdminAction($order_sn, 1);
  562. if (!$r) {
  563. return json_fail('处理失败');
  564. }
  565. // 创建管理员日志
  566. $oldItem = clone $order_info;
  567. $newitem = make(OrderRepository::class)->getOrderInfo($order_sn);
  568. $logSubject = "将订单标记为已查单,订单号为:{$order_sn}";
  569. $logSvalue = $oldItem->id;
  570. $logDbData = [
  571. 'after_items' => [
  572. $newitem->toArray(),
  573. ],
  574. 'before_items' => [
  575. $oldItem->toArray(),
  576. ],
  577. ];
  578. $this->log($logSubject, $logSvalue, $logDbData);
  579. return json_success('', '处理成功');
  580. }
  581. /**
  582. * 支付金币
  583. * @param ValidatorFactoryInterface $validatorFactory
  584. */
  585. public function coinsOrder(ValidatorFactoryInterface $validatorFactory)
  586. {
  587. $inputData = $this->getJsonData();
  588. $rules = [
  589. 'page' => 'nullable|integer',
  590. 'page_size' => 'nullable|integer',
  591. 'order_sn' => 'nullable',
  592. 'user_uid' => 'nullable',
  593. 'status' => 'nullable|integer',
  594. 'stime' => 'nullable',
  595. 'otime' => 'nullable',
  596. 'otime_pay' => 'nullable',
  597. 'stime_pay' => 'nullable',
  598. ];
  599. $validator = $validatorFactory->make($inputData, $rules);
  600. if ($validator->fails()) {
  601. return json_fail($validator->errors()->first());
  602. }
  603. $result = CoinsOrderModel::query()
  604. ->orderByDesc('id')
  605. ->where(function ($q) use ($inputData){
  606. if ($inputData['order_sn']){
  607. $q->where('order_sn',$inputData['order_sn']);
  608. }
  609. if ($inputData['user_uid']){
  610. $q->where('user_code',$inputData['user_uid']);
  611. }
  612. if ($inputData['status']){
  613. $q->where('status',$inputData['status']);
  614. }
  615. if ($inputData['stime'] && $inputData['otime']){
  616. $q->whereBetween(
  617. 'created_at',
  618. [
  619. Carbon::parse($inputData['stime'])->toDateString(),
  620. Carbon::parse($inputData['otime'])->toDateString()
  621. ]
  622. );
  623. }
  624. if ($inputData['stime_pay'] && $inputData['otime_pay']){
  625. $q->whereBetween(
  626. 'pay_time',
  627. [
  628. Carbon::parse($inputData['stime_pay'])->toDateString(),
  629. Carbon::parse($inputData['otime_pay'])->toDateString()
  630. ]
  631. );
  632. }
  633. })
  634. ->paginate((int)$inputData['page_size'], ['*'], 'page', (int)$inputData['page']);
  635. return json_success($result);
  636. }
  637. /**
  638. * 金币订单补单
  639. *
  640. * @param ValidatorFactoryInterface $validatorFactory
  641. * @return mixed
  642. */
  643. public function coinsAgain(ValidatorFactoryInterface $validatorFactory)
  644. {
  645. $inputData = $this->getJsonData();
  646. $rules = [
  647. 'order_sn' => 'required|string', //支付单号
  648. 'repair_remark' => 'nullable|string', //补单备注
  649. ];
  650. $validator = $validatorFactory->make($inputData, $rules);
  651. if ($validator->fails()) {
  652. return json_fail($validator->errors()->first());
  653. }
  654. $orderInfo = make(OrderRepository::class)->getCoinsOrderInfo($inputData['order_sn']);
  655. if (empty($orderInfo)) {
  656. return json_fail('订单不存在');
  657. }
  658. if ($orderInfo['status'] == 1) {
  659. return json_fail('此订单已处理,请勿重复操作!');
  660. }
  661. $res = make(OrderRepository::class)->coinsAgain($inputData['order_sn'], $inputData['repair_remark'], $orderInfo['user_id'], $orderInfo['coins']);
  662. if (!$res) {
  663. return json_fail('补单失败');
  664. }
  665. $logSubject = "给用户{$orderInfo['user_id']}加金币" . $orderInfo['coins'];
  666. $logSvalue = $orderInfo['user_id'];
  667. $logDbData = [
  668. 'after_items' => [
  669. ],
  670. 'before_items' => [
  671. ],
  672. ];
  673. $this->log($logSubject, $logSvalue, $logDbData);
  674. return json_success('', '操作成功');
  675. }
  676. /**
  677. * 帐变列表
  678. *
  679. * @param ValidatorFactoryInterface $validatorFactory
  680. * @return mixed|OrderChangeListResponse
  681. */
  682. public function changeList(ValidatorFactoryInterface $validatorFactory)
  683. {
  684. $inputData = $this->getJsonData();
  685. $rules = [
  686. 'page' => 'required|integer',
  687. 'page_size' => 'required|integer',
  688. 'uid' => 'nullable|string',
  689. 'username' => 'nullable|string',
  690. 'user_uid' => 'nullable|string',
  691. 'type' => 'nullable|integer',
  692. 'way' => 'nullable|integer',
  693. ];
  694. $validator = $validatorFactory->make($inputData, $rules);
  695. if ($validator->fails()) {
  696. // 如果有错误(可能是多个信息),这里只取第一个错误信息返回.
  697. return json_fail($validator->errors()->first());
  698. }
  699. $orders = [
  700. ['created_at', 'DESC'],
  701. ];
  702. $pageSize = $inputData['page_size'] ?? CommonConstant::PAGE_SIZE;
  703. if ($pageSize > 500) {
  704. $pageSize = CommonConstant::PAGE_SIZE;
  705. }
  706. $page = format_page($inputData['page']);
  707. $res = make(ChangeLogRepository::class)->pushCriteria(new ChangeLogCriteria($inputData))->pushCriteria(new OrderLimitCriteria($orders))->paginate($pageSize, ['*'], $page);
  708. return new OrderChangeListResponse($res);
  709. }
  710. }