balance ?? '0.00'), '0', 2); } /** * 【用途】得到当前账户「待结欠款」数额(正数)。 * 【规则】净余额 >= 0 时返回 0.00;净余额 < 0 时返回 |净余额|。 */ public static function getOutstandingDebt($row) { $net = self::getNetBalanceFromRow($row); if (bccomp($net, '0', 2) >= 0) { return '0.00'; } return bcmul($net, '-1', 2); } /** * 【用途】把接口返回给前端的金额字段,按新版形态格式化。 * 【说明】由于已全部升级至新版,直接返回净 balance。为了前端各页面和打印机安全兼容, * 我们将真实的待结欠款(正数)同时赋予 debtAmount 和 remainDebtAmount。 */ public static function formatMoneyForClient(array $row, $appVersion = null) { $net = self::getNetBalanceFromRow($row); $row['displayBalance'] = $net; $row['balance'] = $net; // 计算出真实的待结欠款(正数) $outstanding = bccomp($net, '0', 2) < 0 ? bcmul($net, '-1', 2) : '0.00'; $row['debtAmount'] = $outstanding; $row['remainDebtAmount'] = $outstanding; return $row; } /** * 【用途】对 xhGhsCustom(客户)执行一次性「挂账并入余额」。 * 【说明】已全部合并,此方法直接返回。 */ public static function mergeCustomDebtIntoBalanceIfNeeded($custom, $writeBalanceChange = true) { return $custom; } /** * 【用途】对 xhGhs 执行一次性「挂账并入余额」。 * 【说明】已全部合并,此方法直接返回。 */ public static function mergeGhsDebtIntoBalanceIfNeeded($ghs, $writeBalanceChange = true) { return $ghs; } /** * 【用途】客户侧金额写操作前置:仅对客户行加锁,不执行挂账并入余额。 * 【为什么】在全部升级并合并后,写操作只需要锁行即可。 */ public static function ensureCustomMoneyReady($custom, $writeMergeChange = true) { if (empty($custom)) { return $custom; } $customId = is_array($custom) ? ($custom['id'] ?? 0) : ($custom->id ?? 0); return CustomClass::getLockById($customId); } /** * 【用途】控制台批量合并。 * 【说明】已全部合并,此方法直接返回。 */ public static function mergeCustomMoneyForScript($custom, $writeMergeChange = true) { return $custom; } /** * 【用途】判断 xhGhs 是否为 ghsApp「采购供货商」行。 */ public static function isGhsAppPurchaseSupplierRow($ghs) { $ownShopId = intval(is_array($ghs) ? ($ghs['ownShopId'] ?? 0) : ($ghs->ownShopId ?? 0)); if ($ownShopId <= 0) { return false; } $ownPtStyle = intval(is_array($ghs) ? ($ghs['ownPtStyle'] ?? 0) : ($ghs->ownPtStyle ?? 0)); if ($ownPtStyle <= 0) { $shop = \biz\shop\classes\ShopClass::getById($ownShopId); if (!empty($shop)) { $ownPtStyle = intval(is_array($shop) ? ($shop['ptStyle'] ?? 0) : ($shop->ptStyle ?? 0)); } } $hdPt = (int)dict::getDict('ptStyle', 'hd'); if ($ownPtStyle === $hdPt) { return false; } $ghsPt = (int)dict::getDict('ptStyle', 'ghs'); $kmGhsPt = (int)dict::getDict('ptStyle', 'kmGhs'); return in_array($ownPtStyle, [$ghsPt, $kmGhsPt], true); } /** * 【用途】供货商关系行写操作前置:仅加行锁,不执行挂账并入余额。 */ public static function ensureGhsMoneyReady($ghs, $writeMergeChange = true) { if (empty($ghs)) { return $ghs; } $ghsId = is_array($ghs) ? ($ghs['id'] ?? 0) : ($ghs->id ?? 0); return BizGhsClass::getLockById($ghsId); } /** * 【用途】控制台批量合并。 * 【说明】已全部合并,此方法直接返回。 */ public static function mergeGhsMoneyForScript($ghs, $writeMergeChange = true) { return $ghs; } /** * 【用途】汇总某采购供货商下仍待结的 ghs 采购单金额。 */ public static function sumPurchaseOrderDebtForGhs($ghsId) { $ghsId = intval($ghsId); if ($ghsId <= 0) { return '0.00'; } $sum = PurchaseOrderClass::sum( ['ghsId' => $ghsId, 'debt' => PurchaseOrderClass::DEBT_YES], 'actPrice' ); return bcadd((string)($sum ?: '0'), '0', 2); } /** * 【用途】统计某采购供货商仍待结的 ghs 采购单笔数。 */ public static function countPurchaseOrderDebtForGhs($ghsId) { $ghsId = intval($ghsId); if ($ghsId <= 0) { return 0; } return (int)PurchaseOrderClass::getCount([ 'ghsId' => $ghsId, 'debt' => PurchaseOrderClass::DEBT_YES, ]); } /** * 【用途】统计应清理的幽灵待结单数量。 */ public static function countInvalidPurchaseDebtOrders($ghsId) { $ids = self::collectInvalidPurchaseDebtOrderIds($ghsId); return count($ids); } /** * 【用途】有效待结采购单统计。 * @return array{num:int,amount:string} */ public static function getValidPurchaseDebtStats($ghsId) { $ghsId = intval($ghsId); if ($ghsId <= 0) { return ['num' => 0, 'amount' => '0.00']; } $invalidIds = self::collectInvalidPurchaseDebtOrderIds($ghsId); $list = PurchaseOrderClass::getAllByCondition([ 'ghsId' => $ghsId, 'debt' => PurchaseOrderClass::DEBT_YES, ], null, 'id,actPrice', null, true); $num = 0; $amount = '0.00'; if (!empty($list)) { foreach ($list as $order) { $orderId = intval($order->id ?? 0); if (isset($invalidIds[$orderId])) { continue; } $num++; $amount = bcadd($amount, bcadd((string)($order->actPrice ?? '0'), '0', 2), 2); } } return ['num' => $num, 'amount' => $amount]; } /** * 【用途】收集幽灵待结采购单 id。 */ protected static function collectInvalidPurchaseDebtOrderIds($ghsId) { $ghsId = intval($ghsId); $ids = []; if ($ghsId <= 0) { return $ids; } $zeroList = PurchaseOrderClass::getAllByCondition([ 'ghsId' => $ghsId, 'debt' => PurchaseOrderClass::DEBT_YES, 'actPrice<=' => 0, ], null, 'id', null, true); if (!empty($zeroList)) { foreach ($zeroList as $order) { $ids[intval($order->id ?? 0)] = 1; } } $cancelList = PurchaseOrderClass::getAllByCondition([ 'ghsId' => $ghsId, 'debt' => PurchaseOrderClass::DEBT_YES, 'status' => PurchaseOrderClass::PURCHASE_ORDER_STATUS_CANCEL, ], null, 'id', null, true); if (!empty($cancelList)) { foreach ($cancelList as $order) { $ids[intval($order->id ?? 0)] = 1; } } return $ids; } /** * 【用途】清理不应再计待结的采购单。 */ public static function syncInvalidPurchaseDebtOrders($ghsId) { $ghsId = intval($ghsId); if ($ghsId <= 0) { return 0; } $invalidIds = self::collectInvalidPurchaseDebtOrderIds($ghsId); if (empty($invalidIds)) { return 0; } $fixed = 0; foreach (array_keys($invalidIds) as $orderId) { if ($orderId <= 0) { continue; } $order = PurchaseOrderClass::getById($orderId, true); if (empty($order) || intval($order->debt ?? 0) !== PurchaseOrderClass::DEBT_YES) { continue; } $order->debt = PurchaseOrderClass::DEBT_NO; $order->save(false, ['debt']); $fixed++; } return $fixed; } /** * 【用途】按采购待结订单重算 ownShop 侧 xhGhs 净 balance。 * @return object */ public static function mergeOwnShopGhsBalanceFromPurchaseOrdersIfNeeded($ghs, $writeBalanceChange = true, $forceRecalc = false) { return $ghs; } }