|
|
@@ -9,131 +9,80 @@ use common\components\dict;
|
|
|
use Yii;
|
|
|
|
|
|
/**
|
|
|
- * 客户/供货商账户金额(表 xhGhsCustom、xhGhs)
|
|
|
- *
|
|
|
- * 背景:原 debtAmount=挂账累计、balance=充值余额,现统一为净 balance(正=有余额,负=待结)。
|
|
|
- * 合并(客户/批发关系行):balance = 原 balance - 原 debtAmount,debtAmount 置 0,balanceMerged=1。
|
|
|
- * 合并(ghsApp 采购供货商行,ownPtStyle=ghs/kmGhs):按待结采购单 actPrice 合计重算净 balance,debtAmount 置 0。
|
|
|
- * 合并(hd 花店侧供货商行,ownPtStyle=hd):balance -= debtAmount 旧逻辑(mergeGhsDebtIntoBalanceIfNeeded);二者不可混用。
|
|
|
- * 写业务前调 ensureCustomMoneyReady / ensureGhsMoneyReady(仅行锁,不触发合并)。
|
|
|
- * 批量合并仅由控制台脚本调用 mergeCustomMoneyForScript / mergeGhsMoneyForScript 等。
|
|
|
- * 列表/详情返回前调 formatMoneyForClient。
|
|
|
- * 旧 App(appVersion<3)由 formatMoneyForClient 拆回待结+余额双字段;新 App 只读净 balance。
|
|
|
- *
|
|
|
- * 充值销账(合并后来款 FIFO 销单):bizGhs\custom\services\GhsRechargeSettleService
|
|
|
+ * 【用途】客户/供货商账户金额核心处理类(表 xhGhsCustom、xhGhs)
|
|
|
+ * 【为什么】在全部升级到新版、全部账户已合并的前提下,彻底移除旧版 appVersion < 3 兼容逻辑与 balanceMerged 复杂校验,极大地简化计算路径,提升系统性能与稳定性。
|
|
|
+ * 【说明】
|
|
|
+ * - 数据库中的 balance 已经是唯一的净余额(正数代表有充值余额,负数代表待结欠款)。
|
|
|
+ * - 数据库中的 debtAmount 字段已废弃,其值始终为 0.00。
|
|
|
+ * - 写业务前调用 ensureCustomMoneyReady / ensureGhsMoneyReady(仅行锁,不触发合并)。
|
|
|
*/
|
|
|
class AccountMoneyClass
|
|
|
{
|
|
|
/**
|
|
|
- * 新端协议版本号:请求头 appVersion >= 此值时,接口只返回净 balance,不再拆分待结/余额两列。
|
|
|
- * 与前端 ghsApp/ghs/hdApp/ghsPad 的 request.js 中 appVersion 保持一致。
|
|
|
+ * 新端协议版本号:只返回净 balance,不再拆分待结/余额两列。
|
|
|
*/
|
|
|
const APP_VERSION_NET_BALANCE = 3;
|
|
|
|
|
|
/**
|
|
|
- * 【用途】获取当前 HTTP 请求里的客户端版本号,供 formatMoneyForClient 决定返回字段形态。
|
|
|
- * 【调用时机】一般无需直接调;formatMoneyForClient 内部会自动读取。
|
|
|
- * 【返回值】整数,默认 2(旧端);3 表示新端净余额协议。
|
|
|
+ * 【用途】获取当前 HTTP 请求里的客户端版本号。
|
|
|
+ * 【说明】由于全部已升级到新版,此方法固定返回 3。
|
|
|
*/
|
|
|
public static function getClientAppVersion()
|
|
|
{
|
|
|
- if (isset(Yii::$app->params['clientAppVersion'])) {
|
|
|
- return (int)Yii::$app->params['clientAppVersion'];
|
|
|
- }
|
|
|
- $headers = Yii::$app->request->headers ?? null;
|
|
|
- $ver = $headers ? (int)$headers->get('appVersion', 2) : 2;
|
|
|
- Yii::$app->params['clientAppVersion'] = $ver;
|
|
|
- return $ver;
|
|
|
+ return self::APP_VERSION_NET_BALANCE;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 【用途】判断数据行是否带有 balanceMerged 字段(是否已执行 SQL 迁移)。
|
|
|
- * 【调用时机】内部判断幂等标记;未迁移库时靠 debtAmount 是否为 0 代替。
|
|
|
- * 【参数】$row 数组或 ActiveRecord
|
|
|
- * 【返回值】true=表结构含 balanceMerged 列
|
|
|
+ * 【用途】判断数据行是否带有 balanceMerged 字段。
|
|
|
+ * 【说明】已全部合并,此方法固定返回 true。
|
|
|
*/
|
|
|
public static function hasMergeFlagField($row)
|
|
|
{
|
|
|
- if (is_array($row)) {
|
|
|
- return array_key_exists('balanceMerged', $row);
|
|
|
- }
|
|
|
- return is_object($row) && method_exists($row, 'hasAttribute') && $row->hasAttribute('balanceMerged');
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 【用途】判断该客户/供货商账户是否已经完成「挂账并入余额」。
|
|
|
- * 【调用时机】合并前检查,避免重复合并、重复写说明流水。
|
|
|
- * 【参数】$row 含 balanceMerged、debtAmount 的数组或模型
|
|
|
- * 【返回值】true=已合并(或本无挂账)
|
|
|
+ * 【说明】已全部合并,此方法固定返回 true。
|
|
|
*/
|
|
|
public static function isMerged($row)
|
|
|
{
|
|
|
- if (!self::hasMergeFlagField($row)) {
|
|
|
- return bccomp(self::rawDebtAmount($row), '0', 2) == 0;
|
|
|
- }
|
|
|
- if (is_array($row)) {
|
|
|
- return !empty($row['balanceMerged']);
|
|
|
- }
|
|
|
- return !empty($row->balanceMerged);
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 【用途】内部取 debtAmount 原始值,供 isMerged / calcNetBalance 使用。
|
|
|
- * 【说明】外部业务请用 getNetBalanceFromRow,不要直接读 debtAmount。
|
|
|
+ * 【用途】内部取 debtAmount 原始值。
|
|
|
+ * 【说明】已全部合并,此方法固定返回 '0.00'。
|
|
|
*/
|
|
|
protected static function rawDebtAmount($row)
|
|
|
{
|
|
|
- if (is_array($row)) {
|
|
|
- return $row['debtAmount'] ?? '0.00';
|
|
|
- }
|
|
|
- return $row->debtAmount ?? '0.00';
|
|
|
+ return '0.00';
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 【用途】根据库里的 balance、debtAmount 计算「净账户余额」(合并前后均可用)。
|
|
|
- * 【规则】未合并:净额 = balance - debtAmount(等价于旧逻辑下「余额减待结」后的真实资金位置);
|
|
|
- * 已合并:净额 = balance(debtAmount 应为 0)。
|
|
|
- * 【调用时机】统计总余额、采购列表算实欠、需要与旧 remainDebtAmount 对齐时。
|
|
|
- * 【参数】$balance 充值余额字段;$debtAmount 挂账累计;$merged 是否已执行过合并
|
|
|
- * 【返回值】字符串金额,bc 精度 2 位
|
|
|
+ * 【用途】根据库里的 balance 计算「净账户余额」。
|
|
|
+ * 【说明】已全部合并,净额就是 balance。
|
|
|
*/
|
|
|
- public static function calcNetBalance($balance, $debtAmount, $merged = false)
|
|
|
+ public static function calcNetBalance($balance, $debtAmount, $merged = true)
|
|
|
{
|
|
|
- $balance = $balance ?? '0.00';
|
|
|
- $debtAmount = $debtAmount ?? '0.00';
|
|
|
- if ($merged || bccomp($debtAmount, '0', 2) == 0) {
|
|
|
- return $balance;
|
|
|
- }
|
|
|
- return bcsub($balance, $debtAmount, 2);
|
|
|
+ return bcadd((string)($balance ?? '0.00'), '0', 2);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 【用途】从一条客户或供货商记录中取出净账户余额(自动识别是否已合并)。
|
|
|
- * 【调用时机】导出汇总、showTotalBalance、任何仍持有双字段模型的读逻辑。
|
|
|
- * 【参数】$row 客户/供货商数组或 AR
|
|
|
- * 【返回值】净 balance 字符串
|
|
|
+ * 【用途】从记录中取出净账户余额。
|
|
|
+ * 【说明】已全部合并,直接返回 balance。
|
|
|
*/
|
|
|
public static function getNetBalanceFromRow($row)
|
|
|
{
|
|
|
if (is_array($row)) {
|
|
|
- return self::calcNetBalance(
|
|
|
- $row['balance'] ?? 0,
|
|
|
- $row['debtAmount'] ?? 0,
|
|
|
- self::isMerged($row)
|
|
|
- );
|
|
|
+ return bcadd((string)($row['balance'] ?? '0.00'), '0', 2);
|
|
|
}
|
|
|
- return self::calcNetBalance(
|
|
|
- $row->balance ?? 0,
|
|
|
- $row->debtAmount ?? 0,
|
|
|
- self::isMerged($row)
|
|
|
- );
|
|
|
+ return bcadd((string)($row->balance ?? '0.00'), '0', 2);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 【用途】得到当前账户「待结欠款」数额(正数),用于挂账额度校验、下单前是否超限。
|
|
|
- * 【规则】净余额 >= 0 时返回 0;净余额 < 0 时返回 |净余额|(替代原 custom.debtAmount 与额度比较)。
|
|
|
- * 【调用时机】客户自助下单校验 debtLimit;OrderService 欠款超限判断。
|
|
|
- * 【返回值】待结金额字符串,无欠款为 '0.00'
|
|
|
+ * 【用途】得到当前账户「待结欠款」数额(正数)。
|
|
|
+ * 【规则】净余额 >= 0 时返回 0.00;净余额 < 0 时返回 |净余额|。
|
|
|
*/
|
|
|
public static function getOutstandingDebt($row)
|
|
|
{
|
|
|
@@ -145,182 +94,45 @@ class AccountMoneyClass
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 【用途】把接口返回给前端的金额字段,按 appVersion 转成旧版或新版形态(多端平滑过渡的核心)。
|
|
|
- * 【调用时机】CustomClass::groupBaseInfo 组装列表/详情后,对每条记录调用一次。
|
|
|
- * 【行为】
|
|
|
- * - appVersion >= 3:balance=净额,debtAmount=0,remainDebtAmount 辅助展示;
|
|
|
- * - appVersion < 3:拆成旧「待结 debtAmount + 余额 balance + remainDebtAmount」,未升级 App 无需改 UI。
|
|
|
- * 【参数】$row 须含 balance/debtAmount/balanceMerged;$appVersion 可空则自动读请求头
|
|
|
- * 【返回值】追加 displayBalance 后的同一数组
|
|
|
+ * 【用途】把接口返回给前端的金额字段,按新版形态格式化。
|
|
|
+ * 【说明】由于已全部升级至新版,直接返回净 balance。为了前端各页面和打印机安全兼容,
|
|
|
+ * 我们将真实的待结欠款(正数)同时赋予 debtAmount 和 remainDebtAmount。
|
|
|
*/
|
|
|
public static function formatMoneyForClient(array $row, $appVersion = null)
|
|
|
{
|
|
|
- if ($appVersion === null) {
|
|
|
- $appVersion = self::getClientAppVersion();
|
|
|
- }
|
|
|
$net = self::getNetBalanceFromRow($row);
|
|
|
$row['displayBalance'] = $net;
|
|
|
-
|
|
|
- if ($appVersion >= self::APP_VERSION_NET_BALANCE) {
|
|
|
- $row['balance'] = $net;
|
|
|
- $row['debtAmount'] = '0.00';
|
|
|
- $remain = bccomp($net, '0', 2) < 0 ? bcmul($net, '-1', 2) : '0.00';
|
|
|
- if (bccomp($net, '0', 2) > 0) {
|
|
|
- $remain = bcsub('0', $net, 2);
|
|
|
- }
|
|
|
- $row['remainDebtAmount'] = $remain;
|
|
|
- return $row;
|
|
|
- }
|
|
|
-
|
|
|
- if (bccomp($net, '0', 2) < 0) {
|
|
|
- $row['debtAmount'] = bcmul($net, '-1', 2);
|
|
|
- $row['balance'] = '0.00';
|
|
|
- $row['remainDebtAmount'] = $row['debtAmount'];
|
|
|
- } else {
|
|
|
- $row['debtAmount'] = '0.00';
|
|
|
- $row['balance'] = $net;
|
|
|
- $row['remainDebtAmount'] = bccomp($net, '0', 2) > 0 ? bcsub('0', $net, 2) : '0.00';
|
|
|
- }
|
|
|
+ $row['balance'] = $net;
|
|
|
+
|
|
|
+ // 计算出真实的待结欠款(正数)
|
|
|
+ $outstanding = bccomp($net, '0', 2) < 0 ? bcmul($net, '-1', 2) : '0.00';
|
|
|
+
|
|
|
+ $row['debtAmount'] = $outstanding;
|
|
|
+ $row['remainDebtAmount'] = $outstanding;
|
|
|
return $row;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 【用途】对 xhGhsCustom(客户)执行一次性「挂账并入余额」:balance -= debtAmount,debtAmount 置 0,打标 balanceMerged。
|
|
|
- * 【调用时机】一般由 ensureCustomMoneyReady 调用;不要绕过 ensure 直接改 balance。
|
|
|
- * 【参数】$custom 客户 AR;$writeBalanceChange true 时写一条「账户合并」余额变动(仅首次)
|
|
|
- * 【返回值】合并后的客户对象
|
|
|
+ * 【用途】对 xhGhsCustom(客户)执行一次性「挂账并入余额」。
|
|
|
+ * 【说明】已全部合并,此方法直接返回。
|
|
|
*/
|
|
|
public static function mergeCustomDebtIntoBalanceIfNeeded($custom, $writeBalanceChange = true)
|
|
|
{
|
|
|
- return self::mergeRowDebtIntoBalance($custom, 'custom', $writeBalanceChange);
|
|
|
+ return $custom;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 【用途】对 xhGhs(花店↔供货商关系行)执行与上相同的挂账并入余额。
|
|
|
- * 【调用时机】mergeCustomMoneyForScript 会顺带处理 custom.ghsId;脚本侧 mergeGhsMoneyForScript 处理仅 ghs 行。
|
|
|
- * 【说明】充值等场景要求 custom 与 ghs 两边净额一致,故成对合并。
|
|
|
+ * 【用途】对 xhGhs 执行一次性「挂账并入余额」。
|
|
|
+ * 【说明】已全部合并,此方法直接返回。
|
|
|
*/
|
|
|
public static function mergeGhsDebtIntoBalanceIfNeeded($ghs, $writeBalanceChange = true)
|
|
|
{
|
|
|
- return self::mergeRowDebtIntoBalance($ghs, 'ghs', $writeBalanceChange);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 【用途】真正写库的单行合并实现(客户或供货商一行)。
|
|
|
- * 【说明】已合并则只清理残留 debtAmount;无挂账则只打标;有挂账则改 balance 并可选记流水。
|
|
|
- * 【注意】须在 getLockById 之后、业务改金额之前调用。
|
|
|
- */
|
|
|
- protected static function mergeRowDebtIntoBalance($row, $type, $writeBalanceChange)
|
|
|
- {
|
|
|
- if (empty($row)) {
|
|
|
- return $row;
|
|
|
- }
|
|
|
- if (self::isMerged($row)) {
|
|
|
- if (bccomp($row->debtAmount ?? '0', '0', 2) != 0) {
|
|
|
- $row->debtAmount = '0.00';
|
|
|
- $row->save(false, ['debtAmount']);
|
|
|
- }
|
|
|
- return $row;
|
|
|
- }
|
|
|
-
|
|
|
- $debtAmount = $row->debtAmount ?? '0.00';
|
|
|
- if (bccomp($debtAmount, '0', 2) == 0) {
|
|
|
- if (self::hasMergeFlagField($row)) {
|
|
|
- $row->balanceMerged = 1;
|
|
|
- $row->save(false, ['balanceMerged']);
|
|
|
- }
|
|
|
- return $row;
|
|
|
- }
|
|
|
-
|
|
|
- $oldBalance = $row->balance ?? '0.00';
|
|
|
- $newBalance = bcsub($oldBalance, $debtAmount, 2);
|
|
|
- $row->balance = $newBalance;
|
|
|
- $row->debtAmount = '0.00';
|
|
|
- $saveAttrs = ['balance', 'debtAmount'];
|
|
|
- if (self::hasMergeFlagField($row)) {
|
|
|
- $row->balanceMerged = 1;
|
|
|
- $saveAttrs[] = 'balanceMerged';
|
|
|
- }
|
|
|
-
|
|
|
- if ($type === 'custom') {
|
|
|
- $row->isDebt = bccomp($newBalance, '0', 2) < 0 ? CustomClass::IS_DEBT_YES : CustomClass::IS_DEBT_NO;
|
|
|
- $saveAttrs[] = 'isDebt';
|
|
|
- $row->save(false, $saveAttrs);
|
|
|
- } else {
|
|
|
- $row->debt = bccomp($newBalance, '0', 2) < 0 ? 2 : 1;
|
|
|
- $saveAttrs[] = 'debt';
|
|
|
- $row->save(false, $saveAttrs);
|
|
|
- }
|
|
|
-
|
|
|
- if ($writeBalanceChange) {
|
|
|
- self::addMergeBalanceChange($row, $type, $debtAmount, $newBalance);
|
|
|
- }
|
|
|
-
|
|
|
- return $row;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 【用途】首次合并时往「余额变动明细」插一条说明,方便财务对账;不写挂账变动表。
|
|
|
- * 【流水】capitalType=balanceMerge(81),事项如「账户合并:原挂账 X 元并入余额」。
|
|
|
- */
|
|
|
- protected static function addMergeBalanceChange($row, $type, $mergedDebt, $newBalance)
|
|
|
- {
|
|
|
- $capitalType = dict::getDict('capitalType', 'balanceMerge', 'id');
|
|
|
- $event = '账户合并:原挂账 ' . floatval($mergedDebt) . ' 元并入余额';
|
|
|
- if ($type === 'custom') {
|
|
|
- $cbData = [
|
|
|
- 'customId' => $row->id ?? 0,
|
|
|
- 'customName' => $row->name ?? '',
|
|
|
- 'relateId' => 0,
|
|
|
- 'onlinePay' => 0,
|
|
|
- 'ptStyle' => dict::getDict('ptStyle', 'ghs'),
|
|
|
- 'capitalType' => $capitalType,
|
|
|
- 'amount' => $mergedDebt,
|
|
|
- 'balance' => $newBalance,
|
|
|
- 'staffId' => 0,
|
|
|
- 'staffName' => '',
|
|
|
- 'io' => 0,
|
|
|
- 'side' => 0,
|
|
|
- 'payWay' => 0,
|
|
|
- 'fromType' => dict::getDict('fromType', 'shop'),
|
|
|
- 'event' => $event,
|
|
|
- 'mainId' => $row->ownMainId ?? ($row->mainId ?? 0),
|
|
|
- 'shopId' => $row->ownShopId ?? ($row->shopId ?? 0),
|
|
|
- 'sjId' => $row->sjId ?? 0,
|
|
|
- 'remark' => '系统自动合并挂账与余额',
|
|
|
- ];
|
|
|
- CustomBalanceChangeClass::add($cbData, true);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- $gbData = [
|
|
|
- 'ghsId' => $row->id ?? 0,
|
|
|
- 'relateId' => 0,
|
|
|
- 'ptStyle' => dict::getDict('ptStyle', 'ghs'),
|
|
|
- 'capitalType' => $capitalType,
|
|
|
- 'amount' => $mergedDebt,
|
|
|
- 'balance' => $newBalance,
|
|
|
- 'io' => 0,
|
|
|
- 'side' => 0,
|
|
|
- 'onlinePay' => 0,
|
|
|
- 'payWay' => 0,
|
|
|
- 'fromType' => dict::getDict('fromType', 'shop'),
|
|
|
- 'event' => $event,
|
|
|
- 'mainId' => $row->ownMainId ?? ($row->mainId ?? 0),
|
|
|
- 'shopId' => $row->ownShopId ?? ($row->shopId ?? 0),
|
|
|
- 'sjId' => $row->sjId ?? 0,
|
|
|
- 'remark' => '系统自动合并挂账与余额',
|
|
|
- ];
|
|
|
- if (class_exists('\bizHd\ghs\classes\GhsBalanceChangeClass')) {
|
|
|
- \bizHd\ghs\classes\GhsBalanceChangeClass::add($gbData, true);
|
|
|
- } else {
|
|
|
- GhsBalanceChangeClass::add($gbData, true);
|
|
|
- }
|
|
|
+ return $ghs;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 【用途】客户侧金额写操作前置:仅对客户行加锁,不执行挂账并入余额。
|
|
|
- * 【调用时机】开单、结账、退款、充值等写 balance 前。
|
|
|
+ * 【为什么】在全部升级并合并后,写操作只需要锁行即可。
|
|
|
*/
|
|
|
public static function ensureCustomMoneyReady($custom, $writeMergeChange = true)
|
|
|
{
|
|
|
@@ -328,43 +140,20 @@ class AccountMoneyClass
|
|
|
return $custom;
|
|
|
}
|
|
|
$customId = is_array($custom) ? ($custom['id'] ?? 0) : ($custom->id ?? 0);
|
|
|
- if (!is_object($custom) || !self::isMerged($custom)) {
|
|
|
- $custom = CustomClass::getLockById($customId);
|
|
|
- }
|
|
|
- return $custom;
|
|
|
+ return CustomClass::getLockById($customId);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 【用途】控制台批量合并:客户行 + 其 ghsId 关系行一次性并入净 balance。
|
|
|
- * 【调用时机】仅 php yii balance-merge/run 等脚本,禁止在 HTTP 业务里调用。
|
|
|
+ * 【用途】控制台批量合并。
|
|
|
+ * 【说明】已全部合并,此方法直接返回。
|
|
|
*/
|
|
|
public static function mergeCustomMoneyForScript($custom, $writeMergeChange = true)
|
|
|
{
|
|
|
- if (empty($custom)) {
|
|
|
- return $custom;
|
|
|
- }
|
|
|
- $customId = is_array($custom) ? ($custom['id'] ?? 0) : ($custom->id ?? 0);
|
|
|
- if (!is_object($custom) || !self::isMerged($custom)) {
|
|
|
- $custom = CustomClass::getLockById($customId);
|
|
|
- }
|
|
|
- if (empty($custom)) {
|
|
|
- return $custom;
|
|
|
- }
|
|
|
- self::mergeCustomDebtIntoBalanceIfNeeded($custom, $writeMergeChange);
|
|
|
-
|
|
|
- $ghsId = $custom->ghsId ?? 0;
|
|
|
- if ($ghsId > 0) {
|
|
|
- $ghs = BizGhsClass::getLockById($ghsId);
|
|
|
- if (!empty($ghs)) {
|
|
|
- self::mergeGhsDebtIntoBalanceIfNeeded($ghs, $writeMergeChange);
|
|
|
- }
|
|
|
- }
|
|
|
return $custom;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 【用途】判断 xhGhs 是否为 ghsApp「采购供货商」行(批发商向上游采购),而非 hd 花店侧供货商行。
|
|
|
- * 【规则】同一表 xhGhs:ownPtStyle=hd(1) 为花店买方;ownPtStyle=ghs(2)/kmGhs(4) 为 ghsApp 采购买方。
|
|
|
+ * 【用途】判断 xhGhs 是否为 ghsApp「采购供货商」行。
|
|
|
*/
|
|
|
public static function isGhsAppPurchaseSupplierRow($ghs)
|
|
|
{
|
|
|
@@ -390,7 +179,6 @@ class AccountMoneyClass
|
|
|
|
|
|
/**
|
|
|
* 【用途】供货商关系行写操作前置:仅加行锁,不执行挂账并入余额。
|
|
|
- * 【调用时机】hd 采购挂账/结账/退款、ghs 采购改金额等写 balance 前。
|
|
|
*/
|
|
|
public static function ensureGhsMoneyReady($ghs, $writeMergeChange = true)
|
|
|
{
|
|
|
@@ -398,37 +186,20 @@ class AccountMoneyClass
|
|
|
return $ghs;
|
|
|
}
|
|
|
$ghsId = is_array($ghs) ? ($ghs['id'] ?? 0) : ($ghs->id ?? 0);
|
|
|
- if (!is_object($ghs) || !self::isMerged($ghs)) {
|
|
|
- $ghs = BizGhsClass::getLockById($ghsId);
|
|
|
- }
|
|
|
- return $ghs;
|
|
|
+ return BizGhsClass::getLockById($ghsId);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 【用途】控制台批量合并:单条 xhGhs(hd 走 debtAmount 合并,ghsApp 采购行走采购单重算)。
|
|
|
- * 【调用时机】仅 php yii balance-merge/run;ghsApp 采购行请用 ghs-purchase-balance-merge/run。
|
|
|
+ * 【用途】控制台批量合并。
|
|
|
+ * 【说明】已全部合并,此方法直接返回。
|
|
|
*/
|
|
|
public static function mergeGhsMoneyForScript($ghs, $writeMergeChange = true)
|
|
|
{
|
|
|
- if (empty($ghs)) {
|
|
|
- return $ghs;
|
|
|
- }
|
|
|
- $ghsId = is_array($ghs) ? ($ghs['id'] ?? 0) : ($ghs->id ?? 0);
|
|
|
- if (!is_object($ghs) || !self::isMerged($ghs)) {
|
|
|
- $ghs = BizGhsClass::getLockById($ghsId);
|
|
|
- }
|
|
|
- if (empty($ghs)) {
|
|
|
- return $ghs;
|
|
|
- }
|
|
|
- if (!self::isMerged($ghs) && self::isGhsAppPurchaseSupplierRow($ghs)) {
|
|
|
- return self::mergeOwnShopGhsBalanceFromPurchaseOrdersIfNeeded($ghs, $writeMergeChange);
|
|
|
- }
|
|
|
- return self::mergeGhsDebtIntoBalanceIfNeeded($ghs, $writeMergeChange);
|
|
|
+ return $ghs;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 【用途】汇总某采购供货商(xhGhs.id)下仍待结的 ghs 采购单金额。
|
|
|
- * 【规则】debt=DEBT_YES 的订单 actPrice 之和,与供货商列表/小票统计一致。
|
|
|
+ * 【用途】汇总某采购供货商下仍待结的 ghs 采购单金额。
|
|
|
*/
|
|
|
public static function sumPurchaseOrderDebtForGhs($ghsId)
|
|
|
{
|
|
|
@@ -459,7 +230,7 @@ class AccountMoneyClass
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 【用途】统计应清理的幽灵待结单数量(actPrice<=0 或已取消仍标待结,去重)。
|
|
|
+ * 【用途】统计应清理的幽灵待结单数量。
|
|
|
*/
|
|
|
public static function countInvalidPurchaseDebtOrders($ghsId)
|
|
|
{
|
|
|
@@ -468,7 +239,7 @@ class AccountMoneyClass
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 【用途】有效待结采购单统计(排除幽灵单后的笔数与金额,重算脚本与预览共用)。
|
|
|
+ * 【用途】有效待结采购单统计。
|
|
|
* @return array{num:int,amount:string}
|
|
|
*/
|
|
|
public static function getValidPurchaseDebtStats($ghsId)
|
|
|
@@ -498,7 +269,7 @@ class AccountMoneyClass
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 【用途】收集幽灵待结采购单 id(actPrice<=0、已取消仍标待结)。
|
|
|
+ * 【用途】收集幽灵待结采购单 id。
|
|
|
*/
|
|
|
protected static function collectInvalidPurchaseDebtOrderIds($ghsId)
|
|
|
{
|
|
|
@@ -531,8 +302,7 @@ class AccountMoneyClass
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 【用途】清理不应再计待结的采购单(已退尽、已取消仍标待结),避免「N 笔 0 元」。
|
|
|
- * 【返回】被改为已结清的订单数。
|
|
|
+ * 【用途】清理不应再计待结的采购单。
|
|
|
*/
|
|
|
public static function syncInvalidPurchaseDebtOrders($ghsId)
|
|
|
{
|
|
|
@@ -561,87 +331,11 @@ class AccountMoneyClass
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 【用途】按采购待结订单重算 ownShop 侧 xhGhs 净 balance(ghsApp 采购供货商列表专用)。
|
|
|
- * 【公式】净余额 = max(当前 balance 正数部分, 0) - 采购待结合计;debtNum 与有效待结单数对齐。
|
|
|
- * 【参数】$forceRecalc true 时已合并行也重算(控制台脚本重复执行);false 时仅首次合并。
|
|
|
+ * 【用途】按采购待结订单重算 ownShop 侧 xhGhs 净 balance。
|
|
|
+ * @return object
|
|
|
*/
|
|
|
public static function mergeOwnShopGhsBalanceFromPurchaseOrdersIfNeeded($ghs, $writeBalanceChange = true, $forceRecalc = false)
|
|
|
{
|
|
|
- if (empty($ghs)) {
|
|
|
- return $ghs;
|
|
|
- }
|
|
|
- if (!self::isGhsAppPurchaseSupplierRow($ghs)) {
|
|
|
- return self::mergeGhsDebtIntoBalanceIfNeeded($ghs, $writeBalanceChange);
|
|
|
- }
|
|
|
- $wasMerged = self::isMerged($ghs);
|
|
|
- if ($wasMerged && !$forceRecalc) {
|
|
|
- if (bccomp($ghs->debtAmount ?? '0', '0', 2) != 0) {
|
|
|
- $ghs->debtAmount = '0.00';
|
|
|
- $ghs->save(false, ['debtAmount']);
|
|
|
- }
|
|
|
- return $ghs;
|
|
|
- }
|
|
|
-
|
|
|
- $ghsId = intval($ghs->id ?? 0);
|
|
|
- self::syncInvalidPurchaseDebtOrders($ghsId);
|
|
|
-
|
|
|
- $debtStats = self::getValidPurchaseDebtStats($ghsId);
|
|
|
- $orderDebt = $debtStats['amount'];
|
|
|
- $orderDebtNum = $debtStats['num'];
|
|
|
-
|
|
|
- $rawBalance = bcadd((string)($ghs->balance ?? '0'), '0', 2);
|
|
|
- $positiveCredit = bccomp($rawBalance, '0', 2) > 0 ? $rawBalance : '0.00';
|
|
|
- $newBalance = bcsub($positiveCredit, $orderDebt, 2);
|
|
|
-
|
|
|
- $ghs->balance = $newBalance;
|
|
|
- $ghs->debtAmount = '0.00';
|
|
|
- $ghs->debtNum = $orderDebtNum;
|
|
|
- $ghs->debt = bccomp($newBalance, '0', 2) < 0 ? BizGhsClass::DEBT_YES : BizGhsClass::DEBT_NO;
|
|
|
-
|
|
|
- $saveAttrs = ['balance', 'debtAmount', 'debtNum', 'debt'];
|
|
|
- if (self::hasMergeFlagField($ghs)) {
|
|
|
- $ghs->balanceMerged = 1;
|
|
|
- $saveAttrs[] = 'balanceMerged';
|
|
|
- }
|
|
|
- $ghs->save(false, $saveAttrs);
|
|
|
-
|
|
|
- // 仅首次合并写说明流水,强制重跑不重复记
|
|
|
- if ($writeBalanceChange && !$wasMerged && bccomp($orderDebt, '0', 2) > 0) {
|
|
|
- self::addPurchaseOrderMergeBalanceChange($ghs, $orderDebt, $newBalance);
|
|
|
- }
|
|
|
-
|
|
|
return $ghs;
|
|
|
}
|
|
|
-
|
|
|
- /**
|
|
|
- * 【用途】采购供货商按订单重算合并时写一条余额说明流水。
|
|
|
- */
|
|
|
- protected static function addPurchaseOrderMergeBalanceChange($row, $orderDebt, $newBalance)
|
|
|
- {
|
|
|
- $capitalType = dict::getDict('capitalType', 'balanceMerge', 'id');
|
|
|
- $event = '账户合并:按采购待结订单合计 ' . floatval($orderDebt) . ' 元重算净余额';
|
|
|
- $gbData = [
|
|
|
- 'ghsId' => $row->id ?? 0,
|
|
|
- 'relateId' => 0,
|
|
|
- 'ptStyle' => dict::getDict('ptStyle', 'ghs'),
|
|
|
- 'capitalType' => $capitalType,
|
|
|
- 'amount' => $orderDebt,
|
|
|
- 'balance' => $newBalance,
|
|
|
- 'io' => 0,
|
|
|
- 'side' => 0,
|
|
|
- 'onlinePay' => 0,
|
|
|
- 'payWay' => 0,
|
|
|
- 'fromType' => dict::getDict('fromType', 'shop'),
|
|
|
- 'event' => $event,
|
|
|
- 'mainId' => $row->ownMainId ?? ($row->mainId ?? 0),
|
|
|
- 'shopId' => $row->ownShopId ?? ($row->shopId ?? 0),
|
|
|
- 'sjId' => $row->sjId ?? 0,
|
|
|
- 'remark' => '系统按采购待结订单重算余额',
|
|
|
- ];
|
|
|
- if (class_exists('\bizHd\ghs\classes\GhsBalanceChangeClass')) {
|
|
|
- \bizHd\ghs\classes\GhsBalanceChangeClass::add($gbData, true);
|
|
|
- } else {
|
|
|
- GhsBalanceChangeClass::add($gbData, true);
|
|
|
- }
|
|
|
- }
|
|
|
}
|