挂号退款加退款记录

This commit is contained in:
2025-11-17 10:59:22 +08:00
parent b886726ecc
commit 491d8f8930
8 changed files with 268 additions and 29 deletions

View File

@@ -267,6 +267,17 @@ public class OutpatientRegistrationAppServiceImpl implements IOutpatientRegistra
new HashSet<>(Arrays.asList("patient_name", "organization_name", "practitioner_name", "healthcare_name")), new HashSet<>(Arrays.asList("patient_name", "organization_name", "practitioner_name", "healthcare_name")),
request); request);
// 手动处理 statusEnum 参数(用于过滤退号记录)
String statusEnumParam = request.getParameter("statusEnum");
if (statusEnumParam != null && !statusEnumParam.isEmpty()) {
try {
Integer statusEnum = Integer.parseInt(statusEnumParam);
queryWrapper.eq("status_enum", statusEnum);
} catch (NumberFormatException e) {
// 忽略无效的参数值
}
}
IPage<CurrentDayEncounterDto> currentDayEncounter = outpatientRegistrationAppMapper.getCurrentDayEncounter( IPage<CurrentDayEncounterDto> currentDayEncounter = outpatientRegistrationAppMapper.getCurrentDayEncounter(
new Page<>(pageNo, pageSize), EncounterClass.AMB.getValue(), ParticipantType.ADMITTER.getCode(), new Page<>(pageNo, pageSize), EncounterClass.AMB.getValue(), ParticipantType.ADMITTER.getCode(),
queryWrapper, ChargeItemContext.REGISTER.getValue(), PaymentStatus.SUCCESS.getValue()); queryWrapper, ChargeItemContext.REGISTER.getValue(), PaymentStatus.SUCCESS.getValue());

View File

@@ -131,4 +131,40 @@ public class CurrentDayEncounterDto {
*/ */
private Date birthDate; private Date birthDate;
/**
* 退号日期/时间
*/
private Date returnDate;
/**
* 退号原因
*/
private String returnReason;
/**
* 退号操作人
*/
private String operatorName;
/**
* 退号操作工号
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long operatorId;
/**
* 退款金额
*/
private BigDecimal refundAmount;
/**
* 合同编码(费用性质代码)
*/
private String contractNo;
/**
* 退款方式(多个支付方式用逗号分隔)
*/
private String refundMethod;
} }

View File

