|
|
@@ -680,7 +680,12 @@ class CustomClass extends BaseClass
|
|
|
'remark' => '',
|
|
|
];
|
|
|
BalanceChangeClass::add($change, true);
|
|
|
- return $customBalance;
|
|
|
+
|
|
|
+ // 返充入账后:优先结当前售后原单挂账,剩余再 FIFO(不再二次扣余额)
|
|
|
+ $balanceBefore = bcsub($customBalance, $amount, 2);
|
|
|
+ self::fifoClearAfterRefundCredit($custom, $hd, $refund, $amount, $balanceBefore, $order);
|
|
|
+ $custom = CustomClass::getById($custom->id ?? 0, true);
|
|
|
+ return bcadd((string)($custom->balance ?? $customBalance), '0', 2);
|
|
|
}
|
|
|
|
|
|
//欠款和余额支付的售后 ssh 20250803
|
|
|
@@ -691,6 +696,10 @@ class CustomClass extends BaseClass
|
|
|
if (empty($hd)) {
|
|
|
util::fail('花店信息缺失,编号5362');
|
|
|
}
|
|
|
+ // 入账前净余额,供结账单 payWay 判定
|
|
|
+ $balanceBefore = bcadd((string)($custom->balance ?? '0'), '0', 2);
|
|
|
+ // 原始支付方式:后面流水会改写成余额付,FIFO 判定要用原值
|
|
|
+ $originPayWay = intval($payWay);
|
|
|
$customBalance = bcadd($custom->balance, $amount, 2);
|
|
|
$custom->balance = $customBalance;
|
|
|
if ($custom->balance < 0) {
|
|
|
@@ -852,6 +861,137 @@ class CustomClass extends BaseClass
|
|
|
}
|
|
|
$order->save();
|
|
|
}
|
|
|
+
|
|
|
+ // 当天挂账售后已先减 remainDebtPrice,再 FIFO 优先本单会重复销账;仅隔天/返充类或余额付原路才消欠
|
|
|
+ $sameDay = intval($refund->sameDay ?? 1);
|
|
|
+ $debtPay = intval(dict::getDict('payWay', 'debtPay'));
|
|
|
+ $skipFifo = ($originPayWay === $debtPay && $sameDay === 1);
|
|
|
+ if (!$skipFifo) {
|
|
|
+ self::fifoClearAfterRefundCredit($custom, $hd, $refund, $amount, $balanceBefore, $order);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 售后返充/原路退余额后销挂账:优先当前售后原单 remainDebtPrice(可部分结),再按 id 升序 FIFO。
|
|
|
+ * 调用时机:余额已入账;本方法只用本次金额作资金池,不再扣 balance。
|
|
|
+ *
|
|
|
+ * @param object $custom 客户(已加锁)
|
|
|
+ * @param object $hd 花店账户
|
|
|
+ * @param object $refund 售后单
|
|
|
+ * @param string|float $amount 本次入账金额
|
|
|
+ * @param string|float $balanceBefore 入账前净余额
|
|
|
+ * @param object|null $order 售后关联销售单
|
|
|
+ */
|
|
|
+ protected static function fifoClearAfterRefundCredit($custom, $hd, $refund, $amount, $balanceBefore, $order = null)
|
|
|
+ {
|
|
|
+ $pool = bcadd((string)$amount, '0', 2);
|
|
|
+ if (bccomp($pool, '0', 2) <= 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ $customId = intval($custom->id ?? 0);
|
|
|
+ if ($customId <= 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ $preferOrderId = !empty($order) ? intval($order->id ?? 0) : intval($refund->orderId ?? 0);
|
|
|
+ $plan = self::planFifoClearByPool($customId, $pool, $preferOrderId);
|
|
|
+ if (empty($plan)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ $shopId = intval($refund->shopId ?? ($custom->shopId ?? 0));
|
|
|
+ $shop = $shopId > 0 ? ShopClass::getById($shopId, true) : null;
|
|
|
+ if (empty($shop)) {
|
|
|
+ // 无门店无法建结账单,跳过销账(余额已入账,不阻断售后)
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ $settleParams = [
|
|
|
+ 'staffId' => intval($refund->shopAdminId ?? 0),
|
|
|
+ 'staffName' => (string)($refund->shopAdminName ?? ''),
|
|
|
+ ];
|
|
|
+ $set = SettleClass::addSettle($plan, $shop, $custom, $hd, $settleParams);
|
|
|
+ if (!empty($set)) {
|
|
|
+ SettleClass::clearSettle($set);
|
|
|
+ }
|
|
|
+ // 刷新客户欠款标记(有未结挂账单则为欠款户)
|
|
|
+ $leftDebt = OrderClass::getAllByCondition(['customId' => $customId, 'debt' => 1], null, 'id', null, true);
|
|
|
+ $customFresh = self::getLockById($customId);
|
|
|
+ if (!empty($customFresh)) {
|
|
|
+ $customFresh->isDebt = !empty($leftDebt) ? 1 : 0;
|
|
|
+ $customFresh->save(false, ['isDebt']);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 销挂账分配:可选优先本单,剩余按订单 id 升序 FIFO。
|
|
|
+ * prefer 路径只用 remainDebtPrice,不用 actPrice 兜底,避免脏数据多销。
|
|
|
+ *
|
|
|
+ * @param int $customId
|
|
|
+ * @param string|float $poolAmount
|
|
|
+ * @param int $preferOrderId
|
|
|
+ * @return array<int, array{orderId:int, clearAmount:string, orderSn:string}>
|
|
|
+ */
|
|
|
+ protected static function planFifoClearByPool($customId, $poolAmount, $preferOrderId = 0)
|
|
|
+ {
|
|
|
+ $pool = bcadd((string)$poolAmount, '0', 2);
|
|
|
+ if (bccomp($pool, '0', 2) <= 0) {
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+ $orderList = OrderClass::getAllByCondition(['customId' => $customId, 'debt' => 1], 'id asc', '*', null, true);
|
|
|
+ if (empty($orderList)) {
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+
|
|
|
+ $plan = [];
|
|
|
+ $used = '0.00';
|
|
|
+ $preferOrderId = intval($preferOrderId);
|
|
|
+
|
|
|
+ // 1)售后原单仍挂账:先结本单(不够则部分结)
|
|
|
+ if ($preferOrderId > 0) {
|
|
|
+ foreach ($orderList as $ord) {
|
|
|
+ if (intval($ord->id ?? 0) !== $preferOrderId) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ $remain = bcadd((string)($ord->remainDebtPrice ?? '0'), '0', 2);
|
|
|
+ if (bccomp($remain, '0', 2) <= 0) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ $clearAmount = bccomp($remain, $pool, 2) <= 0 ? $remain : $pool;
|
|
|
+ $plan[] = [
|
|
|
+ 'orderId' => $preferOrderId,
|
|
|
+ 'clearAmount' => $clearAmount,
|
|
|
+ 'orderSn' => $ord->orderSn ?? '',
|
|
|
+ ];
|
|
|
+ $used = bcadd($used, $clearAmount, 2);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2)剩余金额 FIFO(跳过已优先处理的本单)
|
|
|
+ foreach ($orderList as $ord) {
|
|
|
+ $left = bcsub($pool, $used, 2);
|
|
|
+ if (bccomp($left, '0', 2) <= 0) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ $oid = intval($ord->id ?? 0);
|
|
|
+ if ($preferOrderId > 0 && $oid === $preferOrderId) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ $remain = bcadd((string)($ord->remainDebtPrice ?? '0'), '0', 2);
|
|
|
+ if (bccomp($remain, '0', 2) <= 0) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ $clearAmount = bccomp($remain, $left, 2) <= 0 ? $remain : $left;
|
|
|
+ $plan[] = [
|
|
|
+ 'orderId' => $oid,
|
|
|
+ 'clearAmount' => $clearAmount,
|
|
|
+ 'orderSn' => $ord->orderSn ?? '',
|
|
|
+ ];
|
|
|
+ $used = bcadd($used, $clearAmount, 2);
|
|
|
+ }
|
|
|
+
|
|
|
+ return $plan;
|
|
|
}
|
|
|
|
|
|
//添加客户 ssh 2021.2.28
|