mirror of
https://github.com/crmeb/CRMEB.git
synced 2026-10-28 13:31:04 +00:00
fix(资金流水): 读取侧只展示现金渠道,交易类型下拉改由后端下发
- CapitalFlow 新增 searchCashOnlyAttr 搜索器:列表、导出、账单统计统一
whereNotIn('pay_type', ['', 'yue', 'admin']),历史遗留的站内结算流水不再展示,
与写入侧 PayServices::isCashChannel() 口径对齐。
- CapitalFlowServices::getList()/getFlowRecord() 注入 cash_only,trading_type
文案改为按值映射(不再依赖数组下标,历史下线类型回退「其他」)。
- 新增 type_options(全部/订单支付/订单退款/购买会员/线下收银)供前端下拉,
同时保留 status 全量文案兼容旧前端。
- 后台资金流水页:筛选改用 trading_type + typeOptions,支付方式直接取
pay_type_name,移除本地硬编码的支付方式表。
- 同步 .crmeb 售后文档的资金流水读取侧口径说明。
This commit is contained in:
parent
90b1877806
commit
aa82159d43
@ -72,7 +72,7 @@ AfterSaleServices::refund
|
||||
- Handler 中的资金/资源副作用一律经 `RefundEffectContextInterface::once()` 登记去重,禁止直接裸写。
|
||||
- 中台 `refund_status`(0 无 / 1 申请中 / 2 已退)由 Adapter `resolveRefundStatus` 推导,退款完成时 `syncStatus` 同步。
|
||||
|
||||
**资金流水(`eb_capital_flow`)只记真实资金进出**:判定统一入口为 `PayServices::isCashChannel()`(第三方在线渠道 + 线下支付;余额 `yue`、后台代付、0 元单一律 false)。`CapitalFlowServices::setFlow()` 内部已做拦截,退款链路在调用前还要排除 `refund_type=balance` / `refund_method=balance` 的站内结转,即「余额支付订单退款」「原路退款但改退余额」都不产生现金流出,不记流水。
|
||||
**资金流水(`eb_capital_flow`)只记真实资金进出**:判定统一入口为 `PayServices::isCashChannel()`(第三方在线渠道 + 线下支付;余额 `yue`、后台代付、0 元单一律 false)。`CapitalFlowServices::setFlow()` 内部已做拦截,退款链路在调用前还要排除 `refund_type=balance` / `refund_method=balance` 的站内结转,即「余额支付订单退款」「原路退款但改退余额」都不产生现金流出,不记流水。读取侧口径一致:`CapitalFlow::searchCashOnlyAttr` 在列表、导出、账单统计中统一排除 `pay_type` 为 `yue` / `admin` / 空的历史流水,保证后台资金流水页面只出现现金渠道记录。
|
||||
|
||||
> **现状说明**:`OrderRefundCreateAfter / OrderRefundRefuse / OrderRefundCancelAfter` 的模块监听器已注册但服务层触发点待接线(见 [订单生命周期·事件地图](order-lifecycle.md#三订单事件地图)),相关后置逻辑目前挂在 `AfterSaleServices` 内部回调(`lifecycle->afterApply/afterAudit`)。
|
||||
|
||||
|
||||
@ -59,4 +59,18 @@ class CapitalFlow extends BaseModel
|
||||
{
|
||||
if (!empty($value)) $query->whereIn('id', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 仅现金渠道搜索器
|
||||
* 资金流水只统计真实资金进出:余额支付(yue)、后台代付(admin)、0 元单(空) 属于站内结算,
|
||||
* 即使历史数据中存在也不在资金流水、账单中展示。
|
||||
* @param $query
|
||||
* @param $value
|
||||
*/
|
||||
public function searchCashOnlyAttr($query, $value)
|
||||
{
|
||||
if ($value) {
|
||||
$query->whereNotIn('pay_type', ['', 'yue', 'admin']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -128,12 +128,25 @@ class CapitalFlowServices extends BaseService
|
||||
{
|
||||
$export = $where['export'] ?? 0;
|
||||
unset($where['export']);
|
||||
// 资金流水只展示现金渠道:余额支付、后台代付、0 元单等站内结算即使有历史数据也不展示
|
||||
$where['cash_only'] = 1;
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$status = ['全部', '支付订单', '订单退款', '充值订单', '充值退款', '抽奖红包', '佣金提现', '购买会员', '线下收银'];
|
||||
// 全量类型文案(用于列表/导出展示,历史数据可能包含已下线的类型)
|
||||
$typeLabels = [0 => '全部', 1 => '订单支付', 2 => '订单退款', 3 => '充值订单', 4 => '充值退款', 5 => '抽奖红包', 6 => '佣金提现', 7 => '购买会员', 8 => '线下收银'];
|
||||
// 筛选下拉只保留资金流水页面实际使用的现金交易类型;value 与 trading_type 一一对应,不依赖数组下标
|
||||
$type_options = [
|
||||
['label' => '全部', 'value' => 0],
|
||||
['label' => '订单支付', 'value' => 1],
|
||||
['label' => '订单退款', 'value' => 2],
|
||||
['label' => '购买会员', 'value' => 7],
|
||||
['label' => '线下收银', 'value' => 8],
|
||||
];
|
||||
// 兼容旧前端:status 为下标即 trading_type 的全量类型列表;新前端改用 type_options
|
||||
$status = ['全部', '订单支付', '订单退款', '充值订单', '充值退款', '抽奖红包', '佣金提现', '购买会员', '线下收银'];
|
||||
$list = $this->dao->getList($where, $page, $limit);
|
||||
foreach ($list as &$item) {
|
||||
$item['add_time'] = date('Y-m-d H:i:s', $item['add_time']);
|
||||
$item['trading_type'] = $status[$item['trading_type']];
|
||||
$item['trading_type'] = $typeLabels[$item['trading_type']] ?? '其他';
|
||||
$item['pay_type_name'] = PayServices::getPayType()[$item['pay_type'] != 'routine' ? $item['pay_type'] : 'weixin'] ?? '其他方式';
|
||||
}
|
||||
$count = $this->dao->count($where);
|
||||
@ -143,7 +156,7 @@ class CapitalFlowServices extends BaseService
|
||||
$fileName = '账单导出' . date('YmdHis') . rand(1000, 9999);
|
||||
return compact('list', 'fileKey', 'header', 'fileName');
|
||||
} else {
|
||||
return compact('list', 'count', 'status');
|
||||
return compact('list', 'count', 'status', 'type_options');
|
||||
}
|
||||
}
|
||||
|
||||
@ -170,6 +183,8 @@ class CapitalFlowServices extends BaseService
|
||||
*/
|
||||
public function getFlowRecord($where)
|
||||
{
|
||||
// 账单统计与流水列表口径保持一致,只统计现金渠道
|
||||
$where['cash_only'] = 1;
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$data = $this->dao->getRecordList($where, $page, $limit);
|
||||
$i = 1;
|
||||
|
||||
@ -23,8 +23,8 @@
|
||||
></date-range-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="交易类型:">
|
||||
<el-select v-model="formValidate.status" @change="selChange" class="form_content_width">
|
||||
<el-option :label="item" :value="index" v-for="(item, index) in withdrawal" :key="index"></el-option>
|
||||
<el-select v-model="formValidate.trading_type" @change="selChange" class="form_content_width">
|
||||
<el-option :label="item.label" :value="item.value" v-for="item in typeOptions" :key="item.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="流水搜索:">
|
||||
@ -73,9 +73,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="支付方式" min-width="90">
|
||||
<template #default="scope">
|
||||
<div v-for="item in payment" :key="item.value">
|
||||
<span v-if="scope.row.pay_type == item.value"> {{ item.title }} </span>
|
||||
</div>
|
||||
<span>{{ scope.row.pay_type_name || '--' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" min-width="90">
|
||||
@ -129,29 +127,8 @@ const modals = ref(false);
|
||||
const total = ref(0);
|
||||
const loading = ref(false);
|
||||
const tabList = ref([]);
|
||||
const withdrawal = ref([]);
|
||||
const payment = [
|
||||
{
|
||||
title: '全部',
|
||||
value: '',
|
||||
},
|
||||
{
|
||||
title: '微信',
|
||||
value: 'weixin',
|
||||
},
|
||||
{
|
||||
title: '支付宝',
|
||||
value: 'alipay',
|
||||
},
|
||||
{
|
||||
title: '银行卡',
|
||||
value: 'bank',
|
||||
},
|
||||
{
|
||||
title: '线下支付',
|
||||
value: 'offline',
|
||||
},
|
||||
];
|
||||
// 交易类型筛选:后端返回 [{label, value}],value 直接对应 trading_type
|
||||
const typeOptions = ref([]);
|
||||
const formValidate = ref({
|
||||
trading_type: 0,
|
||||
time: '',
|
||||
@ -214,7 +191,10 @@ function getList() {
|
||||
let data = res.data;
|
||||
tabList.value = data.list;
|
||||
total.value = data.count;
|
||||
withdrawal.value = data.status;
|
||||
typeOptions.value =
|
||||
data.type_options && data.type_options.length
|
||||
? data.type_options
|
||||
: (data.status || []).map((label, value) => ({ label, value }));
|
||||
loading.value = false;
|
||||
})
|
||||
.catch((res) => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user