MMerchantWithdraw.Class.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. <?php
  2. namespace JinDouYun\Model\Merchant;
  3. use JinDouYun\Dao\Merchant\DMerchantDetail;
  4. use JinDouYun\Dao\Merchant\DMerchantWithdraw;
  5. use JinDouYun\Dao\Merchant\DMerchantApply;
  6. use JinDouYun\Model\Enterprise\MEnterprise;
  7. use JinDouYun\Model\Finance\MMerchantFlow;
  8. use JinDouYun\Model\MBaseModel;
  9. use Mall\Framework\Core\ErrorCode;
  10. use Mall\Framework\Core\ResultWrapper;
  11. use Mall\Framework\Core\StatusCode;
  12. /**
  13. * @copyright Copyright (c) https://www.qianniaovip.com All rights reserved
  14. * Description:
  15. * Class MMerchantWithdraw
  16. * @package JinDouYun\Model\Merchant
  17. */
  18. class MMerchantWithdraw extends MBaseModel
  19. {
  20. private $onlineEnterpriseId;
  21. private $onlineUserId;
  22. private $objDMerchantWithdraw;
  23. private $objDMerchantApply;
  24. private $objDMerchantDetail;
  25. /**
  26. * MMerchantWithdraw constructor.
  27. * @param $onlineEnterpriseId
  28. * @param $onlineUserId
  29. * @throws \Exception
  30. */
  31. public function __construct($onlineEnterpriseId, $onlineUserId)
  32. {
  33. $this->onlineUserId = $onlineUserId;
  34. $this->onlineEnterpriseId = $onlineEnterpriseId;
  35. parent::__construct($onlineEnterpriseId, $onlineUserId);
  36. $this->objDMerchantWithdraw = new DMerchantWithdraw();
  37. $this->objDMerchantApply = new DMerchantApply();
  38. $this->objDMerchantDetail = new DMerchantDetail();
  39. $this->objDMerchantWithdraw->setTable('qianniao_merchant_withdraw_' . $this->onlineEnterpriseId);
  40. $this->objDMerchantDetail->setTable('qianniao_merchant_detail_' . $this->onlineEnterpriseId);
  41. }
  42. /**
  43. * Doc: (des="商户申请提现")
  44. * User: XMing
  45. * Date: 2020/12/8
  46. * Time: 11:27 上午
  47. * @param array $params
  48. * @param $shopId
  49. * @return ResultWrapper
  50. * @throws \Exception
  51. */
  52. public function add(array $params, $merchantId): ResultWrapper
  53. {
  54. $objMMerchant = new MMerchant($this->onlineEnterpriseId, $this->onlineUserId);
  55. // $merchResult = $objMMerchant->getMerchByShopId($shopId);
  56. $merchantApply = $this->objDMerchantApply->get($merchantId);
  57. if ($merchantApply=== false) {
  58. return ResultWrapper::fail($this->objDMerchantApply->error(), ErrorCode::$dberror);
  59. }
  60. $merch = $merchantApply;
  61. if ($merch['balance'] < $params['money']) {
  62. return ResultWrapper::fail('可提现余额不足', ErrorCode::$paramError);
  63. }
  64. // if ($merch['orderNum'] < $params['orderNum']) {
  65. // return ResultWrapper::fail('提现订单数异常', ErrorCode::$paramError);
  66. // }
  67. $objMEnterprise = new MEnterprise();
  68. $enterpriseResult = $objMEnterprise->getEnterpriseDataByEnterpriseId($this->onlineEnterpriseId);
  69. if (!$enterpriseResult->isSuccess()) {
  70. return ResultWrapper::fail($enterpriseResult->getData(), $enterpriseResult->getErrorCode());
  71. }
  72. $enterprise = $enterpriseResult->getData();
  73. if (empty($enterprise)) {
  74. return ResultWrapper::fail('未获取到平台数据', ErrorCode::$paramError);
  75. }
  76. $settingResult = $objMMerchant->getSetting();
  77. if (!$settingResult->isSuccess()) {
  78. return ResultWrapper::fail($settingResult->getData(), $settingResult->getErrorCode());
  79. }
  80. $setting = $settingResult->getData();
  81. $take_price = getArrayItem($setting, 'take_price', 0);
  82. $take_price_rate = bcdiv($take_price, 100, 4);
  83. $fee = bcmul($params['money'], $take_price_rate, 2);
  84. $nowMoney = bcsub($params['money'], $fee, 2);
  85. $no = createOrderSn(StatusCode::$source['manage'], StatusCode::$orderType['storeWithdraw'], $this->onlineUserId);
  86. $orderNum = $params['orderNum'];//本次提现订单数
  87. $insert = [
  88. 'no' => $no,
  89. 'merchantId' => $merch['id'],
  90. 'merchantName' => $merch['name'],
  91. 'type' => $params['type'],
  92. 'accountContent' => json_encode($params['accountContent']),
  93. 'money' => $params['money'],
  94. 'auditStatus' => StatusCode::$auditStatus['auditing'],
  95. 'rate' => $take_price,//抽成比率
  96. 'fee' => $fee,//抽成金额
  97. 'nowMoney' => $nowMoney,//预计到账金额
  98. 'orderNum' => $orderNum,//本次提现金额订单数
  99. 'createTime' => time(),
  100. ];
  101. //减商户可提现余额
  102. $originMoney = getArrayItem($merch, 'balance', 0);
  103. $finalMoney = bcsub($originMoney, $params['money'], 2);
  104. $merch_log = [
  105. 'merchantId' => $merch['id'],
  106. 'merchantName' => $merch['name'],
  107. 'originId' => 0,
  108. 'originNo' => $no,
  109. 'tradeMoney' => $params['money'],
  110. 'originMoney' => $originMoney,
  111. 'changeMoney' => $params['money'],
  112. 'nowMoney' => $finalMoney,
  113. 'rate' => $take_price,
  114. 'fee' => $fee,
  115. 'type' => StatusCode::$delete,
  116. 'isPayment' => StatusCode::$delete,
  117. 'isPlatform' => StatusCode::$delete,
  118. 'source' => 2,
  119. 'describe' => '账户可提现金额:' . $originMoney . '元,本次提现金额:' . $params['money'] . '元,抽成比率:' . $take_price . '%,预计抽成金额:' . $fee . '元,账户剩余可提现:' . $finalMoney . '元',
  120. 'createTime' => time()
  121. ];
  122. //加商户提现待审核金额
  123. $update_merch = [
  124. 'orderNum' => bcsub($merch['orderNum'], $orderNum, 0),//每次提现都是全部订单
  125. 'auditOrderNum' => bcadd($merch['auditOrderNum'], $orderNum, 0),//等待审核的订单数量
  126. 'balance' => $finalMoney,
  127. 'waitAuditWithdraw' => bcadd(getArrayItem($merch, 'waitAuditWithdraw', 0), $params['money'], 2),
  128. 'updateTime' => time(),
  129. ];
  130. //打款成功后计入平台抽成收入
  131. $objMMerchantFlow = new MMerchantFlow($this->onlineEnterpriseId, $this->onlineUserId);
  132. $beginTransactionStatus = $this->objDMerchantWithdraw->beginTransaction();
  133. $insertResult = $this->objDMerchantWithdraw->insert($insert);
  134. if ($insertResult === false) {
  135. $this->objDMerchantWithdraw->rollBack();
  136. return ResultWrapper::fail($this->objDMerchantWithdraw->error, ErrorCode::$dberror);
  137. }
  138. $merch_log['originId'] = $insertResult;
  139. $flowResult = $objMMerchantFlow->add($merch_log);
  140. if (!$flowResult->isSuccess()) {
  141. $this->objDMerchantWithdraw->rollBack();
  142. return ResultWrapper::fail($flowResult->getData(), $flowResult->getErrorCode());
  143. }
  144. $updateMerchResult = $objMMerchant->update($merch['id'], $update_merch);
  145. if (!$updateMerchResult->isSuccess()) {
  146. $this->objDMerchantWithdraw->rollBack();
  147. return ResultWrapper::fail($updateMerchResult->getData(), $updateMerchResult->getErrorCode());
  148. }
  149. //提现成功添加流水
  150. $insertDetail = [
  151. 'merchantId' => $merch['id'],
  152. 'merchantName' => $merch['name'],
  153. 'originId' => $insertResult,
  154. 'originNo' => $no,
  155. 'money' => $params['money'],
  156. 'afterMoney' => $finalMoney,
  157. 'type' => StatusCode::$delete,
  158. 'source' => 1,
  159. 'remark' => '提现',
  160. 'createTime' => time(),
  161. 'updateTime' => time()
  162. ];
  163. $detailsDbResult = $this->objDMerchantDetail->insert($insertDetail);
  164. if($detailsDbResult === false){
  165. $this->objDMerchantDetail->rollBack();
  166. return ResultWrapper::fail($this->objDMerchantDetail->error(), ErrorCode::$dberror);
  167. }
  168. if($beginTransactionStatus){
  169. $this->objDMerchantWithdraw->commit();
  170. }
  171. return ResultWrapper::success(true);
  172. }
  173. /**
  174. * Doc: (des="更新提现记录状态")
  175. * User: XMing
  176. * Date: 2020/12/8
  177. * Time: 3:58 下午
  178. * @param int $id
  179. * @param int $status
  180. * @return ResultWrapper
  181. * @throws \Exception
  182. */
  183. public function updateAuditStatus(int $id, int $status): ResultWrapper
  184. {
  185. if (!in_array($status, array_keys(StatusCode::$auditStatus))) {
  186. return ResultWrapper::fail('状态不存在', ErrorCode::$notAllowAccess);
  187. }
  188. //查询当前记录
  189. $withdraw = $this->objDMerchantWithdraw->get($id);
  190. if ($withdraw === false) {
  191. return ResultWrapper::fail($this->objDMerchantWithdraw->error, ErrorCode::$dberror);
  192. }
  193. if (empty($withdraw)) {
  194. return ResultWrapper::fail('未获取到指定的记录', ErrorCode::$paramError);
  195. }
  196. //获取商户的数据
  197. $objMMerchant = new MMerchant($this->onlineEnterpriseId, $this->onlineUserId);
  198. // $merchResult = $objMMerchant->getMerchByShopId($withdraw['shopId']);
  199. // if (!$merchResult->isSuccess()) {
  200. // return ResultWrapper::fail($merchResult->getData(), $merchResult->getErrorCode());
  201. // }
  202. // $merch = $merchResult->getData();
  203. $merchantApply = $this->objDMerchantApply->get($withdraw['merchantId']);
  204. if ($merchantApply=== false) {
  205. return ResultWrapper::fail($this->objDMerchantApply->error(), ErrorCode::$dberror);
  206. }
  207. $merch = $merchantApply;
  208. $oldBalance = $merch['balance'];//可提现
  209. $oldWaitAuditWithdraw = $merch['waitAuditWithdraw'];//提现等待审核
  210. $oldAuditWithdraw = $merch['auditWithdraw'];//提现待入账金额
  211. $oldWithdraw = $merch['withdraw'];//已提现金额
  212. $changeMoney = $withdraw['money'];//本次变动金额
  213. $updateMap = [];
  214. $plat_log = [];
  215. switch ($status) {
  216. case StatusCode::$auditStatus['auditing']:
  217. //申请提现操作
  218. break;
  219. case StatusCode::$auditStatus['auditPass']:
  220. //打款成功,需要给平台抽成
  221. // + finishOrderNum - waitFinishOrderNum
  222. if (bcsub($oldAuditWithdraw, $changeMoney, 2) < 0) {
  223. return ResultWrapper::fail('待入账金额不足', ErrorCode::$paramError);
  224. }
  225. $updateMap = [
  226. 'updateTime' => time(),
  227. 'auditWithdraw' => bcsub($oldAuditWithdraw, $changeMoney, 2),
  228. 'withdraw' => bcadd($oldWithdraw, $changeMoney, 2),
  229. 'finishOrderNum' => bcadd($merch['finishOrderNum'], $withdraw['orderNum'], 0),
  230. 'waitFinishOrderNum' => bcsub($merch['waitFinishOrderNum'], $withdraw['orderNum'], 0),
  231. ];
  232. if ($withdraw['fee'] > 0) {
  233. $objMEnterprise = new MEnterprise();
  234. $enterpriseResult = $objMEnterprise->getEnterpriseDataByEnterpriseId($this->onlineEnterpriseId);
  235. if (!$enterpriseResult->isSuccess()) {
  236. return ResultWrapper::fail($enterpriseResult->getData(), $enterpriseResult->getErrorCode());
  237. }
  238. $enterprise = $enterpriseResult->getData();
  239. if (empty($enterprise)) {
  240. return ResultWrapper::fail('未获取到平台数据', ErrorCode::$paramError);
  241. }
  242. $plat_log = [
  243. 'merchantId' => $merch['id'],
  244. 'merchantName' => $merch['name'],
  245. 'originId' => $withdraw['id'],
  246. 'originNo' => $withdraw['no'],
  247. 'tradeMoney' => $withdraw['money'],
  248. 'originMoney' => $enterprise['balance'],
  249. 'changeMoney' => $withdraw['fee'],
  250. 'nowMoney' => bcsub($enterprise['balance'], $withdraw['fee'], 2),
  251. 'rate' => $withdraw['rate'],
  252. 'fee' => $withdraw['fee'],
  253. 'type' => StatusCode::$standard,
  254. 'isPayment' => StatusCode::$delete,
  255. 'isPlatform' => StatusCode::$standard,
  256. 'source' => 2,
  257. 'describe' => '当前平台账户金额:' . $enterprise['balance'] . '元,本次抽成比率:' . $withdraw['rate'] . '%,本次抽成金额:' . $withdraw['fee'] . '元,变动后账户金额:' . bcsub($enterprise['balance'], $withdraw['fee'], 2) . '元',
  258. 'createTime' => time()
  259. ];
  260. }
  261. break;
  262. case StatusCode::$auditStatus['auditNotPass']:
  263. //提现审核拒绝,回到余额
  264. // + notOrderNum - auditOrderNum + orderNum
  265. if (bcsub($oldWaitAuditWithdraw, $changeMoney, 2) < 0) {
  266. return ResultWrapper::fail('待审核金额不足', ErrorCode::$paramError);
  267. }
  268. $updateMap = [
  269. 'updateTime' => time(),
  270. 'balance' => bcadd($oldBalance, $changeMoney, 2),
  271. 'waitAuditWithdraw' => bcsub($oldWaitAuditWithdraw, $changeMoney, 2),
  272. 'notOrderNum' => bcadd($merch['notOrderNum'], $withdraw['orderNum'], 0),
  273. 'auditOrderNum' => bcsub($merch['auditOrderNum'], $withdraw['orderNum'], 0),
  274. 'orderNum' => bcadd($merch['orderNum'], $withdraw['orderNum'], 0),
  275. ];
  276. $plat_log = [
  277. 'merchantId' => $merch['id'],
  278. 'merchantName' => $merch['name'],
  279. 'originId' => $withdraw['id'],
  280. 'originNo' => $withdraw['no'],
  281. 'tradeMoney' => $withdraw['money'],
  282. 'originMoney' => $oldBalance,
  283. 'changeMoney' => $changeMoney,
  284. 'nowMoney' => bcadd($oldBalance, $changeMoney, 2),
  285. 'rate' => 0,
  286. 'fee' => 0,
  287. 'type' => StatusCode::$standard,
  288. 'isPayment' => StatusCode::$delete,
  289. 'isPlatform' => StatusCode::$delete,
  290. 'source' => 2,
  291. 'describe' => '当前账户金额:' . $oldBalance . '元,本次提现驳回金额:' . $changeMoney . '元,变动后账户金额:' . bcadd($oldBalance, $changeMoney, 2) . '元',
  292. 'createTime' => time()
  293. ];
  294. break;
  295. case StatusCode::$auditStatus['auditIng']:
  296. //等待打款,审核成功
  297. // + passOrderNum - auditOrderNum + waitFinishOrderNum
  298. if (bcsub($oldWaitAuditWithdraw, $changeMoney, 2) < 0) {
  299. return ResultWrapper::fail('待审核金额不足', ErrorCode::$paramError);
  300. }
  301. $updateMap = [
  302. 'updateTime' => time(),
  303. 'waitAuditWithdraw' => bcsub($oldWaitAuditWithdraw, $changeMoney, 2),
  304. 'auditWithdraw' => bcadd($oldAuditWithdraw, $changeMoney, 2),
  305. 'passOrderNum' => bcadd($merch['passOrderNum'], $withdraw['orderNum'], 0),
  306. 'waitFinishOrderNum' => bcadd($merch['waitFinishOrderNum'], $withdraw['orderNum'], 0),
  307. 'auditOrderNum' => bcsub($merch['auditOrderNum'], $withdraw['orderNum'], 0),
  308. ];
  309. break;
  310. default:
  311. return ResultWrapper::fail('状态值有误', ErrorCode::$paramError);
  312. break;
  313. }
  314. $updateData = [
  315. 'auditStatus' => $status,
  316. 'updatetime' => time(),
  317. ];
  318. // 审核通过时间
  319. if ($status == StatusCode::$auditStatus['auditIng']) {
  320. $updateData['auditTime'] = time();
  321. }
  322. // 打款完成时间
  323. if ($status == StatusCode::$auditStatus['auditIng']) {
  324. $updateData['payTime'] = time();
  325. }
  326. $this->objDMerchantWithdraw->beginTransaction();
  327. //操作余额
  328. $updateMerchResult = $objMMerchant->update($merch['id'], $updateMap);
  329. if (!$updateMerchResult->isSuccess()) {
  330. $this->objDMerchantWithdraw->rollBack();
  331. return ResultWrapper::fail($updateMerchResult->getData(), $updateMerchResult->getErrorCode());
  332. }
  333. //更新状态
  334. $auditResult = $this->objDMerchantWithdraw->update($updateData, $id);
  335. if ($auditResult === false) {
  336. $this->objDMerchantWithdraw->rollBack();
  337. return ResultWrapper::fail($this->objDMerchantWithdraw->error(), ErrorCode::$dberror);
  338. }
  339. //添加平台记录
  340. if (!empty($plat_log)) {
  341. $objMMerchantFlow = new MMerchantFlow($this->onlineEnterpriseId, $this->onlineUserId);
  342. $flowResult = $objMMerchantFlow->add($plat_log);
  343. if (!$flowResult->isSuccess()) {
  344. $this->objDMerchantWithdraw->rollBack();
  345. return ResultWrapper::fail($flowResult->getData(), $flowResult->getErrorCode());
  346. }
  347. }
  348. $this->objDMerchantWithdraw->commit();
  349. return ResultWrapper::success(true);
  350. }
  351. /**
  352. * Doc: (des="提现记录")
  353. * User: XMing
  354. * Date: 2020/12/8
  355. * Time: 4:53 下午
  356. * @param array $selectParams
  357. * @return ResultWrapper
  358. */
  359. public function getAll(array $selectParams): ResultWrapper
  360. {
  361. $limit = $selectParams['limit'];
  362. unset($selectParams['limit']);
  363. $offset = $selectParams['offset'];
  364. unset($selectParams['offset']);
  365. $returnData = [
  366. 'data' => [],
  367. 'total' => 0,
  368. ];
  369. $fields = ' * ';
  370. $countField = ' COUNT(id) as total ';
  371. $whereSql = '';
  372. if (isset($selectParams['merchantId']) && !empty($selectParams['merchantId'])) {
  373. $where = empty($whereSql) ? ' WHERE ' : ' AND ';
  374. $whereSql .= $where . ' merchantId = ' . $selectParams['merchantId'];
  375. }
  376. if (isset($selectParams['type']) && !empty($selectParams['type'])) {
  377. $where = empty($whereSql) ? ' WHERE ' : ' AND ';
  378. $whereSql .= $where . ' type = ' . $selectParams['type'];
  379. }
  380. if (isset($selectParams['auditStatus']) && !empty($selectParams['auditStatus'])) {
  381. $where = empty($whereSql) ? ' WHERE ' : ' AND ';
  382. $whereSql .= $where . ' auditStatus = ' . $selectParams['auditStatus'];
  383. }
  384. if ( (isset($selectParams['startTime']) && !empty($selectParams['startTime']))&&(isset($selectParams['endTime']) && !empty($selectParams['endTime'])) ) {
  385. $where = empty($whereSql) ? ' WHERE ' : ' AND ';
  386. $whereSql .= $where . ' createTime BETWEEN ' . $selectParams['startTime'] . ' AND '. $selectParams['endTime'];
  387. }
  388. if (isset($selectParams['no']) && !empty($selectParams['no'])) {
  389. $where = empty($whereSql) ? ' WHERE ' : ' AND ';
  390. $whereSql .= $where . ' no = ' . $selectParams['no'];
  391. }
  392. $countSql = 'SELECT ' . $countField . ' FROM ' . $this->objDMerchantWithdraw->get_Table() . $whereSql;
  393. $sql = 'SELECT ' . $fields . ' FROM ' . $this->objDMerchantWithdraw->get_Table() . $whereSql .' ORDER BY createTime DESC LIMIT ' . $offset . ' , ' . $limit;
  394. $dbResult = $this->objDMerchantWithdraw->query($sql);
  395. if ($dbResult === false) {
  396. return ResultWrapper::fail($this->objDMerchantWithdraw->error(), ErrorCode::$dberror);
  397. }
  398. $total = $this->objDMerchantWithdraw->query($countSql);
  399. foreach ($dbResult as &$value) {
  400. $value['accountContent'] = json_decode($value['accountContent'], true);
  401. $value['passMoney'] = 0;
  402. $value['passOrderNum'] = 0;
  403. if (!in_array($value['auditStatus'], [StatusCode::$auditStatus['auditNotPass'], StatusCode::$auditStatus['auditing']])) {
  404. $value['passMoney'] = $value['money'];
  405. $value['passOrderNum'] = $value['orderNum'];
  406. }
  407. }
  408. $return = [
  409. 'data' => $dbResult,
  410. 'total' => isset($total[0]['total']) ? $total[0]['total'] : 0,
  411. ];
  412. return ResultWrapper::success($return);
  413. }
  414. /**
  415. * Doc: (des="统计")
  416. * User: XMing
  417. * Date: 2020/12/9
  418. * Time: 2:15 下午
  419. * @param int $status
  420. * @param int $shopId
  421. * @param string $fields
  422. * @return int
  423. */
  424. public function statistics(int $status, int $shopId, $fields = 'nowMoney'): int
  425. {
  426. $sql = 'SELECT sum(' . $fields . ') as ' . $fields . ' FROM qianniao_merchant_withdraw_' . $this->onlineEnterpriseId . '
  427. WHERE auditStatus = ' . $status;
  428. $sum = $this->objDMerchantWithdraw->query($sql);
  429. if ($sum === false) {
  430. return 0;
  431. }
  432. $sum = isset($sum[0][$fields]) ? $sum[0][$fields] : 0;
  433. return $sum;
  434. }
  435. }