@@ -597,7 +597,7 @@ public class PaymentRecServiceImpl implements IPaymentRecService {
// 全退 // 全退
String ybSettleIds = paymentReconciliation.getYbSettleIds(); String ybSettleIds = paymentReconciliation.getYbSettleIds();
PaymentReconciliation unPaymentReconciliation = normalUnCharge(paymentReconciliation, PaymentRecDetails, null); PaymentReconciliation unPaymentReconciliation = normalUnCharge(paymentReconciliation, PaymentRecDetails, null, null);
if (!StringUtils.isEmpty(ybSettleIds)) { if (!StringUtils.isEmpty(ybSettleIds)) {
// 医保结算信息 // 医保结算信息
List<String> ybSettleIdList = Arrays.asList(ybSettleIds.split(",")); List<String> ybSettleIdList = Arrays.asList(ybSettleIds.split(","));
@@ -734,7 +734,7 @@ public class PaymentRecServiceImpl implements IPaymentRecService {
} }
PaymentReconciliation unPaymentReconciliation = PaymentReconciliation unPaymentReconciliation =
normalUnCharge(paymentReconciliation, paymentRecDetails, cancelPaymentDto.getSetlId()); normalUnCharge(paymentReconciliation, paymentRecDetails, cancelPaymentDto.getSetlId(), cancelPaymentDto.getReason());
return R.ok(unPaymentReconciliation); return R.ok(unPaymentReconciliation);
} }
@@ -792,10 +792,12 @@ public class PaymentRecServiceImpl implements IPaymentRecService {
* *
* @param paymentReconciliation 付款实体 * @param paymentReconciliation 付款实体
* @param paymentRecDetails 付款详情 * @param paymentRecDetails 付款详情
* @param setlIds 医保结算ID
* @param reason 退号/退费原因
* @return 结果 * @return 结果
*/ */
private PaymentReconciliation normalUnCharge(PaymentReconciliation paymentReconciliation, private PaymentReconciliation normalUnCharge(PaymentReconciliation paymentReconciliation,
List<PaymentRecDetail> paymentRecDetails, String setlIds) { List<PaymentRecDetail> paymentRecDetails, String setlIds, String reason) {
// 获取原ID // 获取原ID
Long id = paymentReconciliation.getId(); Long id = paymentReconciliation.getId();
@@ -805,7 +807,8 @@ public class PaymentRecServiceImpl implements IPaymentRecService {
.setEntererId(SecurityUtils.getLoginUser().getPractitionerId()).setBillDate(new Date()) .setEntererId(SecurityUtils.getLoginUser().getPractitionerId()).setBillDate(new Date())
.setTenderedAmount(paymentReconciliation.getTenderedAmount().negate()) .setTenderedAmount(paymentReconciliation.getTenderedAmount().negate())
.setReturnedAmount(paymentReconciliation.getReturnedAmount().negate()) .setReturnedAmount(paymentReconciliation.getReturnedAmount().negate())
.setDisplayAmount(paymentReconciliation.getDisplayAmount().negate()); .setDisplayAmount(paymentReconciliation.getDisplayAmount().negate())
.setRefundReason(reason); // 保存退号/退费原因
if (setlIds != null) { if (setlIds != null) {
paymentReconciliation.setYbSettleIds(setlIds); paymentReconciliation.setYbSettleIds(setlIds);
} }
@@ -2232,7 +2235,7 @@ public class PaymentRecServiceImpl implements IPaymentRecService {
} }
// 全退 // 全退
PaymentReconciliation unPaymentReconciliation = normalUnCharge(paymentReconciliation, paymentRecDetails, null); PaymentReconciliation unPaymentReconciliation = normalUnCharge(paymentReconciliation, paymentRecDetails, null, null);
// 取医保结算数据 // 取医保结算数据
String ybSettleIds = paymentReconciliation.getYbSettleIds(); String ybSettleIds = paymentReconciliation.getYbSettleIds();

View File

@@ -62,7 +62,14 @@
T9.charge_item_ids, T9.charge_item_ids,
T9.payment_id, T9.payment_id,
T9.picture_url, T9.picture_url,
T9.birth_date T9.birth_date,
T9.return_date,
T9.return_reason,
T9.operator_name,
T9.operator_id,
T9.refund_amount,
T9.contract_no,
T9.refund_method
from ( from (
SELECT T1.tenant_id AS tenant_id, SELECT T1.tenant_id AS tenant_id,
T1.id AS encounter_id, T1.id AS encounter_id,
@@ -84,7 +91,15 @@
T13.charge_item_ids, T13.charge_item_ids,
T13.id AS payment_id, T13.id AS payment_id,
ai.picture_url AS picture_url, ai.picture_url AS picture_url,
T8.birth_date AS birth_date T8.birth_date AS birth_date,
-- 退号相关信息
T14.bill_date AS return_date,
T14.refund_reason AS return_reason,
T15."name" AS operator_name,
T14.enterer_id AS operator_id,
ABS(T14.display_amount) AS refund_amount,
T6.contract_no AS contract_no,
T16.refund_method AS refund_method
FROM adm_encounter AS T1 FROM adm_encounter AS T1
LEFT JOIN adm_organization AS T2 ON T1.organization_id = T2.ID AND T2.delete_flag = '0' LEFT JOIN adm_organization AS T2 ON T1.organization_id = T2.ID AND T2.delete_flag = '0'
LEFT JOIN adm_healthcare_service AS T3 ON T1.service_type_id = T3.ID AND T3.delete_flag = '0' LEFT JOIN adm_healthcare_service AS T3 ON T1.service_type_id = T3.ID AND T3.delete_flag = '0'
@@ -111,9 +126,35 @@
LEFT JOIN fin_payment_reconciliation T13 LEFT JOIN fin_payment_reconciliation T13
ON T10.id::TEXT = ANY(string_to_array(T13.charge_item_ids,',')) ON T10.id::TEXT = ANY(string_to_array(T13.charge_item_ids,','))
AND T13.delete_flag = '0' AND T13.delete_flag = '0'
AND T13.status_enum = ${paymentStatus} AND T13.status_enum = ${paymentStatus}
LEFT JOIN adm_invoice AS ai -- 关联退号记录当状态为退号时通过relation_id关联原支付记录
ON ai.reconciliation_id = T13.id AND ai.delete_flag = '0' LEFT JOIN fin_payment_reconciliation T14
ON T13.id = T14.relation_id
AND T14.delete_flag = '0'
AND T14.status_enum = 3
AND T14.payment_enum = 1
LEFT JOIN adm_practitioner AS T15 ON T15.ID = T14.enterer_id AND T15.delete_flag = '0'
-- 关联退号支付详情,获取退款方式(聚合多个支付方式)
LEFT JOIN (
SELECT reconciliation_id,
STRING_AGG(
CASE pay_enum
WHEN 220400 THEN '现金'
WHEN 220100 THEN '微信'
WHEN 220200 THEN '支付宝'
WHEN 220300 THEN '银联'
END,
','
ORDER BY pay_enum
) AS refund_method
FROM fin_payment_rec_detail
WHERE delete_flag = '0'
AND amount &lt; 0
AND pay_enum IN (220400, 220100, 220200, 220300)
GROUP BY reconciliation_id
) AS T16 ON T14.id = T16.reconciliation_id
LEFT JOIN adm_invoice AS ai
ON ai.reconciliation_id = T13.id AND ai.delete_flag = '0'
WHERE T1.delete_flag = '0' WHERE T1.delete_flag = '0'
AND T1.class_enum = #{classEnum} AND T1.class_enum = #{classEnum}
-- AND T1.create_time -- AND T1.create_time

View File

@@ -33,7 +33,10 @@ public class PractitionerServiceImpl extends ServiceImpl<PractitionerMapper, Pra
QueryWrapper<Practitioner> queryWrapper = new QueryWrapper<>(); QueryWrapper<Practitioner> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("user_id", userId); queryWrapper.eq("user_id", userId);
return baseMapper.selectOne(queryWrapper); queryWrapper.orderByDesc("create_time"); // 按创建时间倒序,取最新的一条
queryWrapper.last("LIMIT 1"); // 限制只返回一条
List<Practitioner> list = baseMapper.selectList(queryWrapper);
return list != null && !list.isEmpty() ? list.get(0) : null;
} }
/** /**

View File

@@ -4,6 +4,7 @@ import java.math.BigDecimal;
import java.util.Date; import java.util.Date;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import com.core.common.core.domain.HisBaseEntity; import com.core.common.core.domain.HisBaseEntity;
@@ -102,4 +103,8 @@ public class PaymentReconciliation extends HisBaseEntity {
/** 医保清算标志 */ /** 医保清算标志 */
private Integer ybClearFlag;//默认值0 未清算 private Integer ybClearFlag;//默认值0 未清算
/** 退号/退费原因 */
@TableField("refund_reason")
private String refundReason;
} }

View File

@@ -111,6 +111,8 @@
import { cancelRegister } from './outpatientregistration'; import { cancelRegister } from './outpatientregistration';
import { computed, watch, reactive, ref, getCurrentInstance } from 'vue'; import { computed, watch, reactive, ref, getCurrentInstance } from 'vue';
import { Delete } from '@element-plus/icons-vue'; import { Delete } from '@element-plus/icons-vue';
import useUserStore from '@/store/modules/user';
import { formatDateStr } from '@/utils/index';
// 获取费用性质文本 // 获取费用性质文本
const getFeeTypeText = computed(() => { const getFeeTypeText = computed(() => {
@@ -162,11 +164,16 @@ const props = defineProps({
contractName: { contractName: {
type: String, type: String,
default: '', // 新增:接收费用性质名称 default: '', // 新增:接收费用性质名称
},
registerInfo: {
type: Object,
default: () => ({}), // 原挂号记录信息
} }
}); });
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
const reason = ref(''); const reason = ref('');
const userStore = useUserStore();
const formData = reactive({ const formData = reactive({
totalAmount: 0, totalAmount: 0,
@@ -195,6 +202,17 @@ function submit() {
proxy.$modal.msgError('请输入正确的金额'); proxy.$modal.msgError('请输入正确的金额');
return; return;
} }
// 获取当前时间作为退号操作日期
const returnDate = formatDateStr(new Date(), 'YYYY-MM-DD HH:mm:ss');
// 获取当前用户信息作为操作工号
const operatorId = userStore.id || userStore.name || '';
const operatorName = userStore.name || userStore.nickName || '';
// 计算退款总金额
const refundAmount = formData.selfPay.reduce((sum, item) => sum + (Number(item.amount) || 0), 0);
cancelRegister({ cancelRegister({
paymentEnum: 0, paymentEnum: 0,
kindEnum: 1, kindEnum: 1,
@@ -206,6 +224,18 @@ function submit() {
reason: reason.value, reason: reason.value,
ybFlag: '1', ybFlag: '1',
eleFlag: '0', eleFlag: '0',
// 退号操作记录信息
returnDate: returnDate, // 退号操作日期
operatorId: operatorId, // 退号操作工号用户ID
operatorName: operatorName, // 退号操作人姓名
refundAmount: refundAmount, // 退款金额
// 原挂号信息
registerTime: props.registerInfo?.registerTime || '', // 原挂号时间
registerAmount: props.registerInfo?.totalPrice || props.totalAmount, // 原挂号金额
// 患者信息
patientName: props.registerInfo?.patientName || '', // 患者姓名
patientAge: props.registerInfo?.age || '', // 患者年龄
patientGender: props.registerInfo?.genderEnum_enumText || '', // 患者性别
// returnedAmount: parseFloat(returnedAmount.value), // returnedAmount: parseFloat(returnedAmount.value),
}).then((res) => { }).then((res) => {
if (res.code == 200) { if (res.code == 200) {

View File

@@ -341,7 +341,14 @@
<el-col :span="24" class="card-box"> <el-col :span="24" class="card-box">
<el-card> <el-card>
<template #header> <template #header>
<span style="vertical-align: middle">当日已挂号</span> <div style="display: flex; align-items: center; justify-content: space-between;">
<span style="vertical-align: middle">当日已挂号</span>
<el-radio-group v-model="queryType" @change="handleQueryTypeChange" size="small">
<el-radio-button label="all">全部</el-radio-button>
<el-radio-button label="normal">正常挂号</el-radio-button>
<el-radio-button label="returned">退号记录</el-radio-button>
</el-radio-group>
</div>
</template> </template>
<el-input <el-input
v-model="queryParams.searchKey" v-model="queryParams.searchKey"
@@ -501,24 +508,78 @@
<span>{{ parseTime(scope.row.registerTime) }}</span> <span>{{ parseTime(scope.row.registerTime) }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" key="registerTime" prop="registerTime"> <!-- 退号记录相关列 -->
<el-table-column
v-if="queryType === 'returned'"
label="退号日期/时间"
align="center"
key="returnDate"
prop="returnDate"
width="180"
>
<template #default="scope"> <template #default="scope">
<el-tooltip <span>{{ scope.row.returnDate ? parseTime(scope.row.returnDate) : '-' }}</span>
:content="getReturnTooltip(scope.row)" </template>
placement="top" </el-table-column>
:disabled="!getReturnTooltip(scope.row)" <el-table-column
> v-if="queryType === 'returned'"
<span> label="退号原因"
<el-button align="center"
link key="returnReason"
type="primary" prop="returnReason"
@click="handleReturn(scope.row)" width="200"
:disabled="scope.row.statusEnum != 1" :show-overflow-tooltip="true"
> >
退号 <template #default="scope">
</el-button> <span>{{ scope.row.returnReason || '-' }}</span>
</span> </template>
</el-tooltip> </el-table-column>
<el-table-column
v-if="queryType === 'returned'"
label="退号操作人"
align="center"
key="operatorName"
prop="operatorName"
width="120"
>
<template #default="scope">
<span>{{ scope.row.operatorName || '-' }}</span>
</template>
</el-table-column>
<el-table-column
v-if="queryType === 'returned'"
label="退号操作工号"
align="center"
key="operatorId"
prop="operatorId"
width="120"
>
<template #default="scope">
<span>{{ scope.row.operatorId || '-' }}</span>
</template>
</el-table-column>
<el-table-column
v-if="queryType === 'returned'"
label="退款金额"
align="center"
key="refundAmount"
prop="refundAmount"
width="120"
>
<template #default="scope">
<span>{{ scope.row.refundAmount ? scope.row.refundAmount.toFixed(2) + ' 元' : '-' }}</span>
</template>
</el-table-column>
<el-table-column
v-if="queryType === 'returned'"
label="退款方式"
align="center"
key="refundMethod"
prop="refundMethod"
width="150"
>
<template #default="scope">
<span>{{ scope.row.refundMethod || '-' }}</span>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@@ -571,6 +632,7 @@
:feeType="patientInfo.medfeePaymtdCode || ''" :feeType="patientInfo.medfeePaymtdCode || ''"
:contractName="patientInfo.contractName || ''" :contractName="patientInfo.contractName || ''"
:medfee_paymtd_code="medfee_paymtd_code" :medfee_paymtd_code="medfee_paymtd_code"
:registerInfo="registerInfo"
/> />
<ReprintDialog <ReprintDialog
:open="openReprintDialog" :open="openReprintDialog"
@@ -664,6 +726,8 @@ const chargeItemIdList = ref([]);
const chrgBchnoList = ref([]); const chrgBchnoList = ref([]);
const paymentId = ref(''); const paymentId = ref('');
const loadingText = ref(''); const loadingText = ref('');
const registerInfo = ref({}); // 原挂号记录信息
const queryType = ref('all'); // 查询类型all-全部, normal-正常挂号, returned-退号记录
// 使用 ref 定义查询所得用户信息数据 // 使用 ref 定义查询所得用户信息数据
const patientInfoList = ref(undefined); const patientInfoList = ref(undefined);
@@ -996,6 +1060,12 @@ function getList() {
loading.value = false; loading.value = false;
outpatientRegistrationList.value = res.data.records; outpatientRegistrationList.value = res.data.records;
total.value = res.data.total; total.value = res.data.total;
// 调试:查看返回的数据结构(仅退号记录查询时)
if (queryType.value === 'returned' && res.data.records && res.data.records.length > 0) {
console.log('退号记录数据结构:', res.data.records[0]);
console.log('所有字段:', Object.keys(res.data.records[0]));
}
}); });
} }
@@ -1077,11 +1147,39 @@ function handleClear() {
reset(); reset();
} }
/** 查询类型切换 */
function handleQueryTypeChange() {
queryParams.value.pageNo = 1;
// 根据查询类型设置状态筛选
if (queryType.value === 'returned') {
// 查询退号记录状态为6
queryParams.value.statusEnum = 6;
} else if (queryType.value === 'normal') {
// 查询正常挂号(排除退号状态)
queryParams.value.statusEnum = undefined; // 或者设置为非6的状态
// 如果需要排除退号,可以在后端处理,这里先不设置
} else {
// 查询全部
queryParams.value.statusEnum = undefined;
}
handleQuery();
}
/** 搜索按钮操作 */ /** 搜索按钮操作 */
function handleQuery() { function handleQuery() {
queryParams.value.pageNo = 1; queryParams.value.pageNo = 1;
queryParams.value.registerTimeSTime = dateRange.value[0] + ' 00:00:00'; queryParams.value.registerTimeSTime = dateRange.value[0] + ' 00:00:00';
queryParams.value.registerTimeETime = dateRange.value[1] + ' 23:59:59'; queryParams.value.registerTimeETime = dateRange.value[1] + ' 23:59:59';
// 根据查询类型设置状态筛选
if (queryType.value === 'returned') {
queryParams.value.statusEnum = 6; // 退号状态
} else if (queryType.value === 'normal') {
// 正常挂号不设置statusEnum或排除6
queryParams.value.statusEnum = undefined;
} else {
// 全部
queryParams.value.statusEnum = undefined;
}
getList(); getList();
} }
@@ -1226,6 +1324,18 @@ function handleReturn(row) {
patientInfo.value.medfeePaymtdCode = row.contractNo; // 使用挂号记录中的费用性质代码 patientInfo.value.medfeePaymtdCode = row.contractNo; // 使用挂号记录中的费用性质代码
patientInfo.value.contractName = row.contractName; // 保存费用性质名称用于显示 patientInfo.value.contractName = row.contractName; // 保存费用性质名称用于显示
// 保存完整的原挂号记录信息,用于退号记录
registerInfo.value = {
...row, // 保存完整的挂号记录
patientName: row.patientName,
age: row.age,
genderEnum_enumText: row.genderEnum_enumText,
registerTime: row.registerTime,
totalPrice: row.totalPrice,
encounterId: row.encounterId,
patientId: row.patientId,
};
console.log('退号费用性质:', row.contractNo, row.contractName); console.log('退号费用性质:', row.contractNo, row.contractName);
} }