Compare commits
12 Commits
8a863b4ecb
...
5b0acede89
| Author | SHA1 | Date | |
|---|---|---|---|
| 5b0acede89 | |||
| ac1cd3afc8 | |||
| 6694ae52ba | |||
| 9491ceaa5d | |||
| db9a70a99d | |||
| b1d6c6008e | |||
| 6b9f9a107e | |||
| 11a7f49162 | |||
| b4e5061b73 | |||
| f5a1ad7f3f | |||
| eeac88b1d1 | |||
| 9f619ccdd4 |
@@ -570,13 +570,15 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
||||
// 耗材(前端adviceType=4,后端ItemType.DEVICE=2)
|
||||
List<AdviceSaveDto> deviceList = adviceSaveList.stream()
|
||||
.filter(e -> ItemType.DEVICE.getValue().equals(e.getAdviceType())
|
||||
|| e.getAdviceType() == 4) // 🔧 BugFix: 前端耗材类型值为4
|
||||
|| e.getAdviceType() == 4) // 前端耗材类型值为4
|
||||
.collect(Collectors.toList());
|
||||
// 诊疗活动(包括普通诊疗:前端adviceType=3,会诊:前端adviceType=5)
|
||||
|
||||
// 诊疗活动(前端adviceType=3诊疗、adviceType=5会诊、adviceType=6手术)
|
||||
List<AdviceSaveDto> activityList = adviceSaveList.stream()
|
||||
.filter(e -> ItemType.ACTIVITY.getValue().equals(e.getAdviceType())
|
||||
|| e.getAdviceType() == 3 // 🔧 BugFix: 前端诊疗类型值为3
|
||||
|| e.getAdviceType() == 5) // 🔧 BugFix: 前端会诊类型值为5
|
||||
|| e.getAdviceType() == 3 // 前端诊疗类型值为3
|
||||
|| e.getAdviceType() == 5 // 前端会诊类型值为5
|
||||
|| ItemType.SURGERY.getValue().equals(e.getAdviceType())) // 🔧 BugFix#318: 手术类型值为6
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 🔍 Debug日志: 记录分类结果
|
||||
@@ -605,11 +607,12 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
||||
iDeviceDispenseService.deleteDeviceDispense(adviceSaveDto.getRequestId());
|
||||
}
|
||||
|
||||
// 🔧 Bug Fix: 跳过耗材的库存校验(耗材的库存校验逻辑不同)
|
||||
// 🔧 Bug Fix: 跳过耗材、诊疗、手术的库存校验
|
||||
List<AdviceSaveDto> needCheckList = adviceSaveList.stream()
|
||||
.filter(e -> !DbOpType.DELETE.getCode().equals(e.getDbOpType())
|
||||
&& !ItemType.ACTIVITY.getValue().equals(e.getAdviceType())
|
||||
&& !ItemType.DEVICE.getValue().equals(e.getAdviceType())) // 排除耗材
|
||||
&& !ItemType.DEVICE.getValue().equals(e.getAdviceType())
|
||||
&& !ItemType.SURGERY.getValue().equals(e.getAdviceType())) // 🔧 BugFix#318: 排除手术类型
|
||||
.collect(Collectors.toList());
|
||||
// 校验库存
|
||||
String tipRes = adviceUtils.checkInventory(needCheckList);
|
||||
|
||||
@@ -161,6 +161,11 @@ public class RequestBaseDto {
|
||||
private String doseUnitCode;
|
||||
private String doseUnitCode_dictText;
|
||||
|
||||
/**
|
||||
* 单价
|
||||
*/
|
||||
private BigDecimal unitPrice;
|
||||
|
||||
/**
|
||||
* 总价
|
||||
*/
|
||||
@@ -215,4 +220,16 @@ public class RequestBaseDto {
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long basedOnId;
|
||||
|
||||
/**
|
||||
* 就诊id
|
||||
*/
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long encounterId;
|
||||
|
||||
/**
|
||||
* 患者id
|
||||
*/
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long patientId;
|
||||
|
||||
}
|
||||
|
||||
@@ -292,7 +292,7 @@ public class RequestFormManageAppServiceImpl implements IRequestFormManageAppSer
|
||||
surgeryChargeItem.setBusNo(AssignSeqEnum.CHARGE_ITEM_NO.getPrefix().concat(surgeryServiceRequest.getBusNo()));
|
||||
surgeryChargeItem.setGenerateSourceEnum(GenerateSource.DOCTOR_PRESCRIPTION.getValue());
|
||||
surgeryChargeItem.setPatientId(patientId);
|
||||
surgeryChargeItem.setContextEnum(3); // 3-诊疗
|
||||
surgeryChargeItem.setContextEnum(6); // 6-手术
|
||||
surgeryChargeItem.setEncounterId(encounterId);
|
||||
surgeryChargeItem.setEntererId(practitionerId);
|
||||
surgeryChargeItem.setEnteredDate(curDate);
|
||||
|
||||
@@ -471,6 +471,7 @@
|
||||
T1.dose AS dose,
|
||||
T1.dose_unit_code AS dose_unit_code,
|
||||
T4.id AS charge_item_id,
|
||||
T4.unit_price AS unit_price,
|
||||
T4.total_price AS total_price,
|
||||
T4.status_enum AS charge_status,
|
||||
al.id AS position_id,
|
||||
@@ -480,7 +481,9 @@
|
||||
ccd.name AS condition_definition_name,
|
||||
T1.sort_number AS sort_number,
|
||||
T1.based_on_id AS based_on_id,
|
||||
T1.category_enum AS category_enum
|
||||
T1.category_enum AS category_enum,
|
||||
T1.encounter_id AS encounter_id,
|
||||
T1.patient_id AS patient_id
|
||||
FROM med_medication_request AS T1
|
||||
LEFT JOIN med_medication_definition AS T2 ON T2.ID = T1.medication_id
|
||||
AND T2.delete_flag = '0'
|
||||
@@ -523,6 +526,7 @@
|
||||
NULL AS dose,
|
||||
'' AS dose_unit_code,
|
||||
T3.id AS charge_item_id,
|
||||
T3.unit_price AS unit_price,
|
||||
T3.total_price AS total_price,
|
||||
T3.status_enum AS charge_status,
|
||||
al.id AS position_id,
|
||||
@@ -532,7 +536,9 @@
|
||||
'' AS condition_definition_name,
|
||||
99 AS sort_number,
|
||||
T1.based_on_id AS based_on_id,
|
||||
T1.category_enum AS category_enum
|
||||
T1.category_enum AS category_enum,
|
||||
T1.encounter_id AS encounter_id,
|
||||
T1.patient_id AS patient_id
|
||||
FROM wor_device_request AS T1
|
||||
LEFT JOIN adm_device_definition AS T2 ON T2.ID = T1.device_def_id
|
||||
AND T2.delete_flag = '0'
|
||||
@@ -550,7 +556,7 @@
|
||||
AND T1.refund_device_id IS NULL
|
||||
ORDER BY T1.status_enum)
|
||||
UNION ALL
|
||||
(SELECT 3 AS advice_type,
|
||||
(SELECT CASE WHEN T1.category_enum = 4 THEN 6 ELSE COALESCE(T1.category_enum, 3) END AS advice_type,
|
||||
T1.id AS request_id,
|
||||
T1.id || '-3' AS unique_key,
|
||||
'' AS prescription_no,
|
||||
@@ -561,18 +567,19 @@
|
||||
null AS skin_test_flag,
|
||||
null AS inject_flag,
|
||||
null AS group_id,
|
||||
COALESCE(T2.NAME, CASE WHEN T1.content_json IS NOT NULL AND T1.content_json != '' THEN T1.content_json::json->>'adviceName' ELSE NULL END) AS advice_name,
|
||||
COALESCE(T2.NAME, T1.content_json::jsonb->>'surgeryName', T1.content_json::jsonb->>'adviceName') AS advice_name,
|
||||
'' AS volume,
|
||||
'' AS lot_number,
|
||||
T1.quantity AS quantity,
|
||||
T1.unit_code AS unit_code,
|
||||
T1.status_enum AS status_enum,
|
||||
'' AS method_code,
|
||||
'' AS rate_code,
|
||||
NULL AS dose,
|
||||
'' AS dose_unit_code,
|
||||
T3.id AS charge_item_id,
|
||||
T3.total_price AS total_price,
|
||||
T1.quantity AS quantity,
|
||||
T1.unit_code AS unit_code,
|
||||
T1.status_enum AS status_enum,
|
||||
'' AS method_code,
|
||||
'' AS rate_code,
|
||||
NULL AS dose,
|
||||
'' AS dose_unit_code,
|
||||
T3.id AS charge_item_id,
|
||||
T3.unit_price AS unit_price,
|
||||
T3.total_price AS total_price,
|
||||
T3.status_enum AS charge_status,
|
||||
ao.id AS position_id,
|
||||
ao.name AS position_name,
|
||||
@@ -580,9 +587,11 @@
|
||||
1 AS part_percent,
|
||||
'' AS condition_definition_name,
|
||||
99 AS sort_number,
|
||||
T1.based_on_id AS based_on_id,
|
||||
T1.category_enum AS category_enum
|
||||
FROM wor_service_request AS T1
|
||||
T1.based_on_id AS based_on_id,
|
||||
T1.category_enum AS category_enum,
|
||||
T1.encounter_id AS encounter_id,
|
||||
T1.patient_id AS patient_id
|
||||
FROM wor_service_request AS T1
|
||||
LEFT JOIN wor_activity_definition AS T2
|
||||
ON T2.ID = T1.activity_id
|
||||
AND T2.delete_flag = '0'
|
||||
|
||||
@@ -203,6 +203,7 @@
|
||||
T1.dose AS dose,
|
||||
T1.dose_unit_code AS dose_unit_code,
|
||||
T4.id AS charge_item_id,
|
||||
T4.unit_price AS unit_price,
|
||||
T4.total_price AS total_price,
|
||||
T4.status_enum AS charge_status,
|
||||
al.id AS position_id,
|
||||
@@ -254,6 +255,7 @@
|
||||
NULL AS dose,
|
||||
'' AS dose_unit_code,
|
||||
T3.id AS charge_item_id,
|
||||
T3.unit_price AS unit_price,
|
||||
T3.total_price AS total_price,
|
||||
T3.status_enum AS charge_status,
|
||||
al.id AS position_id,
|
||||
@@ -281,7 +283,7 @@
|
||||
AND T1.refund_device_id IS NULL
|
||||
ORDER BY T1.status_enum)
|
||||
UNION ALL
|
||||
(SELECT 3 AS advice_type,
|
||||
(SELECT CASE WHEN T1.category_enum = 4 THEN 6 ELSE COALESCE(T1.category_enum, 3) END AS advice_type,
|
||||
T1.id AS request_id,
|
||||
T1.id || '-3' AS unique_key,
|
||||
T1.requester_id AS requester_id,
|
||||
@@ -291,7 +293,7 @@
|
||||
null AS skin_test_flag,
|
||||
null AS inject_flag,
|
||||
null AS group_id,
|
||||
T2.NAME AS advice_name,
|
||||
COALESCE(T2.NAME, T1.content_json::jsonb->>'surgeryName') AS advice_name,
|
||||
'' AS volume,
|
||||
'' AS lot_number,
|
||||
T1.quantity AS quantity,
|
||||
@@ -302,6 +304,7 @@
|
||||
NULL AS dose,
|
||||
'' AS dose_unit_code,
|
||||
T3.id AS charge_item_id,
|
||||
T3.unit_price AS unit_price,
|
||||
T3.total_price AS total_price,
|
||||
T3.status_enum AS charge_status,
|
||||
ao.id AS position_id,
|
||||
@@ -309,7 +312,7 @@
|
||||
null AS dispense_per_duration,
|
||||
1 AS part_percent,
|
||||
'' AS condition_definition_name,
|
||||
T1.therapy_enum AS therapyEnum,
|
||||
COALESCE(T1.therapy_enum, 2) AS therapyEnum,
|
||||
99 AS sort_number,
|
||||
T1.based_on_id AS based_on_id
|
||||
FROM wor_service_request AS T1
|
||||
|
||||
@@ -26,12 +26,13 @@
|
||||
<select id="getRequestFormDetail" resultType="com.openhis.web.regdoctorstation.dto.RequestFormDetailQueryDto">
|
||||
SELECT wsr.quantity,
|
||||
wsr.unit_code,
|
||||
wad.NAME AS advice_name,
|
||||
COALESCE(wad.NAME, wsr.content_json::jsonb->>'surgeryName') AS advice_name,
|
||||
aci.total_price
|
||||
FROM wor_service_request AS wsr
|
||||
LEFT JOIN wor_activity_definition AS wad ON wad.ID = wsr.activity_id
|
||||
AND wad.delete_flag = '0'
|
||||
LEFT JOIN adm_charge_item AS aci ON aci.service_id = wsr.ID
|
||||
AND aci.service_table = 'wor_service_request'
|
||||
AND aci.delete_flag = '0'
|
||||
WHERE wsr.delete_flag = '0'
|
||||
AND wsr.prescription_no = #{prescriptionNo}
|
||||
|
||||
@@ -23,14 +23,19 @@ public enum ItemType implements HisEnumInterface {
|
||||
MEDICINE(1, "1", "药品"),
|
||||
|
||||
/**
|
||||
* 耗材
|
||||
* 医疗活动
|
||||
*/
|
||||
ACTIVITY(3, "3", "医疗活动"),
|
||||
|
||||
/**
|
||||
* 耗材(前端使用值2)
|
||||
*/
|
||||
DEVICE(2, "2", "耗材"),
|
||||
|
||||
/**
|
||||
* 医疗活动
|
||||
* 手术(前端使用值6,避免与耗材冲突)
|
||||
*/
|
||||
ACTIVITY(3, "3", "医疗活动");
|
||||
SURGERY(6, "6", "手术");
|
||||
|
||||
@EnumValue
|
||||
private Integer value;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Fix lodash.template assignWith issue - Manual fix script
|
||||
* Run this after npm/yarn install and before build
|
||||
@@ -18,34 +17,35 @@ if (!fs.existsSync(lodashTemplatePath)) {
|
||||
|
||||
let content = fs.readFileSync(lodashTemplatePath, 'utf8');
|
||||
|
||||
// Check if already patched
|
||||
if (content.includes('/* LODASH_TEMPLATE_PATCHED */')) {
|
||||
console.log('✓ lodash.template already patched');
|
||||
// Check if already patched with new version
|
||||
if (content.includes('/* LODASH_TEMPLATE_PATCHED_V2 */')) {
|
||||
console.log('✓ lodash.template already patched with v2');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Check if assignWith is actually missing
|
||||
if (content.includes('assignWith')) {
|
||||
// Check if it's used but not defined
|
||||
const hasFunctionDefinition = /function\s+assignWith|var\s+assignWith\s*=/.test(content);
|
||||
if (hasFunctionDefinition) {
|
||||
console.log('✓ assignWith is already defined in lodash.template');
|
||||
process.exit(0);
|
||||
}
|
||||
// Remove old patch if exists
|
||||
if (content.includes('/* LODASH_TEMPLATE_PATCHED */')) {
|
||||
console.log('🔄 Removing old patch...');
|
||||
content = content.replace(/\/\* LODASH_TEMPLATE_PATCHED \*\/\n.*assignWith[\s\S]*?^\}/m, '');
|
||||
}
|
||||
|
||||
console.log('🔧 Patching lodash.template...');
|
||||
console.log('🔧 Patching lodash.template with v2...');
|
||||
|
||||
// Simple assignWith implementation
|
||||
const assignWithImpl = `/* LODASH_TEMPLATE_PATCHED */
|
||||
// assignWith polyfill for lodash.template
|
||||
// Correct assignWith implementation that handles undefined customizer
|
||||
const assignWithImpl = `/* LODASH_TEMPLATE_PATCHED_V2 */
|
||||
// assignWith polyfill for lodash.template - Fixed version
|
||||
function assignWith(object, source, customizer) {
|
||||
if (object == null) return object;
|
||||
if (typeof customizer !== 'function') {
|
||||
customizer = function(objValue, srcValue) {
|
||||
return srcValue;
|
||||
};
|
||||
}
|
||||
var props = Object.keys(Object(source));
|
||||
for (var i = 0; i < props.length; i++) {
|
||||
var key = props[i];
|
||||
var value = source[key];
|
||||
var assignedValue = customizer ? customizer(object[key], value, key, object, source) : value;
|
||||
var assignedValue = customizer(object[key], value, key, object, source);
|
||||
if (assignedValue !== undefined) {
|
||||
object[key] = assignedValue;
|
||||
}
|
||||
@@ -74,5 +74,5 @@ const after = content.substring(insertPos);
|
||||
content = before + '\n' + assignWithImpl + after;
|
||||
|
||||
fs.writeFileSync(lodashTemplatePath, content);
|
||||
console.log('✅ Successfully patched lodash.template with assignWith function');
|
||||
console.log('✅ Successfully patched lodash.template with assignWith function (v2)');
|
||||
console.log(' File:', lodashTemplatePath);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/bin/bash
|
||||
# Fix lodash.template assignWith issue for Linux/Mac servers
|
||||
# Fix lodash.template assignWith issue for Linux/Mac servers - V2
|
||||
# Run this script after npm/yarn install
|
||||
|
||||
LODGASH_TEMPLATE="node_modules/lodash.template/index.js"
|
||||
@@ -9,34 +9,43 @@ if [ ! -f "$LODGASH_TEMPLATE" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if already patched
|
||||
if grep -q "LODASH_TEMPLATE_PATCHED" "$LODGASH_TEMPLATE"; then
|
||||
echo "✓ lodash.template already patched"
|
||||
# Check if already patched with v2
|
||||
if grep -q "LODASH_TEMPLATE_PATCHED_V2" "$LODGASH_TEMPLATE"; then
|
||||
echo "✓ lodash.template already patched with v2"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "🔧 Patching lodash.template..."
|
||||
# Remove old patch if exists
|
||||
if grep -q "LODASH_TEMPLATE_PATCHED" "$LODGASH_TEMPLATE"; then
|
||||
echo "🔄 Removing old patch..."
|
||||
# Use sed to remove old patch (multi-line)
|
||||
sed -i '/\/\* LODASH_TEMPLATE_PATCHED \*\//,/^}$/d' "$LODGASH_TEMPLATE"
|
||||
fi
|
||||
|
||||
echo "🔧 Patching lodash.template with v2..."
|
||||
|
||||
# Create a temporary file with the patch
|
||||
PATCH=$(cat <<'EOF'
|
||||
/* LODASH_TEMPLATE_PATCHED */
|
||||
// assignWith polyfill for lodash.template
|
||||
PATCH='/* LODASH_TEMPLATE_PATCHED_V2 */
|
||||
// assignWith polyfill for lodash.template - Fixed version
|
||||
function assignWith(object, source, customizer) {
|
||||
if (object == null) return object;
|
||||
if (typeof customizer !== "function") {
|
||||
customizer = function(objValue, srcValue) {
|
||||
return srcValue;
|
||||
};
|
||||
}
|
||||
var props = Object.keys(Object(source));
|
||||
for (var i = 0; i < props.length; i++) {
|
||||
var key = props[i];
|
||||
var value = source[key];
|
||||
var assignedValue = customizer ? customizer(object[key], value, key, object, source) : value;
|
||||
var assignedValue = customizer(object[key], value, key, object, source);
|
||||
if (assignedValue !== undefined) {
|
||||
object[key] = assignedValue;
|
||||
}
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
EOF
|
||||
)
|
||||
'
|
||||
|
||||
# Insert after the first line (license comment)
|
||||
{
|
||||
@@ -45,4 +54,4 @@ EOF
|
||||
tail -n +2 "$LODGASH_TEMPLATE"
|
||||
} > "$LODGASH_TEMPLATE.tmp" && mv "$LODGASH_TEMPLATE.tmp" "$LODGASH_TEMPLATE"
|
||||
|
||||
echo "✅ Successfully patched lodash.template with assignWith function"
|
||||
echo "✅ Successfully patched lodash.template with assignWith function (v2)"
|
||||
|
||||
@@ -9,7 +9,10 @@
|
||||
"predev": "node utils/check.js dev && vdoing",
|
||||
"prebuild": "node utils/check.js build && vdoing",
|
||||
"updateTheme": "yarn remove vuepress-theme-vdoing && rm -rf node_modules && yarn && yarn add vuepress-theme-vdoing -D",
|
||||
"editFm": "node utils/editFrontmatter.js"
|
||||
"editFm": "node utils/editFrontmatter.js",
|
||||
"fix-lodash": "node fix-lodash-manual.js",
|
||||
"build:fixed": "npm run fix-lodash && npm run build",
|
||||
"build:win:fixed": "npm run fix-lodash && npm run build:win"
|
||||
},
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -23,6 +26,7 @@
|
||||
"inquirer": "^7.1.0",
|
||||
"json2yaml": "^1.1.0",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash.assignwith": "^4.2.0",
|
||||
"vuepress": "1.9.9",
|
||||
"vuepress-plugin-baidu-tongji": "^1.0.1",
|
||||
"vuepress-plugin-demo-block": "^0.7.2",
|
||||
@@ -33,5 +37,13 @@
|
||||
"vuepress-theme-vdoing": "^1.12.9",
|
||||
"yamljs": "^0.3.0"
|
||||
},
|
||||
"dependencies": {}
|
||||
"dependencies": {},
|
||||
"resolutions": {
|
||||
"lodash": "^4.17.21",
|
||||
"lodash.template": "^4.5.0"
|
||||
},
|
||||
"overrides": {
|
||||
"lodash": "^4.17.21",
|
||||
"lodash.template": "^4.5.0"
|
||||
}
|
||||
}
|
||||
@@ -571,7 +571,7 @@
|
||||
<script setup>
|
||||
import {getOrgTree, saveOrderGroup} from './api';
|
||||
import adviceBaseList from './adviceBaseList';
|
||||
import {getCurrentInstance, nextTick, watch} from 'vue';
|
||||
import {computed, getCurrentInstance, nextTick, ref, watch} from 'vue';
|
||||
import {calculateQuantityByDays, formatNumber} from '@/utils/his';
|
||||
|
||||
const emit = defineEmits(['selectDiagnosis']);
|
||||
@@ -620,31 +620,31 @@ const stockList = ref([]);
|
||||
const { proxy } = getCurrentInstance();
|
||||
const inputRefs = ref({}); // 存储输入框实例
|
||||
const requiredProps = ref([]); // 存储必填项 prop 顺序
|
||||
const { method_code, unit_code, rate_code, distribution_category_code } = proxy.useDict(
|
||||
const { method_code, unit_code, rate_code, distribution_category_code, drord_doctor_type } = proxy.useDict(
|
||||
'method_code',
|
||||
'unit_code',
|
||||
'rate_code',
|
||||
'distribution_category_code'
|
||||
'distribution_category_code',
|
||||
'drord_doctor_type'
|
||||
);
|
||||
|
||||
const adviceTypeList = ref([
|
||||
{
|
||||
label: '西药中成药',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: '耗材',
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: '诊疗',
|
||||
value: 3,
|
||||
},
|
||||
{
|
||||
label: '全部',
|
||||
value: undefined,
|
||||
},
|
||||
]);
|
||||
// 使用 drord_doctor_type 字典
|
||||
const adviceTypeList = computed(() => {
|
||||
if (drord_doctor_type.value && drord_doctor_type.value.length > 0) {
|
||||
const list = drord_doctor_type.value.map(item => ({
|
||||
label: item.label,
|
||||
value: parseInt(item.value) || item.value
|
||||
}));
|
||||
return [...list, { label: '全部', value: undefined }];
|
||||
}
|
||||
// 默认值
|
||||
return [
|
||||
{ label: '西药中成药', value: 1 },
|
||||
{ label: '耗材', value: 4 },
|
||||
{ label: '诊疗', value: 3 },
|
||||
{ label: '全部', value: undefined },
|
||||
];
|
||||
});
|
||||
onMounted(() => {
|
||||
document.addEventListener('keydown', escKeyListener);
|
||||
});
|
||||
|
||||
@@ -952,34 +952,26 @@ const { method_code, unit_code, rate_code, distribution_category_code, drord_doc
|
||||
'drord_doctor_type'
|
||||
);
|
||||
|
||||
// 删除硬编码的adviceTypeList,直接使用drord_doctor_type字典
|
||||
// drord_doctor_type: 1=西药, 2=中成药, 3=诊疗, 4=耗材, 5=会诊, 6=全部
|
||||
const adviceTypeList = ref([
|
||||
{
|
||||
label: '西药',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: '中成药',
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: '诊疗',
|
||||
value: 3,
|
||||
},
|
||||
{
|
||||
label: '耗材',
|
||||
value: 4,
|
||||
},
|
||||
{
|
||||
label: '会诊',
|
||||
value: 5,
|
||||
},
|
||||
{
|
||||
label: '全部',
|
||||
value: '',
|
||||
},
|
||||
]);
|
||||
// 使用 drord_doctor_type 字典,不再硬编码
|
||||
// drord_doctor_type: 1=西药, 2=中成药, 3=诊疗, 4=耗材, 5=会诊, 6=手术
|
||||
const adviceTypeList = computed(() => {
|
||||
// 如果字典已加载,使用字典数据;否则使用默认值
|
||||
if (drord_doctor_type.value && drord_doctor_type.value.length > 0) {
|
||||
return drord_doctor_type.value.map(item => ({
|
||||
label: item.label,
|
||||
value: parseInt(item.value) || item.value
|
||||
}));
|
||||
}
|
||||
// 默认返回值,确保页面正常显示
|
||||
return [
|
||||
{ label: '西药', value: 1 },
|
||||
{ label: '中成药', value: 2 },
|
||||
{ label: '诊疗', value: 3 },
|
||||
{ label: '耗材', value: 4 },
|
||||
{ label: '会诊', value: 5 },
|
||||
{ label: '手术', value: 6 },
|
||||
];
|
||||
});
|
||||
|
||||
// 根据类型值获取显示标签,避免非编辑态出现空标签
|
||||
const mapAdviceTypeLabel = (type) => {
|
||||
@@ -2386,6 +2378,8 @@ function handleSave(prescriptionId) {
|
||||
saveAdviceType = 1; // 中成药:前端2 -> 后端1
|
||||
} else if (item.adviceType == 5) {
|
||||
saveAdviceType = 3; // 会诊:前端5 -> 后端3(诊疗类)
|
||||
} else if (item.adviceType == 6) {
|
||||
saveAdviceType = 6; // 🔧 BugFix#318: 手术类型保持为6
|
||||
}
|
||||
|
||||
// 🔧 Bug Fix: Validate and fix NaN values before sending to backend
|
||||
@@ -2395,6 +2389,21 @@ function handleSave(prescriptionId) {
|
||||
console.warn('Fixed NaN totalPrice for item:', item.adviceName);
|
||||
}
|
||||
|
||||
// 🔧 BugFix#318: 从 parsedContent 提取标准医嘱字段,排除手术特有字段
|
||||
const standardFields = [
|
||||
'accountId', 'chargeItemId', 'conditionDefinitionId', 'conditionId',
|
||||
'contentJson', 'definitionDetailId', 'definitionId', 'diagnosisName',
|
||||
'dosageInstruction', 'effectiveOrgId', 'encounterDiagnosisId',
|
||||
'encounterId', 'lotNumber', 'patientId', 'practitionerId',
|
||||
'prescriptionNo', 'skinTestFlag', 'unitPrice', 'volume', 'ybClassEnum'
|
||||
];
|
||||
let filteredContent = {};
|
||||
standardFields.forEach(field => {
|
||||
if (parsedContent[field] !== undefined) {
|
||||
filteredContent[field] = parsedContent[field];
|
||||
}
|
||||
});
|
||||
|
||||
// 构造请求参数
|
||||
// 🔧 Bug Fix: 确保库存匹配成功的关键字段
|
||||
// 耗材使用 adm_device_definition 表
|
||||
@@ -2418,10 +2427,12 @@ function handleSave(prescriptionId) {
|
||||
});
|
||||
|
||||
return {
|
||||
...parsedContent,
|
||||
...filteredContent, // 🔧 BugFix#318: 使用过滤后的字段,排除手术特有字段
|
||||
adviceType: saveAdviceType, // 使用转换后的类型
|
||||
requestId: item.requestId,
|
||||
dbOpType: '1',
|
||||
dbOpType: item.requestId ? '2' : '1', // 🔧 BugFix: 根据requestId判断是新增还是修改
|
||||
encounterId: item.encounterId || props.patientInfo.encounterId, // 🔧 BugFix: 确保encounterId
|
||||
patientId: item.patientId || props.patientInfo.patientId, // 🔧 BugFix: 确保patientId
|
||||
groupId: item.groupId,
|
||||
uniqueKey: undefined,
|
||||
// 使用转换后的数量和单位
|
||||
@@ -2728,28 +2739,32 @@ function handleSaveSign(row, index, prescriptionId) {
|
||||
|
||||
formRef.validate((valid) => {
|
||||
if (valid) {
|
||||
if (row.adviceType != 2) {
|
||||
// 🔧 BugFix#318: 手术类型(adviceType=6)不需要检查绑定耗材/药品
|
||||
if (row.adviceType != 2 && row.adviceType != 6) {
|
||||
// 1:用法绑东西 2:诊疗绑东西
|
||||
let typeCode = row.adviceType == 1 ? '1' : '2';
|
||||
// 用法字典值/诊疗定义id
|
||||
let itemNo = row.adviceType == 1 ? row.methodCode : row.adviceDefinitionId;
|
||||
getBindDevice({ typeCode: typeCode, itemNo: itemNo }).then((res) => {
|
||||
if (res.data.length == 0) {
|
||||
return;
|
||||
}
|
||||
// 是否需要打开弹窗
|
||||
let openBindDialog = localStorage.getItem('doctor' + userStore.id);
|
||||
if (!JSON.parse(openBindDialog)) {
|
||||
proxy.$refs['orderBindInfoRef'].open(res.data);
|
||||
} else {
|
||||
// 如果弹窗不提示带出的项目,自动带出
|
||||
// 如果有未签发的项目,并且当前的项目没有带出过绑定项目,则自动带出
|
||||
if (!bindMethod.value[itemNo]) {
|
||||
handleOrderBindInfo(res.data, row.methodCode);
|
||||
bindMethod.value[itemNo] = true;
|
||||
// 🔧 确保 itemNo 有值才调用接口
|
||||
if (itemNo) {
|
||||
getBindDevice({ typeCode: typeCode, itemNo: itemNo }).then((res) => {
|
||||
if (res.data.length == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
// 是否需要打开弹窗
|
||||
let openBindDialog = localStorage.getItem('doctor' + userStore.id);
|
||||
if (!JSON.parse(openBindDialog)) {
|
||||
proxy.$refs['orderBindInfoRef'].open(res.data);
|
||||
} else {
|
||||
// 如果弹窗不提示带出的项目,自动带出
|
||||
// 如果有未签发的项目,并且当前的项目没有带出过绑定项目,则自动带出
|
||||
if (!bindMethod.value[itemNo]) {
|
||||
handleOrderBindInfo(res.data, row.methodCode);
|
||||
bindMethod.value[itemNo] = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
row.isEdit = false;
|
||||
isAdding.value = false;
|
||||
@@ -2771,15 +2786,20 @@ function handleSaveSign(row, index, prescriptionId) {
|
||||
|
||||
row.conditionId = conditionId.value;
|
||||
// 处理总量为小单位情况,需要把单价也保存成小单位的
|
||||
if (row.unitCodeList.find((item) => item.value == row.unitCode).type == 'unit') {
|
||||
if (row.adviceType != 3) {
|
||||
row.unitPrice = row.unitTempPrice;
|
||||
// 🔧 BugFix#318: 手术类型(adviceType=6)可能没有unitCodeList,需要判断
|
||||
if (row.unitCodeList && row.unitCodeList.length > 0) {
|
||||
const foundUnit = row.unitCodeList.find((item) => item.value == row.unitCode);
|
||||
if (foundUnit && foundUnit.type == 'unit') {
|
||||
if (row.adviceType != 3) {
|
||||
row.unitPrice = row.unitTempPrice;
|
||||
}
|
||||
} else {
|
||||
const minUnitItem = row.unitCodeList.find((item) => item.value == row.minUnitCode);
|
||||
if (minUnitItem) {
|
||||
row.unitCode_dictText = minUnitItem.label;
|
||||
}
|
||||
row.unitPrice = row.minUnitPrice;
|
||||
}
|
||||
} else {
|
||||
row.unitCode_dictText = row.unitCodeList.find(
|
||||
(item) => item.value == row.minUnitCode
|
||||
).label;
|
||||
row.unitPrice = row.minUnitPrice;
|
||||
}
|
||||
row.conditionDefinitionId = conditionDefinitionId.value;
|
||||
row.encounterDiagnosisId = encounterDiagnosisId.value;
|
||||
@@ -2962,8 +2982,27 @@ function handleSaveBatch(prescriptionId) {
|
||||
saveAdviceType = 1; // 中成药前端2 -> 后端1
|
||||
} else if (item.adviceType == 5) {
|
||||
saveAdviceType = 3; // 会诊前端5 -> 后端3(诊疗类)
|
||||
} else if (item.adviceType == 6) {
|
||||
saveAdviceType = 6; // 🔧 BugFix#318: 手术类型保持为6
|
||||
}
|
||||
|
||||
// 🔧 BugFix#318: 过滤掉手术特有字段,只保留标准医嘱字段
|
||||
const standardItemFields = [
|
||||
'adviceDefinitionId', 'adviceName', 'adviceTableName', 'adviceType',
|
||||
'basedOnId', 'chargeItemId', 'chargeStatus', 'conditionDefinitionId',
|
||||
'conditionId', 'contentJson', 'dose', 'doseUnitCode', 'encounterDiagnosisId',
|
||||
'encounterId', 'groupId', 'injectFlag', 'lotNumber', 'methodCode', 'partPercent',
|
||||
'patientId', 'positionId', 'positionName', 'prescriptionNo', 'quantity', 'rateCode',
|
||||
'requestId', 'skinTestFlag', 'sortNumber', 'statusEnum', 'totalPrice',
|
||||
'unitCode', 'unitPrice', 'volume', 'ybClassEnum'
|
||||
];
|
||||
let filteredItem = {};
|
||||
standardItemFields.forEach(field => {
|
||||
if (item[field] !== undefined) {
|
||||
filteredItem[field] = item[field];
|
||||
}
|
||||
});
|
||||
|
||||
// 构造 contentJson (保持前端UI原始数据)
|
||||
const itemToSave = {
|
||||
...item,
|
||||
@@ -3011,7 +3050,7 @@ function handleSaveBatch(prescriptionId) {
|
||||
});
|
||||
|
||||
return {
|
||||
...item,
|
||||
...filteredItem, // 🔧 BugFix#318: 使用过滤后的字段
|
||||
patientId: props.patientInfo.patientId,
|
||||
encounterId: props.patientInfo.encounterId,
|
||||
adviceType: saveAdviceType,
|
||||
|
||||
@@ -25,6 +25,15 @@
|
||||
>
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
|
||||
<!-- 手术单号 -->
|
||||
<el-table-column label="手术单号" align="center" width="150">
|
||||
<template #default="scope">
|
||||
<el-link type="primary" @click="handleView(scope.row)">
|
||||
{{ scope.row.surgeryNo || '-' }}
|
||||
</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 申请日期 -->
|
||||
<el-table-column label="申请日期" align="center" prop="createTime" width="180">
|
||||
<template #default="scope">
|
||||
@@ -32,9 +41,6 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 手术单号 -->
|
||||
<el-table-column label="手术单号" align="center" prop="surgeryNo" width="150" show-overflow-tooltip />
|
||||
|
||||
<!-- 患者姓名 -->
|
||||
<el-table-column label="患者姓名" align="center" prop="patientName" width="100" />
|
||||
|
||||
|
||||
@@ -26,10 +26,16 @@
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column label="手术单号" width="160" align="center">
|
||||
<template #default="scope">
|
||||
<el-link type="primary" @click="handleViewDetail(scope.row)">
|
||||
{{ scope.row.prescriptionNo || '-' }}
|
||||
</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="patientName" label="患者姓名" width="120" />
|
||||
<el-table-column prop="name" label="申请单名称" width="140" />
|
||||
<el-table-column prop="createTime" label="创建时间" width="160" />
|
||||
<el-table-column prop="prescriptionNo" label="处方号" width="140" />
|
||||
<el-table-column prop="requesterId_dictText" label="申请者" width="120" />
|
||||
<el-table-column label="操作" align="center" fixed="right">
|
||||
<template #default="scope">
|
||||
|
||||
@@ -371,7 +371,7 @@
|
||||
<div style="display: flex; align-items: center; margin-bottom: 16px; gap: 16px">
|
||||
<span style="font-size: 16px; font-weight: 600">
|
||||
{{ row.adviceName }}
|
||||
{{ row.unitPrice ? Number(row.unitPrice).toFixed(2) + '/次' : '-' + '元' }}
|
||||
{{ row.unitPrice ? ' -' + Number(row.unitPrice).toFixed(2) + '元' : ' -元' }}
|
||||
</span>
|
||||
<div class="form-group">
|
||||
<el-form-item
|
||||
|
||||
@@ -426,34 +426,35 @@ const inputRefs = ref({}); // 存储输入框实例
|
||||
const requiredProps = ref([]); // 存储必填项 prop 顺序
|
||||
const totalAmount = ref(0);
|
||||
const therapyEnum = ref('');
|
||||
const { method_code, unit_code, rate_code, distribution_category_code } = proxy.useDict(
|
||||
const { method_code, unit_code, rate_code, distribution_category_code, drord_doctor_type } = proxy.useDict(
|
||||
'method_code',
|
||||
'unit_code',
|
||||
'rate_code',
|
||||
'distribution_category_code'
|
||||
'distribution_category_code',
|
||||
'drord_doctor_type'
|
||||
);
|
||||
const openDrawer = ref(false);
|
||||
const orderClassCode = ref('');
|
||||
const orderStatus = ref('');
|
||||
// 医嘱类型
|
||||
const adviceTypeList = ref([
|
||||
{
|
||||
label: '西药中成药',
|
||||
value: 1,
|
||||
},
|
||||
// {
|
||||
// label: '耗材',
|
||||
// value: 2,
|
||||
// },
|
||||
{
|
||||
label: '诊疗',
|
||||
value: 3,
|
||||
},
|
||||
{
|
||||
label: '全部',
|
||||
value: '',
|
||||
},
|
||||
]);
|
||||
// 医嘱类型 - 使用 drord_doctor_type 字典
|
||||
const adviceTypeList = computed(() => {
|
||||
// 如果字典已加载,使用字典数据(过滤掉全部选项)
|
||||
if (drord_doctor_type.value && drord_doctor_type.value.length > 0) {
|
||||
const list = drord_doctor_type.value.map(item => ({
|
||||
label: item.label,
|
||||
value: parseInt(item.value) || item.value
|
||||
}));
|
||||
// 添加全部选项
|
||||
return [...list, { label: '全部', value: '' }];
|
||||
}
|
||||
// 默认返回值
|
||||
return [
|
||||
{ label: '西药中成药', value: 1 },
|
||||
{ label: '诊疗', value: 3 },
|
||||
{ label: '手术', value: 6 },
|
||||
{ label: '全部', value: '' },
|
||||
];
|
||||
});
|
||||
// 医嘱状态
|
||||
const statusOption = [
|
||||
{
|
||||
|
||||
@@ -250,12 +250,15 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {computed, onMounted, reactive, ref, watch} from 'vue';
|
||||
import {computed, getCurrentInstance, onMounted, reactive, ref, watch} from 'vue';
|
||||
import {ElMessage} from 'element-plus';
|
||||
import {formatDateStr} from '@/utils/index';
|
||||
import {getAdviceBaseInfo, getDiseaseTreatmentInitLoc, getOrgList} from './api.js';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const { drord_doctor_type } = proxy.useDict('drord_doctor_type');
|
||||
|
||||
// Props定义
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
@@ -280,11 +283,26 @@ const dialogVisible = computed({
|
||||
get: () => props.visible,
|
||||
set: (value) => emit('update:visible', value),
|
||||
});
|
||||
const adviceTypeList = ref([
|
||||
{ label: '耗材', value: 2 },
|
||||
{ label: '诊疗', value: 3 },
|
||||
{ label: '全部', value: '' },
|
||||
]);
|
||||
// 使用 drord_doctor_type 字典
|
||||
const adviceTypeList = computed(() => {
|
||||
if (drord_doctor_type.value && drord_doctor_type.value.length > 0) {
|
||||
// 只保留耗材(4)和诊疗(3)类型,并添加全部选项
|
||||
const filtered = drord_doctor_type.value.filter(item => {
|
||||
const val = parseInt(item.value);
|
||||
return val === 3 || val === 4;
|
||||
}).map(item => ({
|
||||
label: item.label,
|
||||
value: parseInt(item.value)
|
||||
}));
|
||||
return [...filtered, { label: '全部', value: '' }];
|
||||
}
|
||||
// 默认值
|
||||
return [
|
||||
{ label: '耗材', value: 4 },
|
||||
{ label: '诊疗', value: 3 },
|
||||
{ label: '全部', value: '' },
|
||||
];
|
||||
});
|
||||
const adviceType = ref('');
|
||||
const feeItemsList = ref([]);
|
||||
const executeTime = ref('');
|
||||
|
||||
351
scripts/repair_bug_318.py
Normal file
351
scripts/repair_bug_318.py
Normal file
@@ -0,0 +1,351 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Bug #318 历史数据修复脚本
|
||||
为已存在但未生成手术医嘱的手术申请单补齐数据
|
||||
"""
|
||||
|
||||
import psycopg2
|
||||
import json
|
||||
import random
|
||||
import string
|
||||
from datetime import datetime
|
||||
|
||||
# 数据库连接配置
|
||||
DB_CONFIG = {
|
||||
"host": "47.116.196.11",
|
||||
"port": 15432,
|
||||
"database": "postgresql",
|
||||
"user": "postgresql",
|
||||
"password": "postgresql", # 请根据实际情况修改
|
||||
}
|
||||
|
||||
|
||||
def generate_bus_no():
|
||||
"""生成4位随机bus_no"""
|
||||
return "".join(random.choices(string.digits, k=4))
|
||||
|
||||
|
||||
def check_repair_needed(conn):
|
||||
"""检查需要修复的记录数"""
|
||||
cursor = conn.cursor()
|
||||
sql = """
|
||||
SELECT COUNT(*)
|
||||
FROM doc_request_form rf
|
||||
LEFT JOIN wor_service_request sr ON sr.prescription_no = rf.prescription_no
|
||||
AND sr.delete_flag = '0'
|
||||
WHERE rf.type_code = 'PROCEDURE'
|
||||
AND rf.delete_flag = '0'
|
||||
AND sr.id IS NULL
|
||||
"""
|
||||
cursor.execute(sql)
|
||||
count = cursor.fetchone()[0]
|
||||
cursor.close()
|
||||
return count
|
||||
|
||||
|
||||
def get_repair_list(conn):
|
||||
"""获取需要修复的手术申请单列表"""
|
||||
cursor = conn.cursor()
|
||||
sql = """
|
||||
SELECT
|
||||
rf.id,
|
||||
rf.prescription_no,
|
||||
rf.encounter_id,
|
||||
rf.patient_id,
|
||||
rf.requester_id,
|
||||
rf.create_time,
|
||||
rf.org_id,
|
||||
rf.desc_json
|
||||
FROM doc_request_form rf
|
||||
LEFT JOIN wor_service_request sr ON sr.prescription_no = rf.prescription_no
|
||||
AND sr.delete_flag = '0'
|
||||
WHERE rf.type_code = 'PROCEDURE'
|
||||
AND rf.delete_flag = '0'
|
||||
AND sr.id IS NULL
|
||||
ORDER BY rf.create_time DESC
|
||||
"""
|
||||
cursor.execute(sql)
|
||||
results = cursor.fetchall()
|
||||
cursor.close()
|
||||
return results
|
||||
|
||||
|
||||
def parse_surgery_info(desc_json):
|
||||
"""解析手术信息"""
|
||||
if not desc_json:
|
||||
return {}
|
||||
try:
|
||||
if isinstance(desc_json, str):
|
||||
return json.loads(desc_json)
|
||||
return desc_json
|
||||
except:
|
||||
return {}
|
||||
|
||||
|
||||
def repair_service_request(conn, repair_list):
|
||||
"""修复手术医嘱(ServiceRequest)"""
|
||||
cursor = conn.cursor()
|
||||
|
||||
insert_sql = """
|
||||
INSERT INTO wor_service_request (
|
||||
bus_no, prescription_no, status_enum, generate_source_enum,
|
||||
therapy_enum, quantity, unit_code, category_enum,
|
||||
patient_id, requester_id, encounter_id, authored_time,
|
||||
org_id, content_json, delete_flag, create_time, create_by, tenant_id
|
||||
) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||
RETURNING id
|
||||
"""
|
||||
|
||||
new_requests = []
|
||||
for record in repair_list:
|
||||
(
|
||||
rf_id,
|
||||
prescription_no,
|
||||
encounter_id,
|
||||
patient_id,
|
||||
requester_id,
|
||||
create_time,
|
||||
org_id,
|
||||
desc_json,
|
||||
) = record
|
||||
|
||||
# 解析手术信息
|
||||
surgery_info = parse_surgery_info(desc_json)
|
||||
content_json = (
|
||||
json.dumps(surgery_info, ensure_ascii=False) if surgery_info else None
|
||||
)
|
||||
|
||||
# 生成bus_no
|
||||
bus_no = generate_bus_no()
|
||||
|
||||
# 插入ServiceRequest
|
||||
cursor.execute(
|
||||
insert_sql,
|
||||
(
|
||||
bus_no, # bus_no
|
||||
prescription_no, # prescription_no
|
||||
1, # status_enum: 1-待签发
|
||||
1, # generate_source_enum: 1-医生处方
|
||||
2, # therapy_enum: 2-临时医嘱
|
||||
1, # quantity
|
||||
"次", # unit_code
|
||||
4, # category_enum: 4-手术
|
||||
patient_id, # patient_id
|
||||
requester_id, # requester_id
|
||||
encounter_id, # encounter_id
|
||||
create_time, # authored_time
|
||||
org_id, # org_id
|
||||
content_json, # content_json
|
||||
"0", # delete_flag
|
||||
create_time, # create_time
|
||||
requester_id, # create_by
|
||||
1, # tenant_id
|
||||
),
|
||||
)
|
||||
|
||||
service_request_id = cursor.fetchone()[0]
|
||||
new_requests.append(
|
||||
{
|
||||
"service_request_id": service_request_id,
|
||||
"bus_no": bus_no,
|
||||
"prescription_no": prescription_no,
|
||||
"patient_id": patient_id,
|
||||
"encounter_id": encounter_id,
|
||||
"requester_id": requester_id,
|
||||
"create_time": create_time,
|
||||
"org_id": org_id,
|
||||
"surgery_info": surgery_info,
|
||||
}
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
cursor.close()
|
||||
return new_requests
|
||||
|
||||
|
||||
def repair_charge_items(conn, new_requests):
|
||||
"""修复收费项目(ChargeItem)"""
|
||||
cursor = conn.cursor()
|
||||
|
||||
insert_sql = """
|
||||
INSERT INTO adm_charge_item (
|
||||
bus_no, status_enum, generate_source_enum, patient_id,
|
||||
context_enum, encounter_id, enterer_id, entered_date,
|
||||
service_table, service_id, product_table, requesting_org_id,
|
||||
quantity_value, quantity_unit, unit_price, total_price,
|
||||
delete_flag, create_time, create_by, tenant_id
|
||||
) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||
"""
|
||||
|
||||
for req in new_requests:
|
||||
surgery_info = req["surgery_info"]
|
||||
|
||||
# 手术费用
|
||||
surgery_fee = 0
|
||||
if surgery_info and "surgeryFee" in surgery_info:
|
||||
try:
|
||||
surgery_fee = float(surgery_info["surgeryFee"])
|
||||
except:
|
||||
surgery_fee = 0
|
||||
|
||||
# 插入手术费用收费项目
|
||||
cursor.execute(
|
||||
insert_sql,
|
||||
(
|
||||
"CI" + req["bus_no"], # bus_no
|
||||
1, # status_enum: 1-草稿
|
||||
1, # generate_source_enum: 1-医生处方
|
||||
req["patient_id"], # patient_id
|
||||
3, # context_enum: 3-诊疗
|
||||
req["encounter_id"], # encounter_id
|
||||
req["requester_id"], # enterer_id
|
||||
req["create_time"], # entered_date
|
||||
"wor_service_request", # service_table
|
||||
req["service_request_id"], # service_id
|
||||
"wor_activity_definition", # product_table
|
||||
req["org_id"], # requesting_org_id
|
||||
1, # quantity_value
|
||||
"次", # quantity_unit
|
||||
surgery_fee, # unit_price
|
||||
surgery_fee, # total_price
|
||||
"0", # delete_flag
|
||||
req["create_time"], # create_time
|
||||
req["requester_id"], # create_by
|
||||
1, # tenant_id
|
||||
),
|
||||
)
|
||||
|
||||
# 麻醉费用(如果存在且大于0)
|
||||
anesthesia_fee = 0
|
||||
if surgery_info and "anesthesiaFee" in surgery_info:
|
||||
try:
|
||||
anesthesia_fee = float(surgery_info["anesthesiaFee"])
|
||||
except:
|
||||
anesthesia_fee = 0
|
||||
|
||||
if anesthesia_fee > 0:
|
||||
cursor.execute(
|
||||
insert_sql,
|
||||
(
|
||||
"CI" + req["bus_no"] + "_A", # bus_no
|
||||
1, # status_enum
|
||||
1, # generate_source_enum
|
||||
req["patient_id"], # patient_id
|
||||
3, # context_enum
|
||||
req["encounter_id"], # encounter_id
|
||||
req["requester_id"], # enterer_id
|
||||
req["create_time"], # entered_date
|
||||
"wor_service_request", # service_table
|
||||
req["service_request_id"], # service_id
|
||||
"wor_activity_definition", # product_table
|
||||
req["org_id"], # requesting_org_id
|
||||
1, # quantity_value
|
||||
"次", # quantity_unit
|
||||
anesthesia_fee, # unit_price
|
||||
anesthesia_fee, # total_price
|
||||
"0", # delete_flag
|
||||
req["create_time"], # create_time
|
||||
req["requester_id"], # create_by
|
||||
1, # tenant_id
|
||||
),
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
cursor.close()
|
||||
|
||||
|
||||
def verify_repair(conn):
|
||||
"""验证修复结果"""
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 统计手术医嘱数量
|
||||
cursor.execute("""
|
||||
SELECT COUNT(*)
|
||||
FROM wor_service_request
|
||||
WHERE category_enum = 4 AND delete_flag = '0'
|
||||
""")
|
||||
service_request_count = cursor.fetchone()[0]
|
||||
|
||||
# 统计收费项目数量
|
||||
cursor.execute("""
|
||||
SELECT COUNT(*)
|
||||
FROM adm_charge_item ci
|
||||
WHERE ci.service_table = 'wor_service_request'
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM wor_service_request sr
|
||||
WHERE sr.id = ci.service_id AND sr.category_enum = 4
|
||||
)
|
||||
""")
|
||||
charge_item_count = cursor.fetchone()[0]
|
||||
|
||||
cursor.close()
|
||||
return service_request_count, charge_item_count
|
||||
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
print("=" * 60)
|
||||
print("Bug #318 历史数据修复脚本")
|
||||
print("=" * 60)
|
||||
print()
|
||||
|
||||
try:
|
||||
# 连接数据库
|
||||
print("正在连接数据库...")
|
||||
conn = psycopg2.connect(**DB_CONFIG)
|
||||
print("✓ 数据库连接成功")
|
||||
print()
|
||||
|
||||
# 步骤1:检查需要修复的记录数
|
||||
print("步骤1: 检查需要修复的记录...")
|
||||
need_repair_count = check_repair_needed(conn)
|
||||
print(f"✓ 发现 {need_repair_count} 条需要修复的手术申请单")
|
||||
print()
|
||||
|
||||
if need_repair_count == 0:
|
||||
print("没有需要修复的数据,退出")
|
||||
return
|
||||
|
||||
# 步骤2:获取修复列表
|
||||
print("步骤2: 获取修复列表...")
|
||||
repair_list = get_repair_list(conn)
|
||||
print(f"✓ 获取到 {len(repair_list)} 条记录")
|
||||
print()
|
||||
|
||||
# 步骤3:修复ServiceRequest
|
||||
print("步骤3: 生成手术医嘱(ServiceRequest)...")
|
||||
new_requests = repair_service_request(conn, repair_list)
|
||||
print(f"✓ 成功生成 {len(new_requests)} 条手术医嘱")
|
||||
print()
|
||||
|
||||
# 步骤4:修复ChargeItem
|
||||
print("步骤4: 生成收费项目(ChargeItem)...")
|
||||
repair_charge_items(conn, new_requests)
|
||||
print(f"✓ 成功生成收费项目")
|
||||
print()
|
||||
|
||||
# 步骤5:验证修复结果
|
||||
print("步骤5: 验证修复结果...")
|
||||
service_count, charge_count = verify_repair(conn)
|
||||
print(f"✓ 当前手术医嘱总数: {service_count}")
|
||||
print(f"✓ 当前手术收费项目总数: {charge_count}")
|
||||
print()
|
||||
|
||||
print("=" * 60)
|
||||
print("✓ 修复完成!")
|
||||
print("=" * 60)
|
||||
|
||||
except Exception as e:
|
||||
print(f"✗ 错误: {e}")
|
||||
import traceback
|
||||
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
if "conn" in locals():
|
||||
conn.close()
|
||||
print("\n数据库连接已关闭")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
240
sql/bug_318_repair_execute.sql
Normal file
240
sql/bug_318_repair_execute.sql
Normal file
@@ -0,0 +1,240 @@
|
||||
-- ============================================================
|
||||
-- Bug #318 历史数据修复 - 简化版SQL脚本
|
||||
-- 为已存在但未生成手术医嘱的手术申请单补齐数据
|
||||
-- ============================================================
|
||||
-- 执行说明:
|
||||
-- 1. 在数据库管理工具中执行(如 DBeaver、pgAdmin)
|
||||
-- 2. 建议先执行查询部分确认数据
|
||||
-- 3. 备份数据库后再执行修复
|
||||
-- ============================================================
|
||||
|
||||
-- 步骤1: 查看需要修复的记录数
|
||||
-- ============================================================
|
||||
SELECT
|
||||
'需要修复的手术申请单数量' as 检查项,
|
||||
COUNT(*) as 数量
|
||||
FROM doc_request_form rf
|
||||
LEFT JOIN wor_service_request sr ON sr.prescription_no = rf.prescription_no
|
||||
AND sr.delete_flag = '0'
|
||||
WHERE rf.type_code = 'PROCEDURE'
|
||||
AND rf.delete_flag = '0'
|
||||
AND sr.id IS NULL;
|
||||
|
||||
-- 步骤2: 查看详细列表(可选)
|
||||
-- ============================================================
|
||||
/*
|
||||
SELECT
|
||||
rf.id as request_form_id,
|
||||
rf.prescription_no as 手术单号,
|
||||
rf.encounter_id as 就诊ID,
|
||||
rf.patient_id as 患者ID,
|
||||
rf.create_time as 申请时间
|
||||
FROM doc_request_form rf
|
||||
LEFT JOIN wor_service_request sr ON sr.prescription_no = rf.prescription_no
|
||||
AND sr.delete_flag = '0'
|
||||
WHERE rf.type_code = 'PROCEDURE'
|
||||
AND rf.delete_flag = '0'
|
||||
AND sr.id IS NULL
|
||||
ORDER BY rf.create_time DESC
|
||||
LIMIT 10;
|
||||
*/
|
||||
|
||||
-- 步骤3: 执行修复 - 生成手术医嘱(ServiceRequest)
|
||||
-- ============================================================
|
||||
-- ⚠️ 请在确认备份数据库后执行以下语句
|
||||
|
||||
INSERT INTO wor_service_request (
|
||||
bus_no,
|
||||
prescription_no,
|
||||
status_enum,
|
||||
generate_source_enum,
|
||||
therapy_enum,
|
||||
quantity,
|
||||
unit_code,
|
||||
category_enum,
|
||||
patient_id,
|
||||
requester_id,
|
||||
encounter_id,
|
||||
authored_time,
|
||||
org_id,
|
||||
content_json,
|
||||
delete_flag,
|
||||
create_time,
|
||||
create_by,
|
||||
tenant_id
|
||||
)
|
||||
SELECT
|
||||
LPAD(FLOOR(RANDOM() * 10000)::TEXT, 4, '0') as bus_no, -- 生成4位随机数
|
||||
rf.prescription_no,
|
||||
1 as status_enum, -- 1-待签发
|
||||
1 as generate_source_enum, -- 1-医生处方
|
||||
2 as therapy_enum, -- 2-临时医嘱
|
||||
1 as quantity,
|
||||
'次' as unit_code,
|
||||
4 as category_enum, -- 4-手术
|
||||
rf.patient_id,
|
||||
rf.requester_id,
|
||||
rf.encounter_id,
|
||||
rf.create_time as authored_time,
|
||||
rf.org_id,
|
||||
rf.desc_json as content_json, -- 存储手术详情
|
||||
'0' as delete_flag,
|
||||
rf.create_time,
|
||||
rf.requester_id as create_by,
|
||||
1 as tenant_id
|
||||
FROM doc_request_form rf
|
||||
LEFT JOIN wor_service_request sr ON sr.prescription_no = rf.prescription_no
|
||||
AND sr.delete_flag = '0'
|
||||
WHERE rf.type_code = 'PROCEDURE'
|
||||
AND rf.delete_flag = '0'
|
||||
AND sr.id IS NULL;
|
||||
|
||||
-- 步骤4: 查看生成的手术医嘱数量
|
||||
-- ============================================================
|
||||
SELECT
|
||||
'生成的手术医嘱数量' as 检查项,
|
||||
COUNT(*) as 数量
|
||||
FROM wor_service_request
|
||||
WHERE category_enum = 4
|
||||
AND delete_flag = '0'
|
||||
AND create_time > CURRENT_TIMESTAMP - INTERVAL '1 hour'; -- 最近1小时生成的
|
||||
|
||||
-- 步骤5: 生成手术收费项目(ChargeItem)
|
||||
-- ============================================================
|
||||
-- 先创建临时表存储新生成的ServiceRequest
|
||||
CREATE TEMPORARY TABLE temp_new_service_requests AS
|
||||
SELECT
|
||||
sr.id as service_request_id,
|
||||
sr.bus_no,
|
||||
sr.prescription_no,
|
||||
sr.patient_id,
|
||||
sr.encounter_id,
|
||||
sr.requester_id,
|
||||
sr.create_time,
|
||||
sr.org_id,
|
||||
sr.content_json
|
||||
FROM wor_service_request sr
|
||||
WHERE sr.category_enum = 4
|
||||
AND sr.delete_flag = '0'
|
||||
AND sr.create_time > CURRENT_TIMESTAMP - INTERVAL '1 hour'; -- 最近1小时生成的
|
||||
|
||||
-- 插入手术费用收费项目
|
||||
INSERT INTO adm_charge_item (
|
||||
bus_no,
|
||||
status_enum,
|
||||
generate_source_enum,
|
||||
patient_id,
|
||||
context_enum,
|
||||
encounter_id,
|
||||
enterer_id,
|
||||
entered_date,
|
||||
service_table,
|
||||
service_id,
|
||||
product_table,
|
||||
requesting_org_id,
|
||||
quantity_value,
|
||||
quantity_unit,
|
||||
unit_price,
|
||||
total_price,
|
||||
delete_flag,
|
||||
create_time,
|
||||
create_by,
|
||||
tenant_id
|
||||
)
|
||||
SELECT
|
||||
'CI' || t.bus_no as bus_no,
|
||||
1 as status_enum, -- 1-草稿
|
||||
1 as generate_source_enum, -- 1-医生处方
|
||||
t.patient_id,
|
||||
3 as context_enum, -- 3-诊疗
|
||||
t.encounter_id,
|
||||
t.requester_id as enterer_id,
|
||||
t.create_time as entered_date,
|
||||
'wor_service_request' as service_table,
|
||||
t.service_request_id as service_id,
|
||||
'wor_activity_definition' as product_table,
|
||||
t.org_id as requesting_org_id,
|
||||
1 as quantity_value,
|
||||
'次' as quantity_unit,
|
||||
COALESCE((t.content_json::jsonb->>'surgeryFee')::numeric, 0) as unit_price,
|
||||
COALESCE((t.content_json::jsonb->>'surgeryFee')::numeric, 0) as total_price,
|
||||
'0' as delete_flag,
|
||||
t.create_time,
|
||||
t.requester_id as create_by,
|
||||
1 as tenant_id
|
||||
FROM temp_new_service_requests t
|
||||
WHERE COALESCE((t.content_json::jsonb->>'surgeryFee')::numeric, 0) >= 0;
|
||||
|
||||
-- 插入麻醉费用收费项目(如果有麻醉费用)
|
||||
INSERT INTO adm_charge_item (
|
||||
bus_no,
|
||||
status_enum,
|
||||
generate_source_enum,
|
||||
patient_id,
|
||||
context_enum,
|
||||
encounter_id,
|
||||
enterer_id,
|
||||
entered_date,
|
||||
service_table,
|
||||
service_id,
|
||||
product_table,
|
||||
requesting_org_id,
|
||||
quantity_value,
|
||||
quantity_unit,
|
||||
unit_price,
|
||||
total_price,
|
||||
delete_flag,
|
||||
create_time,
|
||||
create_by,
|
||||
tenant_id
|
||||
)
|
||||
SELECT
|
||||
'CI' || t.bus_no || '_A' as bus_no,
|
||||
1 as status_enum,
|
||||
1 as generate_source_enum,
|
||||
t.patient_id,
|
||||
3 as context_enum,
|
||||
t.encounter_id,
|
||||
t.requester_id as enterer_id,
|
||||
t.create_time as entered_date,
|
||||
'wor_service_request' as service_table,
|
||||
t.service_request_id as service_id,
|
||||
'wor_activity_definition' as product_table,
|
||||
t.org_id as requesting_org_id,
|
||||
1 as quantity_value,
|
||||
'次' as quantity_unit,
|
||||
(t.content_json::jsonb->>'anesthesiaFee')::numeric as unit_price,
|
||||
(t.content_json::jsonb->>'anesthesiaFee')::numeric as total_price,
|
||||
'0' as delete_flag,
|
||||
t.create_time,
|
||||
t.requester_id as create_by,
|
||||
1 as tenant_id
|
||||
FROM temp_new_service_requests t
|
||||
WHERE t.content_json::jsonb->>'anesthesiaFee' IS NOT NULL
|
||||
AND (t.content_json::jsonb->>'anesthesiaFee')::numeric > 0;
|
||||
|
||||
-- 步骤6: 验证修复结果
|
||||
-- ============================================================
|
||||
SELECT
|
||||
'手术医嘱总数' as 检查项,
|
||||
COUNT(*) as 数量
|
||||
FROM wor_service_request
|
||||
WHERE category_enum = 4
|
||||
AND delete_flag = '0';
|
||||
|
||||
SELECT
|
||||
'手术收费项目总数' as 检查项,
|
||||
COUNT(*) as 数量
|
||||
FROM adm_charge_item ci
|
||||
WHERE ci.service_table = 'wor_service_request'
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM wor_service_request sr
|
||||
WHERE sr.id = ci.service_id AND sr.category_enum = 4
|
||||
);
|
||||
|
||||
-- 清理临时表
|
||||
DROP TABLE IF EXISTS temp_new_service_requests;
|
||||
|
||||
-- ============================================================
|
||||
-- ✓ 修复完成!
|
||||
-- ============================================================
|
||||
254
sql/bug_318_repair_historical_data.sql
Normal file
254
sql/bug_318_repair_historical_data.sql
Normal file
@@ -0,0 +1,254 @@
|
||||
-- ========================================================
|
||||
-- Bug #318 历史数据修复脚本
|
||||
-- 为已存在但未生成手术医嘱的手术申请单补齐数据
|
||||
-- ========================================================
|
||||
|
||||
-- 1. 查询所有未生成手术医嘱的手术申请单
|
||||
SELECT
|
||||
rf.id as request_form_id,
|
||||
rf.prescription_no,
|
||||
rf.encounter_id,
|
||||
rf.patient_id,
|
||||
rf.requester_id,
|
||||
rf.create_time,
|
||||
rf.desc_json
|
||||
FROM doc_request_form rf
|
||||
LEFT JOIN wor_service_request sr ON sr.prescription_no = rf.prescription_no
|
||||
AND sr.delete_flag = '0'
|
||||
WHERE rf.type_code = 'PROCEDURE' -- 手术申请单
|
||||
AND rf.delete_flag = '0'
|
||||
AND sr.id IS NULL -- 没有对应的手术医嘱
|
||||
ORDER BY rf.create_time DESC;
|
||||
|
||||
-- ========================================================
|
||||
-- 2. 修复脚本:为缺失的手术申请单生成手术医嘱
|
||||
-- ========================================================
|
||||
|
||||
-- 创建临时表存储需要修复的数据
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS temp_surgery_repair AS
|
||||
SELECT
|
||||
rf.id as request_form_id,
|
||||
rf.prescription_no,
|
||||
rf.encounter_id,
|
||||
rf.patient_id,
|
||||
rf.requester_id,
|
||||
rf.create_time,
|
||||
rf.desc_json,
|
||||
rf.org_id
|
||||
FROM doc_request_form rf
|
||||
LEFT JOIN wor_service_request sr ON sr.prescription_no = rf.prescription_no
|
||||
AND sr.delete_flag = '0'
|
||||
WHERE rf.type_code = 'PROCEDURE'
|
||||
AND rf.delete_flag = '0'
|
||||
AND sr.id IS NULL;
|
||||
|
||||
-- 查看需要修复的记录数
|
||||
SELECT COUNT(*) as need_repair_count FROM temp_surgery_repair;
|
||||
|
||||
-- ========================================================
|
||||
-- 3. 插入手术医嘱(ServiceRequest)
|
||||
-- ========================================================
|
||||
|
||||
INSERT INTO wor_service_request (
|
||||
id,
|
||||
bus_no,
|
||||
prescription_no,
|
||||
status_enum,
|
||||
generate_source_enum,
|
||||
therapy_enum,
|
||||
quantity,
|
||||
unit_code,
|
||||
category_enum,
|
||||
patient_id,
|
||||
requester_id,
|
||||
encounter_id,
|
||||
authored_time,
|
||||
org_id,
|
||||
content_json,
|
||||
delete_flag,
|
||||
create_time,
|
||||
create_by
|
||||
)
|
||||
SELECT
|
||||
nextval('wor_service_request_id_seq'), -- 使用序列生成ID
|
||||
LPAD(FLOOR(RANDOM() * 10000)::TEXT, 4, '0'), -- 生成4位随机bus_no
|
||||
prescription_no,
|
||||
1, -- status_enum: 1-待签发(DRAFT)
|
||||
1, -- generate_source_enum: 1-医生处方
|
||||
2, -- therapy_enum: 2-临时医嘱(TEMPORARY)
|
||||
1, -- quantity: 1
|
||||
'次', -- unit_code
|
||||
4, -- category_enum: 4-手术
|
||||
patient_id,
|
||||
requester_id,
|
||||
encounter_id,
|
||||
create_time,
|
||||
org_id,
|
||||
CASE
|
||||
WHEN desc_json IS NOT NULL AND desc_json != '' THEN desc_json
|
||||
ELSE NULL
|
||||
END, -- content_json: 存储手术详情
|
||||
'0', -- delete_flag
|
||||
create_time,
|
||||
requester_id
|
||||
FROM temp_surgery_repair;
|
||||
|
||||
-- ========================================================
|
||||
-- 4. 插入手术收费项目(ChargeItem)
|
||||
-- ========================================================
|
||||
|
||||
-- 首先创建临时表关联新生成的ServiceRequest
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS temp_new_service_request AS
|
||||
SELECT
|
||||
sr.id as service_request_id,
|
||||
sr.prescription_no,
|
||||
sr.patient_id,
|
||||
sr.encounter_id,
|
||||
sr.requester_id,
|
||||
sr.create_time,
|
||||
sr.org_id,
|
||||
sr.bus_no,
|
||||
t.desc_json
|
||||
FROM wor_service_request sr
|
||||
JOIN temp_surgery_repair t ON t.prescription_no = sr.prescription_no
|
||||
WHERE sr.category_enum = 4
|
||||
AND sr.delete_flag = '0'
|
||||
AND sr.create_time > NOW() - INTERVAL '1 hour'; -- 只取最近1小时新增的
|
||||
|
||||
-- 插入手术费用收费项目
|
||||
INSERT INTO adm_charge_item (
|
||||
id,
|
||||
bus_no,
|
||||
status_enum,
|
||||
generate_source_enum,
|
||||
patient_id,
|
||||
context_enum,
|
||||
encounter_id,
|
||||
enterer_id,
|
||||
entered_date,
|
||||
service_table,
|
||||
service_id,
|
||||
product_table,
|
||||
requesting_org_id,
|
||||
quantity_value,
|
||||
quantity_unit,
|
||||
unit_price,
|
||||
total_price,
|
||||
delete_flag,
|
||||
create_time,
|
||||
create_by
|
||||
)
|
||||
SELECT
|
||||
nextval('adm_charge_item_id_seq'),
|
||||
'CI' || bus_no,
|
||||
1, -- status_enum: 1-草稿(DRAFT)
|
||||
1, -- generate_source_enum: 1-医生处方
|
||||
patient_id,
|
||||
3, -- context_enum: 3-诊疗
|
||||
encounter_id,
|
||||
requester_id,
|
||||
create_time,
|
||||
'wor_service_request', -- service_table
|
||||
service_request_id, -- service_id
|
||||
'wor_activity_definition', -- product_table
|
||||
org_id,
|
||||
1, -- quantity_value
|
||||
'次', -- quantity_unit
|
||||
COALESCE(
|
||||
(desc_json::jsonb->>'surgeryFee')::numeric,
|
||||
0
|
||||
), -- unit_price: 从desc_json解析手术费用
|
||||
COALESCE(
|
||||
(desc_json::jsonb->>'surgeryFee')::numeric,
|
||||
0
|
||||
), -- total_price
|
||||
'0',
|
||||
create_time,
|
||||
requester_id
|
||||
FROM temp_new_service_request;
|
||||
|
||||
-- 插入麻醉费用收费项目(如果有麻醉费用)
|
||||
INSERT INTO adm_charge_item (
|
||||
id,
|
||||
bus_no,
|
||||
status_enum,
|
||||
generate_source_enum,
|
||||
patient_id,
|
||||
context_enum,
|
||||
encounter_id,
|
||||
enterer_id,
|
||||
entered_date,
|
||||
service_table,
|
||||
service_id,
|
||||
product_table,
|
||||
requesting_org_id,
|
||||
quantity_value,
|
||||
quantity_unit,
|
||||
unit_price,
|
||||
total_price,
|
||||
delete_flag,
|
||||
create_time,
|
||||
create_by
|
||||
)
|
||||
SELECT
|
||||
nextval('adm_charge_item_id_seq'),
|
||||
'CI' || bus_no || '_A',
|
||||
1,
|
||||
1,
|
||||
patient_id,
|
||||
3,
|
||||
encounter_id,
|
||||
requester_id,
|
||||
create_time,
|
||||
'wor_service_request',
|
||||
service_request_id,
|
||||
'wor_activity_definition',
|
||||
org_id,
|
||||
1,
|
||||
'次',
|
||||
(desc_json::jsonb->>'anesthesiaFee')::numeric,
|
||||
(desc_json::jsonb->>'anesthesiaFee')::numeric,
|
||||
'0',
|
||||
create_time,
|
||||
requester_id
|
||||
FROM temp_new_service_request
|
||||
WHERE desc_json::jsonb->>'anesthesiaFee' IS NOT NULL
|
||||
AND (desc_json::jsonb->>'anesthesiaFee')::numeric > 0;
|
||||
|
||||
-- ========================================================
|
||||
-- 5. 验证修复结果
|
||||
-- ========================================================
|
||||
|
||||
-- 查看修复后的手术医嘱数量
|
||||
SELECT
|
||||
'修复后的手术医嘱数量' as check_item,
|
||||
COUNT(*) as count
|
||||
FROM wor_service_request sr
|
||||
WHERE sr.category_enum = 4
|
||||
AND sr.delete_flag = '0'
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM doc_request_form rf
|
||||
WHERE rf.prescription_no = sr.prescription_no
|
||||
AND rf.type_code = 'PROCEDURE'
|
||||
);
|
||||
|
||||
-- 查看修复后的收费项目数量
|
||||
SELECT
|
||||
'修复后的手术收费项目数量' as check_item,
|
||||
COUNT(*) as count
|
||||
FROM adm_charge_item ci
|
||||
WHERE ci.service_table = 'wor_service_request'
|
||||
AND ci.delete_flag = '0'
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM wor_service_request sr
|
||||
WHERE sr.id = ci.service_id
|
||||
AND sr.category_enum = 4
|
||||
);
|
||||
|
||||
-- 清理临时表
|
||||
DROP TABLE IF EXISTS temp_surgery_repair;
|
||||
DROP TABLE IF EXISTS temp_new_service_request;
|
||||
|
||||
-- ========================================================
|
||||
-- 完成!
|
||||
-- ========================================================
|
||||
17
sql/bug_318_step1_check.sql
Normal file
17
sql/bug_318_step1_check.sql
Normal file
@@ -0,0 +1,17 @@
|
||||
-- Bug #318 历史数据修复 - 步骤1:查询需要修复的手术申请单
|
||||
-- 执行此SQL查看有多少手术申请单需要修复
|
||||
|
||||
SELECT
|
||||
rf.id as request_form_id,
|
||||
rf.prescription_no as 手术单号,
|
||||
rf.encounter_id as 就诊ID,
|
||||
rf.patient_id as 患者ID,
|
||||
rf.create_time as 申请时间,
|
||||
SUBSTRING(rf.desc_json::text, 1, 100) as 手术信息预览
|
||||
FROM doc_request_form rf
|
||||
LEFT JOIN wor_service_request sr ON sr.prescription_no = rf.prescription_no
|
||||
AND sr.delete_flag = '0'
|
||||
WHERE rf.type_code = 'PROCEDURE' -- 手术申请单
|
||||
AND rf.delete_flag = '0'
|
||||
AND sr.id IS NULL -- 没有对应的手术医嘱
|
||||
ORDER BY rf.create_time DESC;
|
||||
159
sql/bug_318_step2_repair.sql
Normal file
159
sql/bug_318_step2_repair.sql
Normal file
@@ -0,0 +1,159 @@
|
||||
-- Bug #318 历史数据修复 - 步骤2:执行修复
|
||||
-- ⚠️ 请在执行前备份数据库!
|
||||
|
||||
-- =====================================================
|
||||
-- 步骤 2.1: 创建临时表存储需要修复的手术申请单
|
||||
-- =====================================================
|
||||
|
||||
CREATE TEMPORARY TABLE temp_repair_list AS
|
||||
SELECT
|
||||
rf.id as request_form_id,
|
||||
rf.prescription_no,
|
||||
rf.encounter_id,
|
||||
rf.patient_id,
|
||||
rf.requester_id,
|
||||
rf.create_time,
|
||||
rf.org_id,
|
||||
rf.desc_json
|
||||
FROM doc_request_form rf
|
||||
LEFT JOIN wor_service_request sr ON sr.prescription_no = rf.prescription_no
|
||||
AND sr.delete_flag = '0'
|
||||
WHERE rf.type_code = 'PROCEDURE'
|
||||
AND rf.delete_flag = '0'
|
||||
AND sr.id IS NULL;
|
||||
|
||||
-- 查看需要修复的记录数
|
||||
SELECT COUNT(*) as 需要修复的记录数 FROM temp_repair_list;
|
||||
|
||||
-- =====================================================
|
||||
-- 步骤 2.2: 生成手术医嘱(ServiceRequest)
|
||||
-- =====================================================
|
||||
|
||||
INSERT INTO wor_service_request (
|
||||
bus_no,
|
||||
prescription_no,
|
||||
status_enum,
|
||||
generate_source_enum,
|
||||
therapy_enum,
|
||||
quantity,
|
||||
unit_code,
|
||||
category_enum,
|
||||
patient_id,
|
||||
requester_id,
|
||||
encounter_id,
|
||||
authored_time,
|
||||
org_id,
|
||||
content_json,
|
||||
delete_flag,
|
||||
create_time,
|
||||
create_by,
|
||||
tenant_id
|
||||
)
|
||||
SELECT
|
||||
LPAD(FLOOR(RANDOM() * 10000)::TEXT, 4, '0'),
|
||||
prescription_no,
|
||||
1, -- 待签发
|
||||
1, -- 医生处方
|
||||
2, -- 临时医嘱
|
||||
1,
|
||||
'次',
|
||||
4, -- 手术
|
||||
patient_id,
|
||||
requester_id,
|
||||
encounter_id,
|
||||
create_time,
|
||||
org_id,
|
||||
desc_json,
|
||||
'0',
|
||||
create_time,
|
||||
requester_id,
|
||||
1 -- tenant_id
|
||||
FROM temp_repair_list;
|
||||
|
||||
-- 查看生成的手术医嘱数量
|
||||
SELECT '生成的手术医嘱数量' as 检查项, COUNT(*) as 数量
|
||||
FROM wor_service_request
|
||||
WHERE prescription_no IN (SELECT prescription_no FROM temp_repair_list);
|
||||
|
||||
-- =====================================================
|
||||
-- 步骤 2.3: 生成手术收费项目(ChargeItem)
|
||||
-- =====================================================
|
||||
|
||||
-- 获取刚生成的ServiceRequest
|
||||
CREATE TEMPORARY TABLE temp_new_requests AS
|
||||
SELECT
|
||||
sr.id as service_request_id,
|
||||
sr.prescription_no,
|
||||
sr.patient_id,
|
||||
sr.encounter_id,
|
||||
sr.requester_id,
|
||||
sr.create_time,
|
||||
sr.org_id,
|
||||
sr.bus_no,
|
||||
t.desc_json
|
||||
FROM wor_service_request sr
|
||||
JOIN temp_repair_list t ON t.prescription_no = sr.prescription_no
|
||||
WHERE sr.category_enum = 4
|
||||
AND sr.delete_flag = '0';
|
||||
|
||||
-- 插入手术费用
|
||||
INSERT INTO adm_charge_item (
|
||||
bus_no,
|
||||
status_enum,
|
||||
generate_source_enum,
|
||||
patient_id,
|
||||
context_enum,
|
||||
encounter_id,
|
||||
enterer_id,
|
||||
entered_date,
|
||||
service_table,
|
||||
service_id,
|
||||
product_table,
|
||||
requesting_org_id,
|
||||
quantity_value,
|
||||
quantity_unit,
|
||||
unit_price,
|
||||
total_price,
|
||||
delete_flag,
|
||||
create_time,
|
||||
create_by,
|
||||
tenant_id
|
||||
)
|
||||
SELECT
|
||||
'CI' || bus_no,
|
||||
1, -- 草稿
|
||||
1, -- 医生处方
|
||||
patient_id,
|
||||
3, -- 诊疗
|
||||
encounter_id,
|
||||
requester_id,
|
||||
create_time,
|
||||
'wor_service_request',
|
||||
service_request_id,
|
||||
'wor_activity_definition',
|
||||
org_id,
|
||||
1,
|
||||
'次',
|
||||
COALESCE((desc_json::jsonb->>'surgeryFee')::numeric, 0),
|
||||
COALESCE((desc_json::jsonb->>'surgeryFee')::numeric, 0),
|
||||
'0',
|
||||
create_time,
|
||||
requester_id,
|
||||
1
|
||||
FROM temp_new_requests;
|
||||
|
||||
-- 查看生成的收费项目数量
|
||||
SELECT '生成的手术收费项目数量' as 检查项, COUNT(*) as 数量
|
||||
FROM adm_charge_item
|
||||
WHERE service_id IN (SELECT service_request_id FROM temp_new_requests);
|
||||
|
||||
-- =====================================================
|
||||
-- 步骤 2.4: 清理临时表
|
||||
-- =====================================================
|
||||
|
||||
DROP TABLE IF EXISTS temp_repair_list;
|
||||
DROP TABLE IF EXISTS temp_new_requests;
|
||||
|
||||
-- =====================================================
|
||||
-- 完成!
|
||||
-- =====================================================
|
||||
Reference in New Issue
Block a user