GhsController.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. <?php
  2. namespace console\controllers;
  3. use biz\shop\models\Shop;
  4. use bizGhs\custom\classes\AccountMoneyClass;
  5. use bizGhs\custom\classes\CustomClass;
  6. use bizGhs\ghs\classes\GhsClass;
  7. use bizGhs\order\classes\OrderClass;
  8. use bizGhs\order\classes\PurchaseOrderClass;
  9. use common\components\noticeUtil;
  10. use yii\console\Controller;
  11. /**
  12. * 批发供货商控制台任务
  13. *
  14. * adjust-debt:合并后净余额模型下的欠款一致性巡检(与线 ensure*MoneyReady 一致)
  15. * 用法:php yii ghs/adjust-debt
  16. */
  17. class GhsController extends Controller
  18. {
  19. /**
  20. * 供货商欠款跟踪:先合并挂账进余额,再比对订单待结与账户净额
  21. */
  22. public function actionAdjustDebt()
  23. {
  24. ini_set('memory_limit', '2045M');
  25. set_time_limit(0);
  26. $query = new \yii\db\Query();
  27. $query->from(Shop::tableName());
  28. $query->where(['ptStyle' => 2]);
  29. foreach ($query->batch(10) as $batch) {
  30. foreach ($batch as $shop) {
  31. $sjName = $shop['merchantName'] ?? '';
  32. $shopName = $shop['shopName'] ?? '';
  33. $name = $sjName . ' ' . $shopName;
  34. $where = ['ownShopId' => $shop['id']];
  35. $ghsList = GhsClass::getAllByCondition($where, null, '*', null, true);
  36. if (empty($ghsList)) {
  37. continue;
  38. }
  39. foreach ($ghsList as $ghs) {
  40. $this->auditGhsDebtRow($ghs, $name);
  41. }
  42. }
  43. }
  44. }
  45. /**
  46. * 单条 xhGhs:合并后校验成对净余额、销售/采购挂账待结是否一致
  47. */
  48. protected function auditGhsDebtRow($ghs, $shopLabel)
  49. {
  50. $ghsName = $ghs->name ?? '';
  51. $ghsId = intval($ghs->id ?? 0);
  52. if ($ghsId <= 0) {
  53. return;
  54. }
  55. // 与线上一致:巡检前先合并历史 debtAmount → 净 balance
  56. AccountMoneyClass::ensureGhsMoneyReady($ghs, true);
  57. $ghs = GhsClass::getById($ghsId, true);
  58. if (empty($ghs)) {
  59. return;
  60. }
  61. $custom = CustomClass::getByCondition(['ghsId' => $ghsId], true);
  62. if (!empty($custom)) {
  63. AccountMoneyClass::ensureCustomMoneyReady($custom, true);
  64. $custom = CustomClass::getById($custom->id ?? 0, true);
  65. $customNet = AccountMoneyClass::getNetBalanceFromRow($custom);
  66. $ghsNet = AccountMoneyClass::getNetBalanceFromRow($ghs);
  67. if (bccomp($customNet, $ghsNet, 2) !== 0) {
  68. $customId = intval($custom->id ?? 0);
  69. noticeUtil::push(
  70. "{$shopLabel} 供货商{$ghsName}({$ghsId})与客户{$customId} 成对净余额不一致。客户:{$customNet} 关系:{$ghsNet}",
  71. '15280215347'
  72. );
  73. }
  74. }
  75. $saleDebtSum = $this->sumSaleOrderRemainDebt($custom);
  76. $purchaseDebtSum = $this->sumPurchaseOrderRemainDebt($ghsId);
  77. if (bccomp($saleDebtSum, $purchaseDebtSum, 2) !== 0) {
  78. noticeUtil::push(
  79. "{$shopLabel} 供货商{$ghsName}({$ghsId})销售单待结与采购挂账不一致。销售:{$saleDebtSum} 采购:{$purchaseDebtSum}",
  80. '15280215347'
  81. );
  82. }
  83. // 账户净余额为负时:销售单待结合计应与 |净余额| 一致(有余额抵扣时不做此项比对)
  84. $ghsNet = AccountMoneyClass::getNetBalanceFromRow($ghs);
  85. if (bccomp($ghsNet, '0', 2) < 0) {
  86. $accountDebt = AccountMoneyClass::getOutstandingDebt($ghs);
  87. if (bccomp($saleDebtSum, $accountDebt, 2) !== 0) {
  88. noticeUtil::push(
  89. "{$shopLabel} 供货商{$ghsName}({$ghsId})订单待结与账户待结不一致。订单待结:{$saleDebtSum} 账户待结:{$accountDebt} 净余额:{$ghsNet}",
  90. '15280215347'
  91. );
  92. }
  93. }
  94. }
  95. /**
  96. * 销售单挂账待结合计(FIFO 后以 remainDebtPrice 为准)
  97. */
  98. protected function sumSaleOrderRemainDebt($custom)
  99. {
  100. $customId = is_object($custom) ? intval($custom->id ?? 0) : 0;
  101. if ($customId <= 0) {
  102. return '0.00';
  103. }
  104. $orderList = OrderClass::getAllByCondition(
  105. ['customId' => $customId, 'debt' => OrderClass::DEBT_YES],
  106. null,
  107. '*',
  108. null,
  109. true
  110. );
  111. if (empty($orderList)) {
  112. return '0.00';
  113. }
  114. $total = '0.00';
  115. foreach ($orderList as $order) {
  116. $remain = $order->remainDebtPrice ?? 0;
  117. $total = bcadd($total, bcadd((string)$remain, '0', 2), 2);
  118. }
  119. return $total;
  120. }
  121. /**
  122. * 采购单(xhGhsCgOrder)挂账待结合计:有 remainDebtPrice 用之,否则 actPrice
  123. */
  124. protected function sumPurchaseOrderRemainDebt($ghsId)
  125. {
  126. $orderList = PurchaseOrderClass::getAllByCondition([
  127. 'ghsId' => $ghsId,
  128. 'status' => PurchaseOrderClass::PURCHASE_ORDER_STATUS_COMPLETE,
  129. 'debt' => PurchaseOrderClass::DEBT_YES,
  130. ], null, '*', null, true);
  131. if (empty($orderList)) {
  132. return '0.00';
  133. }
  134. $total = '0.00';
  135. foreach ($orderList as $order) {
  136. $remain = '0';
  137. if (is_object($order) && method_exists($order, 'hasAttribute') && $order->hasAttribute('remainDebtPrice')) {
  138. $remain = $order->remainDebtPrice ?? '0';
  139. }
  140. $total = bcadd($total, bcadd((string)$remain, '0', 2), 2);
  141. }
  142. return $total;
  143. }
  144. }