OrderCgClearClass.php 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. <?php
  2. namespace bizHd\purchase\classes;
  3. use bizGhs\clear\classes\ClearClass;
  4. use bizGhs\order\classes\OrderClass;
  5. use bizHd\base\classes\BaseClass;
  6. use common\components\dict;
  7. class OrderCgClearClass extends BaseClass
  8. {
  9. public static $baseFile = '\bizHd\purchase\models\OrderCgClear';
  10. const STATUS_AWAIT_PAY = 1;
  11. const STATUS_HAS_PAY = 2;
  12. const STATUS_EXPIRE = 3;
  13. public static function buildPairsFromOrders($orderList)
  14. {
  15. if (empty($orderList)) {
  16. return [];
  17. }
  18. $purchaseIds = [];
  19. foreach ($orderList as $order) {
  20. $purchaseId = is_array($order) ? ($order['purchaseId'] ?? 0) : ($order->purchaseId ?? 0);
  21. if (!empty($purchaseId)) {
  22. $purchaseIds[] = $purchaseId;
  23. }
  24. }
  25. $cgMap = [];
  26. if (!empty($purchaseIds)) {
  27. $cgList = PurchaseClass::getByIds(array_unique($purchaseIds));
  28. if (!empty($cgList)) {
  29. $cgMap = array_column($cgList, null, 'id');
  30. }
  31. }
  32. $pairs = [];
  33. foreach ($orderList as $order) {
  34. $orderId = is_array($order) ? ($order['id'] ?? 0) : ($order->id ?? 0);
  35. $orderSn = is_array($order) ? ($order['orderSn'] ?? '') : ($order->orderSn ?? '');
  36. $amount = self::resolveDebtAmount($order);
  37. $cgId = intval(is_array($order) ? ($order['purchaseId'] ?? 0) : ($order->purchaseId ?? 0));
  38. $cgSn = '';
  39. if ($cgId > 0 && isset($cgMap[$cgId])) {
  40. $cgSn = $cgMap[$cgId]['orderSn'] ?? '';
  41. }
  42. $pairs[] = [
  43. 'orderId' => intval($orderId),
  44. 'orderSn' => $orderSn,
  45. 'cgId' => $cgId,
  46. 'cgSn' => $cgSn,
  47. 'amount' => $amount,
  48. ];
  49. }
  50. return $pairs;
  51. }
  52. public static function buildPairsFromPurchases($purchaseList)
  53. {
  54. if (empty($purchaseList)) {
  55. return [];
  56. }
  57. $saleIds = [];
  58. foreach ($purchaseList as $purchase) {
  59. $saleId = is_array($purchase) ? ($purchase['saleId'] ?? 0) : ($purchase->saleId ?? 0);
  60. if (!empty($saleId)) {
  61. $saleIds[] = $saleId;
  62. }
  63. }
  64. $orderMap = [];
  65. if (!empty($saleIds)) {
  66. $orderList = OrderClass::getByIds(array_unique($saleIds));
  67. if (!empty($orderList)) {
  68. $orderMap = array_column($orderList, null, 'id');
  69. }
  70. }
  71. $pairs = [];
  72. foreach ($purchaseList as $purchase) {
  73. $cgId = is_array($purchase) ? ($purchase['id'] ?? 0) : ($purchase->id ?? 0);
  74. $cgSn = is_array($purchase) ? ($purchase['orderSn'] ?? '') : ($purchase->orderSn ?? '');
  75. $amount = self::resolveDebtAmount($purchase);
  76. $orderId = intval(is_array($purchase) ? ($purchase['saleId'] ?? 0) : ($purchase->saleId ?? 0));
  77. $orderSn = '';
  78. if ($orderId > 0 && isset($orderMap[$orderId])) {
  79. $orderSn = $orderMap[$orderId]['orderSn'] ?? '';
  80. }
  81. $pairs[] = [
  82. 'orderId' => $orderId,
  83. 'orderSn' => $orderSn,
  84. 'cgId' => intval($cgId),
  85. 'cgSn' => $cgSn,
  86. 'amount' => $amount,
  87. ];
  88. }
  89. return $pairs;
  90. }
  91. public static function bindRelations($clear, $pairs, $status = self::STATUS_AWAIT_PAY)
  92. {
  93. $clearId = is_object($clear) ? ($clear->id ?? 0) : ($clear['id'] ?? 0);
  94. $clearSn = is_object($clear) ? ($clear->orderSn ?? '') : ($clear['orderSn'] ?? '');
  95. if (empty($clearId) || empty($pairs)) {
  96. return;
  97. }
  98. foreach ($pairs as $pair) {
  99. $orderId = intval($pair['orderId'] ?? 0);
  100. $cgId = intval($pair['cgId'] ?? 0);
  101. if ($orderId <= 0 && $cgId <= 0) {
  102. continue;
  103. }
  104. $exists = self::getByCondition([
  105. 'clearId' => $clearId,
  106. 'orderId' => $orderId,
  107. 'cgId' => $cgId,
  108. ], true);
  109. $newAmount = self::normalizeAmount($pair['amount'] ?? 0);
  110. if (!empty($exists)) {
  111. self::patchAmountIfEmpty($exists, $newAmount);
  112. continue;
  113. }
  114. self::add([
  115. 'clearId' => $clearId,
  116. 'clearSn' => $clearSn,
  117. 'orderId' => $orderId,
  118. 'orderSn' => $pair['orderSn'] ?? '',
  119. 'cgId' => $cgId,
  120. 'cgSn' => $pair['cgSn'] ?? '',
  121. 'amount' => $newAmount,
  122. 'status' => $status,
  123. ]);
  124. }
  125. }
  126. public static function markDoneByClearId($clearId)
  127. {
  128. self::markStatusByClearId($clearId, self::STATUS_HAS_PAY);
  129. }
  130. /**
  131. * 更新关联表中的结账单号 (clearSn)
  132. * 用途:当微信/支付宝支付由于拉卡拉规则需要生成新的结账单号时,同步更新关联表中的单号,保持数据一致性
  133. * 谁用:PurchaseClearController 微信/支付宝支付接口
  134. */
  135. public static function updateClearSnByClearId($clearId, $newClearSn)
  136. {
  137. $clearId = intval($clearId);
  138. if ($clearId <= 0 || empty($newClearSn)) {
  139. return;
  140. }
  141. $list = self::getAllByCondition(['clearId' => $clearId], null, '*', null, true);
  142. if (empty($list)) {
  143. return;
  144. }
  145. foreach ($list as $item) {
  146. $item->clearSn = $newClearSn;
  147. $item->save();
  148. }
  149. }
  150. public static function markExpireByClearId($clearId)
  151. {
  152. self::markStatusByClearId($clearId, self::STATUS_EXPIRE);
  153. }
  154. public static function markStatusByClearId($clearId, $status)
  155. {
  156. $clearId = intval($clearId);
  157. $status = intval($status);
  158. if ($clearId <= 0) {
  159. return;
  160. }
  161. $list = self::getAllByCondition(['clearId' => $clearId], null, '*', null, true);
  162. if (empty($list)) {
  163. return;
  164. }
  165. foreach ($list as $item) {
  166. $item->status = $status;
  167. $item->save();
  168. }
  169. }
  170. public static function getOrderIdsByClearId($clearId)
  171. {
  172. $clearId = intval($clearId);
  173. if ($clearId <= 0) {
  174. return [];
  175. }
  176. $list = self::getAllByCondition(['clearId' => $clearId, 'orderId>' => 0], null, 'orderId', null);
  177. return array_values(array_unique(array_filter(array_map('intval', array_column($list, 'orderId')))));
  178. }
  179. public static function getCgIdsByClearId($clearId)
  180. {
  181. $clearId = intval($clearId);
  182. if ($clearId <= 0) {
  183. return [];
  184. }
  185. $list = self::getAllByCondition(['clearId' => $clearId, 'cgId>' => 0], null, 'cgId', null);
  186. return array_values(array_unique(array_filter(array_map('intval', array_column($list, 'cgId')))));
  187. }
  188. public static function getPendingClearIdByOrderId($orderId, $customId)
  189. {
  190. $orderId = intval($orderId);
  191. $customId = intval($customId);
  192. if ($orderId <= 0) {
  193. return 0;
  194. }
  195. $list = self::getAllByCondition([
  196. 'orderId' => $orderId,
  197. 'status' => self::STATUS_AWAIT_PAY,
  198. ], null, 'clearId', null);
  199. if (empty($list)) {
  200. return 0;
  201. }
  202. $clearIds = array_unique(array_map('intval', array_column($list, 'clearId')));
  203. $now = date("Y-m-d H:i:s");
  204. foreach ($clearIds as $clearId) {
  205. $clear = ClearClass::getById($clearId, true);
  206. if (empty($clear)) {
  207. continue;
  208. }
  209. if (($clear->status ?? 0) != PurchaseClearClass::STATUS_AWAIT_PAY) {
  210. continue;
  211. }
  212. if ($customId > 0 && ($clear->customId ?? 0) != $customId) {
  213. continue;
  214. }
  215. $deadline = $clear->deadline ?? '';
  216. if (!empty($deadline) && $deadline < $now) {
  217. continue;
  218. }
  219. return intval($clearId);
  220. }
  221. return 0;
  222. }
  223. protected static function resolveDebtAmount($entity)
  224. {
  225. return self::normalizeAmount(self::readField($entity, 'actPrice'));
  226. }
  227. protected static function readField($entity, $key)
  228. {
  229. return is_array($entity) ? ($entity[$key] ?? 0) : ($entity->$key ?? 0);
  230. }
  231. protected static function normalizeAmount($amount)
  232. {
  233. if ($amount === '' || $amount === null) {
  234. return '0.00';
  235. }
  236. return bcadd((string)$amount, '0', 2);
  237. }
  238. protected static function patchAmountIfEmpty($row, $amount)
  239. {
  240. $amount = self::normalizeAmount($amount);
  241. if (bccomp($amount, '0', 2) <= 0) {
  242. return false;
  243. }
  244. $current = self::normalizeAmount(is_object($row) ? ($row->amount ?? 0) : ($row['amount'] ?? 0));
  245. if (bccomp($current, '0', 2) > 0) {
  246. return false;
  247. }
  248. if (is_object($row)) {
  249. $row->amount = $amount;
  250. return $row->save(false);
  251. }
  252. return false;
  253. }
  254. }