CgRefundService.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. <?php
  2. namespace bizHd\cg\services;
  3. use biz\ghs\classes\GhsClass;
  4. use biz\hb\classes\HbClass;
  5. use biz\shop\classes\ShopCapitalClass;
  6. use biz\shop\classes\ShopClass;
  7. use biz\wx\classes\WxMessageClass;
  8. use bizGhs\product\classes\ProductClass;
  9. use bizGhs\stock\classes\StockRecordClass;
  10. use bizHd\base\services\BaseService;
  11. use bizHd\cg\classes\CgRefundClass;
  12. use bizHd\cg\classes\CgRefundItemClass;
  13. use bizHd\purchase\classes\PurchaseClass;
  14. use bizHd\purchase\classes\PurchaseItemClass;
  15. use bizHd\shop\classes\MainClass;
  16. use bizHd\stat\classes\StatIncomeClass;
  17. use bizHd\wx\classes\WxOpenClass;
  18. use common\components\dict;
  19. use common\components\noticeUtil;
  20. use common\components\orderSn;
  21. use common\components\util;
  22. use Yii;
  23. class CgRefundService extends BaseService
  24. {
  25. public static $baseFile = '\bizHd\cg\classes\CgRefundClass';
  26. //新增退款
  27. public static function addRefund($post, $cg)
  28. {
  29. $cgId = $cg->id ?? 0;
  30. $mainId = $cg->mainId ?? 0;
  31. $shopId = $cg->shopId ?? 0;
  32. $sjId = $cg->sjId ?? 0;
  33. $payWay = $cg->payWay;
  34. $cgOrderSn = $cg->orderSn ?? '';
  35. $cg->refund = PurchaseClass::REFUND_YES;
  36. $cg->save();
  37. $transaction_id = $cg->thirdNo ?? '';
  38. if ($payWay == dict::getDict('payWay', 'wxPay')) {
  39. if (empty($transaction_id)) {
  40. util::fail('第三方支付订单号没有找到');
  41. }
  42. }
  43. $refundOrderSn = orderSn::getCgRefundSn();
  44. $refundPrice = $post['price'] ?? 0;
  45. if (is_numeric($refundPrice) == false || $refundPrice < 0) {
  46. util::fail('退款金额有问题');
  47. }
  48. $shop = ShopClass::getLockById($shopId);
  49. if (empty($shop)) {
  50. util::fail('没有找到门店');
  51. }
  52. $main = MainClass::getLockById($mainId);
  53. if (empty($main)) {
  54. util::fail('没有main信息');
  55. }
  56. $data = [];
  57. $data['status'] = CgRefundClass::STATUS_COMPLETE;
  58. $data['orderSn'] = $refundOrderSn;
  59. $data['shopId'] = $shopId;
  60. $data['mainId'] = $mainId;
  61. $data['sjId'] = $sjId;
  62. $data['shopAdminId'] = $cg->shopAdminId;
  63. $data['shopAdminName'] = $cg->shopAdminName;
  64. $data['cgId'] = $cg->id;
  65. $refundType = $post['refundType'] ?? 0;
  66. $data['refundType'] = $refundType;
  67. $data['refundPrice'] = $refundPrice;
  68. $data['remark'] = $post['remark'];
  69. $data['status'] = CgRefundClass::STATUS_UN_COMPLETE;
  70. //花材列表结构
  71. // [{productId:0,num:1,unitType:0,unitPrice:12,unitName:'扎'}] productId 花材id num 退货数 unitType 大小单位0大1小 unitPrice 售价 unitName单位名称
  72. $productList = $post['product'] ?? '';
  73. $bigNum = 0;
  74. $smallNum = 0;
  75. foreach ($productList as $current) {
  76. $unitType = $current['unitType'] ?? dict::getDict('unitType', 'big');
  77. $num = $current['num'] ?? 0;
  78. if ($unitType == dict::getDict('unitType', 'big')) {
  79. $bigNum = bcadd($bigNum, $num);
  80. } else {
  81. $smallNum = bcadd($smallNum, $num);
  82. }
  83. }
  84. $data['bigNum'] = $bigNum;
  85. $data['smallNum'] = $smallNum;
  86. $cgRefund = CgRefundClass::add($data, true);
  87. if ($refundType == CgRefundClass::REFUND_TYPE_MONEY_GOOD) {
  88. $cgItemInfo = PurchaseItemClass::getAllByCondition(['orderSn' => $cgOrderSn], null, '*', 'productId', true);
  89. foreach ($productList as $info) {
  90. $unitType = $info['unitType'] ?? 0;
  91. $num = $info['num'] ?? 0;
  92. $unitPrice = $info['unitPrice'] ?? 0;
  93. $unitName = $info['unitName'] ?? '';
  94. $productId = $info['productId'] ?? 0;
  95. $ptItemId = $info['ptItemId'] ?? 0;
  96. $currentCgItem = $cgItemInfo[$productId] ?? null;
  97. if (empty($currentCgItem)) {
  98. util::fail('没有找到花材哦!');
  99. }
  100. $currentCgItem->refundNum = bcadd($currentCgItem->refundNum, $num);
  101. $currentCgItem->save();
  102. $refundData = [];
  103. $refundData['orderSn'] = $refundOrderSn;
  104. $refundData['itemId'] = $ptItemId;
  105. $refundData['productId'] = $productId;
  106. $refundData['name'] = $info['name'] ?? '';
  107. $refundData['cover'] = $info['cover'] ?? '';
  108. $refundData['itemCost'] = $info['cost'] ?? 0;
  109. $refundData['ratio'] = $info['ratio'] ?? 0;
  110. $refundData['mainId'] = $mainId;
  111. $refundData['shopId'] = $shopId;
  112. $refundData['sjId'] = $sjId;
  113. $refundData['xhNum'] = $num;
  114. $refundData['xhUnitName'] = $unitName;
  115. $refundData['xhUnitType'] = $unitType;
  116. $refundData['xhUnitPrice'] = $unitPrice;
  117. $refundData['xhPrice'] = 0;
  118. CgRefundItemClass::addData($refundData, $cg);
  119. }
  120. }
  121. //门店总收入增加
  122. $currentTotalIncome = bcadd($main->totalIncome, $refundPrice, 2);
  123. $main->totalIncome = $currentTotalIncome;
  124. $main->save();
  125. $currentType = dict::getDict('capitalType', 'cgRefund', 'id');
  126. //记录总的退款金额
  127. $currentTkPrice = bcadd($cg->tkPrice, $refundPrice, 2);
  128. $cg->tkPrice = $currentTkPrice;
  129. $cg->refund = PurchaseClass::REFUND_YES;
  130. $cg->save();
  131. $ghsId = $cg->ghsId;
  132. $ghs = GhsClass::getLockById($ghsId);
  133. if (empty($ghs)) {
  134. util::fail('没有找到供货商');
  135. }
  136. $ghsName = $ghs->name ?? '';
  137. if ($payWay == dict::getDict('payWay', 'wxPay')) {
  138. //微信收款的原路退回
  139. ini_set('date.timezone', 'Asia/Shanghai');
  140. $wx = Yii::getAlias("@vendor/wxPayApi_v3.0.10");
  141. require_once($wx . '/lib/WxPay.Api.php');
  142. require_once($wx . '/example/WxPay.Config.php');
  143. $totalFee = $cg->book == 1 ? $cg->bookPrice * 100 : $cg->orderPrice * 100;
  144. $refundFee = $refundPrice * 100;
  145. $merchantExt = WxOpenClass::getWxInfo();
  146. $mid = $merchantExt['wxPayMerchantId'] ?? '';
  147. $appId = $merchantExt['miniAppId'] ?? '';
  148. $key = $merchantExt['wxPayKey'] ?? '';
  149. $input = new \WxPayRefund();
  150. $input->SetTransaction_id($transaction_id);
  151. $input->SetTotal_fee($totalFee);
  152. $input->SetRefund_fee($refundFee);
  153. $input->SetNotify_url(Yii::$app->params['hdHost'] . '/notice/wx-refund-callback/');
  154. $config = new \WxPayConfig();
  155. $config->SetAppId($appId);
  156. $config->SetMerchantId($mid);
  157. $config->SetKey($key);
  158. $input->SetOut_refund_no($refundOrderSn);
  159. $input->SetOp_user_id($mid);
  160. $return = \WxPayApi::refund($config, $input);
  161. if (isset($return['return_code']) == false || $return['return_code'] != 'SUCCESS' || isset($return['result_code']) == false || $return['result_code'] != 'SUCCESS') {
  162. $msg = $return['return_msg'] ?? '';
  163. $err_code_des = $return['err_code_des'] ?? '';
  164. Yii::info("退款失败 cgId:{$cgId} msg:{$msg}");
  165. Yii::info($err_code_des);
  166. Yii::info('微信退款返回信息:' . json_encode($return));
  167. util::fail('退款操作失败');
  168. }
  169. $wxRefundId = $return['refund_id'] ?? '';
  170. $cgRefund->thirdRefundNo = $wxRefundId;
  171. $cgRefund->save();
  172. //采购单总金额还要减去退款
  173. $currentRefund = bcadd($cg->refundPrice, $refundPrice, 2);
  174. $cg->refundPrice = $currentRefund;
  175. $currentActPrice = bcsub($cg->actPrice, $refundPrice, 2);
  176. if ($currentActPrice < 0) {
  177. util::fail('退款金额有问题!');
  178. }
  179. $cg->actPrice = $currentActPrice;
  180. $currentRealPrice = bcsub($cg->realPrice, $refundPrice, 2);
  181. if ($currentRealPrice < 0) {
  182. util::fail('退款金额有问题,请排查');
  183. }
  184. $cg->realPrice = $currentRealPrice;
  185. $cg->save();
  186. //发起退款通知
  187. $customName = $order->customName ?? '';
  188. noticeUtil::push("商家正在给{$customName}退款{$refundPrice}元", '15280215347');
  189. } elseif ($payWay == dict::getDict('payWay', 'debtPay')) {
  190. $clearId = $cg->clearId ?? 0;
  191. if (!empty($clearId)) {
  192. util::fail('订单已经结帐,请走线下退款');
  193. }
  194. //采购单总金额还要减去退款
  195. $currentRefund = bcadd($cg->refundPrice, $refundPrice, 2);
  196. $cg->refundPrice = $currentRefund;
  197. $currentActPrice = bcsub($cg->actPrice, $refundPrice, 2);
  198. if ($currentActPrice < 0) {
  199. util::fail('退款金额有问题!');
  200. }
  201. $cg->actPrice = $currentActPrice;
  202. $currentRealPrice = bcsub($cg->realPrice, $refundPrice, 2);
  203. if ($currentRealPrice < 0) {
  204. util::fail('退款金额有问题,请排查');
  205. }
  206. $cg->realPrice = $currentRealPrice;
  207. $currentRemainDebt = bcsub($cg->remainDebtPrice, $refundPrice, 2);
  208. if ($currentRemainDebt < 0) {
  209. util::fail('退款金额有问题哦');
  210. }
  211. if ($currentRemainDebt == 0) {
  212. $cg->debt = PurchaseClass::DEBT_NO;
  213. }
  214. $cg->remainDebtPrice = $currentRemainDebt;
  215. $cg->save();
  216. //门店应付总款减少
  217. $currentMayPay = bcsub($main->mayPay, $refundPrice, 2);
  218. if ($currentMayPay < 0) {
  219. util::fail('应付款有问题');
  220. }
  221. $main->mayPay = $currentMayPay;
  222. $main->save();
  223. //应付供货商款减少
  224. \bizHd\ghs\classes\GhsClass::refundDebtAmountReduce($ghs, $cgRefund, $cg);
  225. } elseif ($payWay == dict::getDict('payWay', 'balancePay')) {
  226. //采购单总金额还要减去退款
  227. $currentRefund = bcadd($cg->refundPrice, $refundPrice, 2);
  228. $cg->refundPrice = $currentRefund;
  229. $currentActPrice = bcsub($cg->actPrice, $refundPrice, 2);
  230. if ($currentActPrice < 0) {
  231. util::fail('退款金额有问题!');
  232. }
  233. $cg->actPrice = $currentActPrice;
  234. $currentRealPrice = bcsub($cg->realPrice, $refundPrice, 2);
  235. if ($currentRealPrice < 0) {
  236. util::fail('退款金额有问题,请排查');
  237. }
  238. $cg->realPrice = $currentRealPrice;
  239. $cg->save();
  240. //门店余额增加
  241. ShopClass::cgRefundAddBalance($main, $shop, $refundPrice, $cgRefund, $ghs);
  242. } else {
  243. util::fail('支付方式没有找到哦!');
  244. }
  245. $sjId = $cg->sjId ?? 0;
  246. $shopId = $cg->shopId ?? 0;
  247. $event = "采购退款({$ghsName})";
  248. $capitalData = [
  249. 'capitalType' => $currentType,
  250. 'io' => 1,
  251. 'totalIncome' => $currentTotalIncome,
  252. 'payWay' => 0,
  253. 'amount' => $refundPrice,
  254. 'sjId' => $sjId,
  255. 'shopId' => $shopId,
  256. 'event' => $event,
  257. 'mainId' => $mainId,
  258. ];
  259. ShopCapitalClass::addCapital($capitalData);
  260. //每天每月收入
  261. StatIncomeClass::updateOrInsert($main, $shop, $refundPrice);
  262. //微信付款的不需要通知,微信官方会通知
  263. if ($payWay != dict::getDict('payWay', 'wxPay')) {
  264. //微信通知退款成功
  265. WxMessageClass::cgRefundInform($shop, $cg, $refundPrice);
  266. }
  267. return $cgRefund;
  268. }
  269. //供货商productId 转 hdProductId [{productId:1,...}]
  270. public static function toggleProductList($ghsItemInfo, $hdShopId, $hdSjId, $mainId)
  271. {
  272. $productIds = array_column($ghsItemInfo, "productId");
  273. $productData = ProductClass::getProductByIds($productIds);
  274. $itemIds = [];
  275. $productMap = [];
  276. foreach ($productData as $v) {
  277. $itemIds[] = $v['itemId'];
  278. $productMap[$v['id']] = $v['itemId'];
  279. }
  280. $hdProductData = ProductClass::getProductInfoByItemIds($itemIds, $mainId);
  281. $hdProductData = array_column($hdProductData, null, "itemId");
  282. foreach ($ghsItemInfo as $k => $v) {
  283. $itemId = $productMap[$v['productId']];
  284. $hdProductId = $hdProductData[$itemId]['id'];
  285. $ghsItemInfo[$k]['hdProductId'] = $hdProductId;
  286. }
  287. return $ghsItemInfo;
  288. }
  289. }