RemitOrder.php 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  1. <?php
  2. namespace backend\models;
  3. use common\helpers\Utils;
  4. use Yii;
  5. use yii\helpers\ArrayHelper;
  6. use yii\redis\Connection;
  7. /**
  8. * This is the model class for table "crm_remit_order".
  9. *
  10. * @property integer $id
  11. * @property integer $remit_no
  12. * @property integer $batch_no
  13. * @property integer $biz_type
  14. * @property integer $biz_no
  15. * @property integer $pay_type
  16. * @property string $payee_name
  17. * @property string $amount
  18. * @property string $bank_name
  19. * @property string $bank_branch
  20. * @property string $bank_card_no
  21. * @property string $bank_province
  22. * @property string $bank_city
  23. * @property string $bank_code
  24. * @property string $bank_branch_code
  25. * @property integer $is_business
  26. * @property integer $audit_status
  27. * @property integer $audit_admin_id
  28. * @property string $audit_name
  29. * @property string $audit_reason
  30. * @property integer $audit_time
  31. * @property integer $reaudit_admin_id
  32. * @property string $reaudit_name
  33. * @property string $reaudit_reason
  34. * @property integer $reaudit_time
  35. * @property integer $pay_status
  36. * @property integer $pay_time
  37. * @property integer $complete_time
  38. * @property string $out_no
  39. * @property integer $out_no_crc32
  40. * @property string $ret_code
  41. * @property string $res_code
  42. * @property string $ret_msg
  43. * @property string $sign
  44. * @property string $memo
  45. * @property integer $create_time
  46. * @property string $last_modified
  47. */
  48. class RemitOrder extends \yii\db\ActiveRecord
  49. {
  50. const STATUS_AUDIT_INIT = 0; // 未审核
  51. const STATUS_AUDIT_SUCCESS = 1; // 初审通过
  52. const STATUS_REAUDIT_SUCCESS = 2; // 复审通过
  53. const STATUS_AUDIT_FAIL = 3; // 初审失败
  54. const STATUS_REAUDIT_FAIL = 4; // 复审失败
  55. const STATUS_PAY_INIT = 0; // 未打款
  56. const STATUS_PAY_SUCCESS = 1; // 打款成功
  57. const STATUS_PAY_FAIL = 2; // 打款失败
  58. const STATUS_PAY_INNER_PROCESS = 3; // 内部打款中
  59. const STATUS_PAY_OUTER_PROCESS = 4; // 外部打款中
  60. const STATUS_PAY_EXCEPTION = 5; // 打款异常
  61. /**
  62. * 状态值跟文字的映射关系
  63. * @var array
  64. */
  65. public static $statusTextMap = [
  66. // 打款状态
  67. 'pay_status' => [
  68. self::STATUS_PAY_INIT => '未打款',
  69. self::STATUS_PAY_SUCCESS => '打款成功',
  70. self::STATUS_PAY_FAIL => '打款失败',
  71. self::STATUS_PAY_INNER_PROCESS => '打款中', // 内部打款中
  72. self::STATUS_PAY_OUTER_PROCESS => '打款中', // 外部打款中
  73. self::STATUS_PAY_EXCEPTION => '打款异常',
  74. ],
  75. ];
  76. /**
  77. * 打款若干天后才可以更新状态为成功或失败
  78. * @var int
  79. */
  80. public $daysAfterPayTime = 1;
  81. /**
  82. * @inheritdoc
  83. */
  84. public static function tableName()
  85. {
  86. return 'crm_remit_order';
  87. }
  88. /**
  89. * @return \yii\db\Connection the database connection used by this AR class.
  90. */
  91. public static function getDb()
  92. {
  93. return Yii::$app->get('dbXcrm');
  94. }
  95. /**
  96. * @inheritdoc
  97. */
  98. public function rules()
  99. {
  100. return [
  101. [['remit_no', 'batch_no', 'biz_no', 'pay_type', 'payee_name', 'amount', 'bank_name', 'bank_card_no', 'create_time'], 'required'],
  102. [['remit_no', 'batch_no', 'biz_type', 'biz_no', 'pay_type', 'is_business', 'audit_status', 'audit_admin_id', 'audit_time', 'reaudit_admin_id', 'reaudit_time', 'pay_status', 'pay_time', 'complete_time', 'out_no_crc32', 'create_time'], 'integer'],
  103. [['amount'], 'number', 'min' => 0.01],
  104. [['last_modified'], 'safe'],
  105. [['payee_name', 'bank_name', 'bank_branch', 'bank_card_no', 'bank_province', 'bank_city', 'bank_code', 'bank_branch_code', 'audit_name', 'reaudit_name', 'ret_code', 'res_code', 'sign'], 'string', 'max' => 32],
  106. [['audit_reason', 'reaudit_reason', 'ret_msg'], 'string', 'max' => 255],
  107. [['out_no'], 'string', 'max' => 64],
  108. [['remit_no'], 'unique'],
  109. [['memo'], 'string', 'max' => '255'],
  110. ];
  111. }
  112. /**
  113. * @inheritdoc
  114. */
  115. public function attributeLabels()
  116. {
  117. return [
  118. 'id' => 'ID',
  119. 'remit_no' => '打款单号',
  120. 'batch_no' => '打款批次号',
  121. 'biz_type' => '业务类型 1出金',
  122. 'biz_no' => '业务单号(出金单号)',
  123. 'pay_type' => '打款方式',
  124. 'payee_name' => '收款人名字',
  125. 'amount' => '打款金额',
  126. 'bank_name' => '银行名称',
  127. 'bank_branch' => '银行支行',
  128. 'bank_card_no' => '银行卡号',
  129. 'bank_province' => '开户行所在省',
  130. 'bank_city' => '开户行所在市',
  131. 'bank_code' => '银行代码',
  132. 'bank_branch_code' => '银行支行代码',
  133. 'is_business' => '是否对公 0对私 1对公',
  134. 'audit_status' => '审核状态 0未审核 1初审通过 2复审通过 3初审未通过 4复审未通过',
  135. 'audit_admin_id' => '初审人id',
  136. 'audit_name' => '初审人名字',
  137. 'audit_reason' => '初审不通过原因',
  138. 'audit_time' => '初审时间',
  139. 'reaudit_admin_id' => '复审人id',
  140. 'reaudit_name' => '复审人名字',
  141. 'reaudit_reason' => '复审不通过原因',
  142. 'reaudit_time' => '复审时间',
  143. 'pay_status' => '打款状态 0未打款 1打款成功 2打款失败 3内部打款中 4外部打款中 5打款异常',
  144. 'pay_time' => '打款时间',
  145. 'complete_time' => '完成时间',
  146. 'out_no' => '外部交易号',
  147. 'out_no_crc32' => '外部交易号CRC32',
  148. 'ret_code' => '返回状态码',
  149. 'res_code' => '交易状态码',
  150. 'ret_msg' => '返回信息',
  151. 'sign' => '数据签名',
  152. 'memo' => '备注',
  153. 'create_time' => '创建时间',
  154. 'last_modified' => '最后修改时间',
  155. ];
  156. }
  157. /**
  158. * 生成打款单号 100开头
  159. * @return string
  160. */
  161. public static function generateRemitNo()
  162. {
  163. /** @var Connection $redis */
  164. $redis = Yii::$app->get('redis');
  165. $i = 0;
  166. while (true) {
  167. $i++;
  168. list($usec, $sec) = explode(" ", microtime());
  169. $remitNo = '100' . date('ymdHis', $sec) . sprintf('%03d', $usec * 1000);
  170. if ($redis->set("aike_service:remit_no:{$remitNo}", "1", 'EX', '30', 'NX')) {
  171. return $remitNo;
  172. }
  173. if ($i > 3) {
  174. break;
  175. }
  176. usleep(1000); // sleep 1ms
  177. }
  178. return false;
  179. }
  180. /**
  181. * @param int $bizNo
  182. * @param int $bizType
  183. * @return bool
  184. */
  185. public static function checkBizExist($bizNo, $bizType)
  186. {
  187. return static::find()->where(['biz_no' => $bizNo, 'biz_type' => $bizType])->andWhere(['<>', 'audit_status', self::STATUS_AUDIT_FAIL])->exists();
  188. }
  189. /**
  190. * @param int $remitNo
  191. * @return array|null|\yii\db\ActiveRecord|RemitOrder
  192. */
  193. public static function findByRemitNo($remitNo)
  194. {
  195. return static::find()->where(['remit_no' => $remitNo])->limit(1)->one();
  196. }
  197. /**
  198. * 通过财务打款批次号获取打款实例
  199. * @param $batchNo
  200. * @return array|null|\yii\db\ActiveRecord|RemitOrder
  201. */
  202. public static function findByBatchNo($batchNo)
  203. {
  204. return static::find()->where(['batch_no' => $batchNo])->limit(1)->one();
  205. }
  206. /**
  207. * 批次初审
  208. * @param array $data
  209. * @return bool
  210. */
  211. public function doBatchAudit($data = [])
  212. {
  213. $saveData = [];
  214. if (!isset($data['audit_status']) || !in_array($data['audit_status'], [self::STATUS_AUDIT_SUCCESS, self::STATUS_AUDIT_FAIL])) {
  215. $this->addError('audit_status', '审核状态非法');
  216. return false;
  217. }
  218. $saveData['audit_status'] = $data['audit_status'];
  219. if (isset($data['audit_reason']) && trim($data['audit_status']) != '') {
  220. $saveData['audit_reason'] = trim($data['audit_reason']);
  221. }
  222. if (isset($data['audit_admin_id']) && trim($data['audit_admin_id']) != '') {
  223. $saveData['audit_admin_id'] = intval($data['audit_admin_id']);
  224. }
  225. if (isset($data['audit_name']) && trim($data['audit_name']) != '') {
  226. $saveData['audit_name'] = trim($data['audit_name']);
  227. }
  228. $ip = isset($data['audit_ip']) ? trim($data['audit_ip']) : Utils::getClientIp();
  229. unset($data);
  230. $saveData['audit_time'] = time();
  231. if ($this->audit_status == self::STATUS_AUDIT_INIT || $this->audit_status == self::STATUS_REAUDIT_FAIL) {
  232. // 未审核 或者 复审失败
  233. $affectRows = static::updateAll($saveData, ['batch_no' => $this->batch_no, 'audit_status' => $this->audit_status]);
  234. if ($affectRows == 0) {
  235. $this->addError('audit_status', '审核状态更新失败');
  236. return false;
  237. } else {
  238. $logData = [];
  239. isset($saveData['audit_admin_id']) && $logData['admin_id'] = $saveData['audit_admin_id'];
  240. isset($saveData['audit_name']) && $logData['admin_name'] = $saveData['audit_name'];
  241. if ($saveData['audit_status'] == self::STATUS_AUDIT_SUCCESS) {
  242. $logData['memo'] = "财务打款审核状态: 初审通过";
  243. } else {
  244. $logData['memo'] = "财务打款审核状态: 初审未通过";
  245. }
  246. $logData['admin_ip'] = $ip;
  247. BatchRemitLog::addLog($this->getAttributes(), $logData);
  248. return true;
  249. }
  250. } else {
  251. $this->addError('audit_status', '审核状态必须是未审核或者复审失败');
  252. return false;
  253. }
  254. }
  255. /**
  256. * @param array $data
  257. * @return bool
  258. */
  259. public function doBatchReAudit($data = [])
  260. {
  261. $saveData = [];
  262. if (!isset($data['audit_status']) || !in_array($data['audit_status'], [self::STATUS_REAUDIT_SUCCESS, self::STATUS_REAUDIT_FAIL])) {
  263. $this->addError('audit_status', '审核状态非法');
  264. return false;
  265. }
  266. $saveData['audit_status'] = $data['audit_status'];
  267. if (isset($data['reaudit_reason']) && trim($data['reaudit_reason']) != '') {
  268. $saveData['reaudit_reason'] = trim($data['reaudit_reason']);
  269. }
  270. if (isset($data['reaudit_admin_id']) && trim($data['reaudit_admin_id']) != '') {
  271. $saveData['reaudit_admin_id'] = intval($data['reaudit_admin_id']);
  272. }
  273. if (isset($data['reaudit_name']) && trim($data['reaudit_name']) != '') {
  274. $saveData['reaudit_name'] = trim($data['reaudit_name']);
  275. }
  276. $ip = isset($data['reaudit_ip']) ? trim($data['reaudit_ip']) : Utils::getClientIp();
  277. unset($data);
  278. $saveData['reaudit_time'] = time();
  279. if ($this->audit_status == self::STATUS_AUDIT_SUCCESS) {
  280. // 初审成功
  281. $affectRows = static::updateAll($saveData, ['batch_no' => $this->batch_no, 'audit_status' => $this->audit_status]);
  282. if ($affectRows == 0) {
  283. $this->addError('audit_status', '审核状态更新失败');
  284. return false;
  285. } else {
  286. $logData = $singleLog = [];
  287. isset($saveData['reaudit_admin_id']) && $logData['admin_id'] = $saveData['reaudit_admin_id'];
  288. isset($saveData['reaudit_admin_id']) && $singleLog['admin_id'] = $saveData['reaudit_admin_id'];
  289. isset($saveData['reaudit_name']) && $logData['admin_name'] = $saveData['reaudit_name'];
  290. isset($saveData['reaudit_name']) && $singleLog['admin_name'] = $saveData['reaudit_name'];
  291. $logData['admin_ip'] = $ip;
  292. $singleLog['admin_ip'] = $ip;
  293. if ($saveData['audit_status'] == self::STATUS_REAUDIT_SUCCESS) {
  294. $logData['memo'] = "财务打款审核状态: 复审通过";
  295. $singleLog['memo'] = "创建打款单";
  296. // 单条记录日志
  297. $allData = static::find()->select('remit_no')->where(['batch_no' => $this->batch_no])->asArray()->all();
  298. foreach ($allData as $item) {
  299. RemitLog::addLog($item, $singleLog);
  300. }
  301. } else {
  302. $logData['memo'] = "财务打款审核状态: 复审未通过";
  303. }
  304. // 批次记载日志
  305. BatchRemitLog::addLog($this->getAttributes(), $logData);
  306. return true;
  307. }
  308. } else {
  309. $this->addError('audit_status', '审核状态必须是初审通过');
  310. return false;
  311. }
  312. }
  313. /**
  314. * @param array $data
  315. * @return bool
  316. */
  317. public function doAudit($data = [])
  318. {
  319. $saveData = [];
  320. if (!isset($data['audit_status']) || !in_array($data['audit_status'], [self::STATUS_AUDIT_SUCCESS, self::STATUS_AUDIT_FAIL])) {
  321. $this->addError('audit_status', '审核状态非法');
  322. return false;
  323. }
  324. $saveData['audit_status'] = $data['audit_status'];
  325. if (isset($data['audit_reason']) && trim($data['audit_status']) != '') {
  326. $saveData['audit_reason'] = trim($data['audit_reason']);
  327. }
  328. if (isset($data['audit_admin_id']) && trim($data['audit_admin_id']) != '') {
  329. $saveData['audit_admin_id'] = intval($data['audit_admin_id']);
  330. }
  331. if (isset($data['audit_name']) && trim($data['audit_name']) != '') {
  332. $saveData['audit_name'] = trim($data['audit_name']);
  333. }
  334. $ip = isset($data['audit_ip']) ? trim($data['audit_ip']) : Utils::getClientIp();
  335. unset($data);
  336. $saveData['audit_time'] = time();
  337. if ($this->audit_status == self::STATUS_AUDIT_INIT || $this->audit_status == self::STATUS_REAUDIT_FAIL) {
  338. // 未审核 或者 复审失败
  339. $affectRows = static::updateAll($saveData, ['id' => $this->id, 'remit_no' => $this->remit_no, 'audit_status' => $this->audit_status]);
  340. if ($affectRows == 0) {
  341. $this->addError('audit_status', '审核状态更新失败');
  342. return false;
  343. } else {
  344. $logData = [];
  345. isset($saveData['audit_admin_id']) && $logData['admin_id'] = $saveData['audit_admin_id'];
  346. isset($saveData['audit_name']) && $logData['admin_name'] = $saveData['audit_name'];
  347. if ($saveData['audit_status'] == self::STATUS_AUDIT_SUCCESS) {
  348. $logData['memo'] = "打款单审核状态: 初审通过";
  349. } else {
  350. $logData['memo'] = "打款单审核状态: 初审失败";
  351. }
  352. $logData['admin_ip'] = $ip;
  353. RemitLog::addLog($this->getAttributes(), $logData);
  354. return true;
  355. }
  356. } else {
  357. $this->addError('audit_status', '审核状态必须是未审核或者复审失败');
  358. return false;
  359. }
  360. }
  361. /**
  362. * @param array $data
  363. * @return bool
  364. */
  365. public function doReAudit($data = [])
  366. {
  367. $saveData = [];
  368. if (!isset($data['audit_status']) || !in_array($data['audit_status'], [self::STATUS_REAUDIT_SUCCESS, self::STATUS_REAUDIT_FAIL])) {
  369. $this->addError('audit_status', '审核状态非法');
  370. return false;
  371. }
  372. $saveData['audit_status'] = $data['audit_status'];
  373. if (isset($data['reaudit_reason']) && trim($data['reaudit_reason']) != '') {
  374. $saveData['reaudit_reason'] = trim($data['reaudit_reason']);
  375. }
  376. if (isset($data['reaudit_admin_id']) && trim($data['reaudit_admin_id']) != '') {
  377. $saveData['reaudit_admin_id'] = intval($data['reaudit_admin_id']);
  378. }
  379. if (isset($data['reaudit_name']) && trim($data['reaudit_name']) != '') {
  380. $saveData['reaudit_name'] = trim($data['reaudit_name']);
  381. }
  382. $ip = isset($data['reaudit_ip']) ? trim($data['reaudit_ip']) : Utils::getClientIp();
  383. unset($data);
  384. $saveData['reaudit_time'] = time();
  385. if ($this->audit_status == self::STATUS_AUDIT_SUCCESS) {
  386. // 初审成功
  387. $affectRows = static::updateAll($saveData, ['id' => $this->id, 'remit_no' => $this->remit_no, 'audit_status' => $this->audit_status]);
  388. if ($affectRows == 0) {
  389. $this->addError('audit_status', '审核状态更新失败');
  390. return false;
  391. } else {
  392. $logData = [];
  393. isset($saveData['reaudit_admin_id']) && $logData['admin_id'] = $saveData['reaudit_admin_id'];
  394. isset($saveData['reaudit_name']) && $logData['admin_name'] = $saveData['reaudit_name'];
  395. if ($saveData['audit_status'] == self::STATUS_REAUDIT_SUCCESS) {
  396. $logData['memo'] = "打款单审核状态: 复审通过";
  397. } else {
  398. $logData['memo'] = "打款单审核状态: 复审失败";
  399. }
  400. $logData['admin_ip'] = $ip;
  401. RemitLog::addLog($this->getAttributes(), $logData);
  402. return true;
  403. }
  404. } else {
  405. $this->addError('audit_status', '审核状态必须是初审通过');
  406. return false;
  407. }
  408. }
  409. /**
  410. * 列表数据
  411. * @param array $post
  412. * @return array
  413. */
  414. public function getList($post)
  415. {
  416. $result = ['code' => 0, 'data' => [], 'message' => ''];
  417. $status = isset($post['status']) ? $post['status'] : 'all';
  418. $batch_no = isset($post['batch_no']) ? $post['batch_no'] : '';
  419. $sTime = isset($post['sTime']) ? $post['sTime'] : ''; // 创建时间
  420. $eTime = isset($post['eTime']) ? $post['eTime'] : '';
  421. $sTime2 = isset($post['sTime2']) ? $post['sTime2'] : ''; // 操作时间
  422. $eTime2 = isset($post['eTime2']) ? $post['eTime2'] : '';
  423. $order = isset($post['order']) ? strtolower($post['order']) : '';
  424. $orderBy = isset($post['orderBy']) ? strtolower($post['orderBy']) : 'desc';
  425. $start = isset($post['start']) ? (int) $post['start'] : 0;
  426. $length = isset($post['length']) ? (int) $post['length'] : 20;
  427. $draw = isset($post['draw']) ? $post['draw'] : 1;
  428. $where = ['and'];
  429. // 只有复审成功后的才显示在打款列表
  430. $where[] = ['=', 'audit_status', self::STATUS_REAUDIT_SUCCESS];
  431. // 根据打款状态筛选
  432. if ($status == 'first_trial') {
  433. // 待打款明细
  434. $where[] = ['=', 'pay_status', self::STATUS_PAY_INIT];
  435. } elseif ($status == 're_trial') {
  436. // 打款中明细
  437. $where[] = ['in', 'pay_status', [self::STATUS_PAY_INNER_PROCESS, self::STATUS_PAY_OUTER_PROCESS]];
  438. } elseif ($status == 'passed') {
  439. // 打款成功明细
  440. $where[] = ['=', 'pay_status', self::STATUS_PAY_SUCCESS];
  441. } elseif ($status == 'fail') {
  442. // 打款不成功明细
  443. $where[] = ['=', 'pay_status', self::STATUS_PAY_FAIL];
  444. }
  445. // 打款批次号
  446. if ($batch_no) {
  447. $where[] = ['=', 'batch_no', $batch_no];
  448. }
  449. // 时间
  450. if ($sTime) {
  451. $startTime = strtotime($sTime);
  452. if ($startTime) {
  453. $where[] = ['>=', 'create_time', $startTime];
  454. }
  455. }
  456. if ($eTime) {
  457. $eTime = trim($eTime);
  458. if (preg_match('/^\d+\-\d+\-\d+$/', $eTime)) {
  459. $endTime = strtotime($eTime) + 86400;
  460. } else {
  461. $endTime = strtotime($eTime);
  462. }
  463. if ($endTime) {
  464. $where[] = ['<=', 'create_time', $endTime];
  465. }
  466. }
  467. // 在打款成功明细、打款不成功明细页面,可按完成时间搜索
  468. if (in_array($status, ['passed', 'fail'])) {
  469. if ($sTime2) {
  470. $startTime2 = strtotime($sTime2);
  471. if ($startTime2) {
  472. $where[] = ['>=', 'complete_time', $startTime2];
  473. }
  474. }
  475. if ($eTime2) {
  476. $eTime2 = trim($eTime2);
  477. if (preg_match('/^\d+\-\d+\-\d+$/', $eTime2)) {
  478. $endTime2 = strtotime($eTime2) + 86400;
  479. } else {
  480. $endTime2 = strtotime($eTime2);
  481. }
  482. if ($endTime2) {
  483. $where[] = ['<=', 'complete_time', $endTime2];
  484. }
  485. }
  486. }
  487. // 排序
  488. $allowOrderColumn = ['id', 'batch_no', 'pay_count', 'amount_sum', 'create_time', 'pay_status', 'pay_time'];
  489. if (in_array($order, $allowOrderColumn) && in_array($orderBy, ['asc', 'desc'])) {
  490. if ($orderBy == 'asc') {
  491. $orderCondition = [$order => SORT_ASC];
  492. } else {
  493. $orderCondition = [$order => SORT_DESC];
  494. }
  495. } else {
  496. $orderCondition = ['id' => SORT_DESC];
  497. }
  498. // 字段
  499. $select = ['remit_no', 'batch_no', 'COUNT(*) AS pay_count', 'SUM(amount) AS amount_sum', 'create_time', 'pay_status', 'pay_time', 'complete_time', 'ret_msg'];
  500. $query = static::find();
  501. $query->select($select)
  502. ->where($where)
  503. ->groupBy('batch_no');
  504. $count = $query->count();
  505. if ($count) {
  506. $query->offset($start)->limit($length);
  507. $list = $query->orderBy($orderCondition)->asArray()->all();
  508. // 操作人员的名字到日志表读取,因为用了GROUP BY,所以未使用聚合函数的字段要在子查询里排序
  509. $remitNoArr = array_column($list, 'remit_no');
  510. $remitNoStr = '';
  511. foreach ($remitNoArr as $k => $v) {
  512. $remitNoStr .= '"' . $v . '",';
  513. }
  514. $remitNoStr = rtrim($remitNoStr, ',');
  515. $sql = "SELECT remit_no, admin_name FROM (SELECT * FROM " . RemitLog::tableName() . " WHERE remit_no IN ({$remitNoStr}) ORDER BY id DESC) AS remit_log GROUP BY remit_no ";
  516. $logList = $this->getDb()->createCommand($sql)->queryAll();
  517. foreach ($list as $k => $v) {
  518. $list[$k]['amount_sum'] = Utils::formatFloatOrInt($v['amount_sum']);
  519. $list[$k]['pay_status'] = isset(self::$statusTextMap['pay_status'][$v['pay_status']]) ? self::$statusTextMap['pay_status'][$v['pay_status']] : $v['pay_status'];
  520. $list[$k]['create_time'] = date('Y-m-d H:i:s', $v['create_time']);
  521. // 打款成功或不成功用完成时间,其他用支付时间
  522. if (in_array($v['pay_status'], [self::STATUS_PAY_SUCCESS, self::STATUS_PAY_FAIL])) {
  523. $list[$k]['pay_time'] = $v['complete_time'] ? date('Y-m-d H:i:s', $v['complete_time']) : ($v['pay_time'] ? date('Y-m-d H:i:s', $v['pay_time']) : '');
  524. } else {
  525. $list[$k]['pay_time'] = $v['pay_time'] ? date('Y-m-d H:i:s', $v['pay_time']) : '';
  526. }
  527. unset($list[$k]['complete_time']);
  528. $list[$k]['admin_name'] = '';
  529. foreach ($logList as $k2 => $v2) {
  530. if ($v['remit_no'] == $v2['remit_no']) {
  531. $list[$k]['admin_name'] = $v2['admin_name'];
  532. break;
  533. }
  534. }
  535. }
  536. // 计算笔数和总额,放到最后一行
  537. $query = static::find();
  538. $sum = $query->select(['COUNT(*) AS pay_count', 'SUM(amount) AS amount_sum'])->where($where)->asArray()->limit(1)->one();
  539. $lastRow = [
  540. 'batch_no' => '',
  541. 'pay_count' => $sum['pay_count'],
  542. 'amount_sum' => $sum['amount_sum'],
  543. 'create_time' => '',
  544. 'pay_status' => '',
  545. 'pay_time' => '',
  546. 'ret_msg' => '',
  547. 'admin_name' => '',
  548. ];
  549. array_push($list, $lastRow);
  550. } else {
  551. // 没有数据则输出默认值
  552. $list = [
  553. [
  554. 'batch_no' => '',
  555. 'pay_count' => 0,
  556. 'amount_sum' => 0,
  557. 'create_time' => '',
  558. 'pay_status' => '',
  559. 'pay_time' => '',
  560. 'ret_msg' => '',
  561. 'admin_name' => '',
  562. ],
  563. ];
  564. }
  565. $data['data'] = $list;
  566. $data['draw'] = $draw;
  567. $data['recordsFiltered'] = $count;
  568. $data['recordsTotal'] = $count;
  569. $result['data'] = $data;
  570. $result['code'] = 1;
  571. return $result;
  572. }
  573. /**
  574. * 更改打款状态
  575. * @param array $post
  576. * @return array
  577. */
  578. public function updatePayStatus($post)
  579. {
  580. $result = ['code' => 0, 'data' => [], 'message' => ''];
  581. $batch_no = isset($post['batch_no']) ? $post['batch_no'] : '';
  582. $status = isset($post['status']) ? $post['status'] : '';
  583. $reason = isset($post['reason']) ? trim($post['reason']) : '';
  584. $daysAfterPayTime = isset($post['daysAfterPayTime']) && intval($post['daysAfterPayTime']) ? intval($post['daysAfterPayTime']) : $this->daysAfterPayTime;
  585. $admin_id = isset($post['admin_id']) ? $post['admin_id'] : 0;
  586. $admin_name = isset($post['admin_name']) ? $post['admin_name'] : '';
  587. $admin_ip = isset($post['admin_ip']) ? $post['admin_ip'] : '';
  588. // 检查参数
  589. if (!$batch_no || !in_array($status, ['success', 'fail']) || !$admin_id || !$admin_name) {
  590. $result['message'] = '参数错误';
  591. return $result;
  592. }
  593. // 检查数据
  594. $remitOrderList = static::find()->where(['batch_no' => $batch_no, 'pay_status' => [self::STATUS_PAY_INNER_PROCESS, self::STATUS_PAY_OUTER_PROCESS]])->asArray()->all();
  595. if (!$remitOrderList) {
  596. $result['message'] = '没有对应的打款批次号';
  597. return $result;
  598. }
  599. // 组装数据
  600. $pay_status = $status == 'success' ? self::STATUS_PAY_SUCCESS : self::STATUS_PAY_FAIL;
  601. $time = time();
  602. $saveData = [
  603. 'pay_status' => $pay_status,
  604. 'complete_time' => $time,
  605. ];
  606. if ($status == 'fail') {
  607. $saveData['ret_msg'] = $reason;
  608. }
  609. $todayBeginTime = strtotime(date('Y-m-d'));
  610. $affectRows = 0;
  611. $withinDaysCount = 0;
  612. $transaction = $this->getDb()->beginTransaction();
  613. try {
  614. foreach ($remitOrderList as $k => $v) {
  615. // 打款若干天后才可以更新状态为成功或失败
  616. $payTime = strtotime(date('Y-m-d', $v['pay_time']));
  617. if (($todayBeginTime - $payTime) / 86400 < $daysAfterPayTime) {
  618. $withinDaysCount++;
  619. continue;
  620. }
  621. $updateResult = static::updateAll($saveData, ['id' => $v['id']]);
  622. if ($updateResult) {
  623. $affectRows++;
  624. // 记录日志
  625. $logData = [
  626. 'remit_no' => $v['remit_no'],
  627. 'memo' => '打款状态: ' . self::$statusTextMap['pay_status'][$v['pay_status']] . ' -> ' . self::$statusTextMap['pay_status'][$pay_status],
  628. 'admin_id' => $admin_id,
  629. 'admin_name' => $admin_name,
  630. 'admin_ip' => $admin_ip,
  631. 'create_time' => $time,
  632. ];
  633. $remitLog = new RemitLog();
  634. $remitLog->attributes = $logData;
  635. $remitLog->save();
  636. }
  637. }
  638. $logData = [
  639. 'batch_no' => $batch_no,
  640. 'memo' => '打款状态: ' . self::$statusTextMap['pay_status'][$v['pay_status']] . ' -> ' . self::$statusTextMap['pay_status'][$pay_status],
  641. 'admin_id' => $admin_id,
  642. 'admin_name' => $admin_name,
  643. 'admin_ip' => $admin_ip,
  644. 'create_time' => $time,
  645. ];
  646. $batchRemitLog = new BatchRemitLog();
  647. $batchRemitLog->attributes = $logData;
  648. $batchRemitLog->save();
  649. $transaction->commit();
  650. } catch (\Exception $e) {
  651. $transaction->rollBack();
  652. }
  653. $result['code'] = $affectRows ? 1 : 0;
  654. $result['message'] = '更新' . $affectRows . '笔打款单';
  655. return $result;
  656. }
  657. }