817 lines
33 KiB
JavaScript
Raw Normal View History

2026-07-27 11:28:33 +08:00
const { ObjectId } = require('mongodb');
const BigNumber = require('bignumber.js');
const dayjs = require('dayjs');
const common = require('../../common');
const zytHis = require('../zyt-his');
const Sm4Util = require("../../utils/sm4-util");
const trade = require('../trade');
const format = require('./format');
const ems = require('../ems-express');
const devAmount = Number(process.env.CONFIG_DEV_UNION_PAY_AMOUNT);
let scheduleTaskIsRunning = false;
exports.main = async (ctx, db) => {
switch (ctx.type) {
case 'getRxMedicalWineOrder':
return getRxMedicalWineOrder(ctx, db);
case 'getWineOrderPayQrcode':
return getWineOrderPayQrcode(ctx, db);
case 'initRxMedicalWineOrder':
return initRxMedicalWineOrder(ctx, db);
case 'refundRxMedicalWineOrder':
return refundRxMedicalWineOrder(ctx, db);
case 'invokeMedicalWinePurchasePaySuccess':
return invokeMedicalWinePurchasePaySuccess(ctx, db);
case 'checkReceiveAddress':
return checkReceiveAddress(ctx, db);
case 'runChineseMedicineOrderSchedule':
return runChineseMedicineOrderSchedule(ctx, db);
case 'getWineShippingList':
return getWineShippingList(ctx, db);
case 'getWineShippingDetail':
return getWineShippingDetail(ctx);
case 'updateWineAfterSaleInfo':
return updateWineAfterSaleInfo(ctx, db);
case 'getWineOrderStatus':
return getWineOrderStatus(ctx, db);
case 'refundWineOrderFee':
return refundWineOrderFee(ctx, db);
case 'refundWineOrderShippingFee':
return refundWineOrderShippingFee(ctx, db);
case 'getWineOrderPatient':
return getWineOrderPatient(ctx, db);
case 'reCreateWineEmsOrder':
return reCreateWineEmsOrder(ctx, db);
case 'wineTest':
return await wineTest(ctx, db);
}
}
function validChargeAmount(amount) {
if (typeof amount !== 'number' || !(amount >= 0)) {
return false
}
// 金额最多精确到分
const cent = new BigNumber(amount).multipliedBy(100).toNumber();
return Number.isInteger(cent) && cent >= 0;
}
async function checkReceiveAddress(ctx) {
try {
const region = Array.isArray(ctx.region) ? ctx.region.filter(i => typeof i === 'string' && i.trim()) : [];
const address = typeof ctx.address === 'string' ? ctx.address.trim() : '';
if (region.length === 0 || address === '') {
return { success: false, message: '参数错误' }
}
const res = await ems.parseAddress(region.join('') + address);
if (!res || !res.success) {
return { success: false, message: `收货地址校验失败:${res?.message}` }
}
const [province, city, area] = region;
const result = await ems.checkAddress({ province, city, area, address });
return { success: true, data: result, message: '地址校验成功' };
} catch (e) {
return { success: false, message: `地址校验失败:${e?.message}` }
}
}
async function getWineShippingList(ctx, db) {
try {
const orderNo = typeof ctx.orderNo === 'string' ? ctx.orderNo.trim() : '';
const name = typeof ctx.name === 'string' ? ctx.name.trim() : '';
const receiveName = typeof ctx.receiveName === 'string' ? ctx.receiveName.trim() : '';
const backShippingNo = typeof ctx.backShippingNo === 'string' ? ctx.backShippingNo.trim() : '';
const startDate = ctx.startDate && dayjs(ctx.startDate).isValid() ? dayjs(ctx.startDate).startOf('day') : null;
const endDate = ctx.endDate && dayjs(ctx.endDate).isValid() ? dayjs(ctx.endDate).endOf('day') : null;
const page = Number.isInteger(ctx.page) && ctx.page > 0 ? ctx.page : 0;
const pageSize = Number.isInteger(ctx.pageSize) && ctx.pageSize > 0 ? ctx.pageSize : 10;
const skip = (page - 1) * pageSize;
const query = { payTime: { $exists: true } };
if (ctx.storeIds && ctx.storeIds.length > 0) {
query.storeId = { $in: ctx.storeIds };
}
if (orderNo) {
query.orderNo = orderNo;
}
if (name) {
query.name = RegExp(name, 'i');
}
if (receiveName) {
query['receiveInfo.name'] = RegExp(receiveName, 'i');
}
if (backShippingNo) {
query['afterSale.waybillNo'] = backShippingNo;
}
if (Array.isArray(ctx.statusList) && ctx.statusList.length > 0) {
query.status = { $in: ctx.statusList };
}
if (startDate) {
query.createTime = { $gte: startDate.valueOf() };
}
if (endDate) {
query.createTime = query.createTime || {};
query.createTime['$lte'] = endDate.valueOf();
}
const data = await db.collection('chinese-medicine-order').find(query).sort({ createTime: -1 }).skip(skip).limit(pageSize).toArray();
const total = await db.collection('chinese-medicine-order').countDocuments(query);
const pages = Math.ceil(total / pageSize);
return { success: true, data: { list: data, total, pages }, message: '查询订单成功' };
} catch (e) {
return { success: false, message: `获取订单失败:${e?.message}` }
}
}
async function getRxMedicalWineOrder(ctx, db) {
try {
const corpId = typeof ctx.corpId === 'string' ? ctx.corpId.trim() : '';
const id = ObjectId.isValid(ctx.id) ? new ObjectId(ctx.id) : null;
const withChargeInfo = typeof ctx.withChargeInfo === 'boolean' ? ctx.withChargeInfo : false;
if (!id) {
return { success: false, message: '参数错误' }
}
const order = await db.collection('chinese-medicine-order').findOne({ _id: id });
if (!order) {
return { success: false, message: '中药饮配方配方订单不存在' }
}
const result = { success: true, data: order, message: '查询中药饮配方配方订单成功' };
if (order.status === 'unpay' && withChargeInfo) {
const store = await db.collection('store-list').findOne({ store_id: order.storeId });
if (!store) {
return { success: false, message: '门店不存在' }
}
result.storeSaleWine = Boolean(store.saleWine);
const res = await getExpressFee(corpId, db);
if (!res.success) {
return res
}
result.deliveryCharge = res.data;
}
return result;
} catch (e) {
return { success: false, message: `查询浸酒方失败:${e?.message}` }
}
}
async function getWineOrderPayQrcode(ctx, db) {
try {
const id = ObjectId.isValid(ctx.id) ? new ObjectId(ctx.id) : null;
const name = typeof ctx.name === 'string' ? ctx.name.trim() : '';
const mobile = typeof ctx.mobile === 'string' ? ctx.mobile.trim() : '';
const region = Array.isArray(ctx.region) ? ctx.region.filter(i => typeof i === 'string' && i.trim()) : [];
const address = typeof ctx.address === 'string' ? ctx.address.trim() : '';
const paperInvoice = typeof ctx.paperInvoice === 'boolean' ? ctx.paperInvoice : false;
if (!id || name === '' || mobile === '' || region.length === 0 || address === '') {
return { success: false, message: '参数错误' }
}
if (!/^1[3456789]\d{9}$/.test(mobile)) {
return { success: false, message: '手机号格式错误' }
}
const order = await db.collection('chinese-medicine-order').findOne({ _id: id });
if (!order) {
return { success: false, message: '浸酒订单不存在' }
}
if (order.status !== 'unpay' || order.pickUpType != 'delivery') {
return { success: false, message: '当前订单状态不支持生成支付二维码' }
}
await db.collection('chinese-medicine-order').updateOne({ _id: order._id }, {
$set: {
receiveInfo: {
name,
mobile,
region,
address,
},
paperInvoice
}
})
const totalAmount = devAmount > 0 ? new BigNumber(devAmount).plus(order.shippingFee).toNumber() : order.totalFee;
const data = {
totalAmount,
businessNo: order.orderNo,
businessType: 'chineseMedicineOrder',
desc: `【震元堂】中药饮片订单`,
expireTime: order.expireTime,
}
const res = await trade.createUnionPayTrade(data);
if (!res || !res.success) {
return res
}
return { success: true, data: res.qrcode, message: '生成中药饮片订单支付二维码成功' }
} catch (e) {
return { success: false, message: `获取中药饮片订单支付二维码失败:${e?.message}` }
}
}
async function initRxMedicalWineOrder(ctx, db) {
try {
const rpNo = typeof ctx.rpNo === 'string' ? ctx.rpNo.trim() : '';
const corpId = typeof ctx.corpId === 'string' ? ctx.corpId.trim() : '';
if (!ObjectId.isValid(rpNo)) {
return { success: false, message: '参数错误' }
}
const order = await db.collection('chinese-medicine-order').findOne({ rpNo, disabled: false });
if (order) {
return { success: true, data: { status: order.status, id: order._id }, message: '该处方已经生成浸酒订单' }
}
const rx = await db.collection('diagnostic-record').findOne({ _id: new ObjectId(rpNo) });
if (!rx) {
return { success: false, message: '处方不存在' }
}
if (rx.status !== 'PASS' || rx.prescriptionType !== 'medicalWinePurchase') {
return { success: false, message: '当前处方不支持生成浸酒订单' }
}
if (Date.now() > rx.expireTime) {
return { success: false, message: '处方已过期' }
}
const data = {
createTime: Date.now(),
rpNo,
storeId: rx.drugStoreNo,
name: Sm4Util.decryptDataForSm3(rx.name),
mobile: Sm4Util.decryptDataForSm3(rx.mobile),
patientId: rx.patientId,
orderNo: rx.medOrgOrderNo,
orderId: rx.orderId,
status: rx.pickUpType === 'selfTake' ? 'completed' : 'unpay', // 自提订单默认已完成 线下支付
pickUpType: rx.pickUpType,
expireTime: rx.expireTime,
disabled: false
}
const store = await db.collection('store-list').findOne({ store_id: data.storeId });
if (!store) {
return { success: false, message: '门店不存在' }
}
data.storeName = store.name;
const wineInfo = await getWineInfo(rx.wines, db);
if (!wineInfo.success) {
return wineInfo
}
data.wines = wineInfo.data;
const res = await zytHis({ type: 'getHisMedicinePurchase', patientId: rx.patientId, orderNo: data.orderNo })
if (!res.success) {
return res
}
const total_amount = Number(res.data.total_amount);
if (!validChargeAmount(total_amount)) {
return { success: false, message: '金额格式错误' }
}
if (res.data.patientid !== rx.patientId) {
return { success: false, message: '患者ID不匹配' }
}
data.goodsFee = total_amount;
if (rx.pickUpType === 'selfTake') {
data.shippingFee = 0;
data.shippingDiscount = 0;
data.shippingOriginalFee = 0;
} else {
const res = await getExpressFee(corpId, db);
if (!res.success) {
return res
}
data.shippingFee = res.data.shippingFee;
data.shippingDiscount = res.data.shippingDiscount;
data.shippingOriginalFee = res.data.shippingOriginalFee;
}
const totalFee = new BigNumber(data.goodsFee).plus(data.shippingFee).toNumber();
data.totalFee = totalFee;
if (!validChargeAmount(totalFee)) {
return { success: false, message: '总金额计算错误' }
}
const { insertedId } = await db.collection('chinese-medicine-order').insertOne(data);
if (!insertedId) {
return { success: false, message: '生成浸酒订单失败' }
}
return { success: true, data: { status: data.status, id: insertedId }, message: '生成浸酒订单成功' }
} catch (e) {
return { success: false, message: e.message }
}
}
async function refundRxMedicalWineOrder(ctx, db) {
try {
const id = ObjectId.isValid(ctx.id) ? new ObjectId(ctx.id) : null;
if (!id) {
return { success: false, message: '参数错误' }
}
const order = await db.collection('chinese-medicine-order').findOne({ _id: id });
if (!order) {
return { success: false, message: '浸酒订单不存在' }
}
if (order.status !== 'paid') {
return { success: false, message: '当前订单状态不支持退款' }
}
const data = {
businessNo: order.orderNo,
businessType: 'chineseMedicineOrder',
tradeNo: order.tradeNo,
}
const res = await trade.refundUnionPayTrade(data);
if (!res.success) {
return res
}
return { success: true, data: res, message: '浸酒订单退款成功' }
} catch (e) {
return { success: false, message: `获取浸酒订单退款失败:${e?.message}` }
}
}
async function invokeMedicalWinePurchasePaySuccess(ctx, db) {
try {
const { tradeNo, businessNo, payTime } = ctx;
const order = await db.collection('chinese-medicine-order').findOne({ orderNo: businessNo });
if (!order) {
return { success: false, message: '浸酒订单不存在' }
}
if (order.status !== 'unpay') {
return { success: false, message: '当前订单状态不支持支付成功回调' }
}
const timestamp = payTime && dayjs(payTime).isValid() ? dayjs(payTime).valueOf() : Date.now();
await db.collection('chinese-medicine-order').updateOne({ _id: order._id }, { $set: { status: 'paid', tradeNo, payTime: timestamp, updateTime: Date.now() } });
order.status = 'paid';
order.payTime = timestamp;
order.tradeNo = tradeNo;
await syncHisWineOrderInfo(order, db)
await createDeliveryOrder(order, db);
return { success: true, message: '浸酒订单支付成功回调处理成功' }
} catch (e) {
return { success: false, message: `浸酒订单支付成功回调处理失败:${e?.message}` }
}
}
async function getWineInfo(data, db) {
const ids = data.map(i => new ObjectId(i._id));
const wines = await db.collection('chinese-medicine').find({ type: 'wine', disabled: false, _id: { $in: ids } }).toArray();
const result = [];
for (const item of data) {
const wine = wines.find(i => i._id.toString() === item._id);
if (!wine) {
return { success: false, message: `浸酒${item.name}不存在` }
}
result.push({
name: wine.name,
details: wine.details,
ingredients: wine.ingredients,
efficacy: wine.efficacy,
quantity: item.quantity,
hisId: wine.hisId,
unit: wine.unit
})
}
return { success: true, data: result }
}
async function getExpressFee(corpId, db) {
try {
const config = await db.collection('hlw-config').findOne({ corpId });
if (!config) {
return { success: false, message: '快递配用配置有误,请联系工作人员' };
}
const { wineExpressFee, wineExpressDiscountFee } = config;
const list = [wineExpressFee, wineExpressDiscountFee];
if (list.some(i => !validChargeAmount(i))) {
return { success: false, message: '快递配用配置有误,请联系工作人员' };
}
const shippingFee = new BigNumber(wineExpressFee).minus(wineExpressDiscountFee).toNumber();
if (!(validChargeAmount(shippingFee))) {
return { success: false, message: '邮政快递配用配置有误,请联系工作人员' };
}
return {
success: true,
data: {
shippingDiscount: wineExpressDiscountFee,
shippingOriginalFee: wineExpressFee,
shippingFee
},
message: '获取快递费用配置成功'
}
} catch (e) {
return { success: false, message: e.message };
}
}
async function syncHisWineOrderInfo(order, db) {
try {
if (!['paid', 'shipped'].includes(order.status)) {
return { success: false, message: '当前订单状态不支持同步' }
}
const trade = await db.collection('trades').findOne({ tradeNo: order.tradeNo }, { projection: { tradeStatus: 1, tradeNo: 1, outTradeNo: 1, totalAmount: 1 } });
if (!trade || trade.tradeStatus !== 'paid') {
return { success: false, message: '订单不存在或状态错误' }
}
const data = {
patientId: order.patientId,
orderNo: order.orderNo,
tradeNo: order.tradeNo,
outTradeNo: trade.outTradeNo,
totalAmount: order.totalFee
}
const res = await zytHis({ type: 'syncHisChargeStatus', ...data });
if (res.success) {
await db.collection('chinese-medicine-order').updateOne({ _id: order._id }, { $set: { syncHisChargeStatus: 'charged' } });
return { success: true, message: '同步浸酒订单信息成功' }
}
return res
} catch (e) {
return { success: false, message: e.message }
}
}
async function syncHisRefundStatus(order, db) {
try {
if (!['goodsFeeRefunded', 'refunded'].includes(order.status)) {
return { success: false, message: '当前订单状态不支持同步' }
}
const refundRecords = Array.isArray(order.refundRecords) ? order.refundRecords.reverse() : [];
const refund = refundRecords.find(i => i.type === 'goodsFee' && i.result === 'refunded');
if (!refund) {
return { success: false, message: '订单不存在退款记录' }
}
const data = {
patientId: order.patientId,
orderNo: order.orderNo,
refundSerialNo: refund.refundSerialNo,
}
const res = await zytHis({ type: 'syncHisRefundStatus', ...data });
if (res.success) {
await db.collection('chinese-medicine-order').updateOne({ _id: order._id }, { $set: { syncHisChargeStatus: 'refunded' } });
return { success: true, message: '同步浸酒订单信息成功' }
}
return res
} catch (e) {
return { success: false, message: e.message }
}
}
async function getWineShippingDetail(ctx) {
try {
const shippingNo = typeof ctx.shippingNo === 'string' ? ctx.shippingNo.trim() : '';
if (!shippingNo) {
return { success: false, message: '配送单号不能为空' }
}
const emsApi = require('../ems-express');
const res = await emsApi.getShippingDetail(shippingNo);
return { success: true, data: res.data, message: '获取配送详情成功' }
} catch (e) {
return { success: false, message: e.message };
}
}
async function createDeliveryOrder(order, db) {
try {
const emsApi = require('../ems-express');
const emsOrderData = format.formatEMSOrderData(order);
const { success, data } = await emsApi.createOrder(emsOrderData);
if (success && data) {
await db.collection('chinese-medicine-order').updateOne({ _id: order._id }, { $set: { status: 'shipped', shippingNo: data.waybillNo } });
return { success: true, message: 'ems订单创建成功', data: { shippingNo: data.waybillNo } };
}
return { success: false, message: '购药订单物流下单失败' };
} catch (e) {
return { success: false, message: `购药订单物流下单错误:${e.message}` };
}
}
async function updateWineAfterSaleInfo(ctx, db) {
try {
const id = typeof ctx.id === 'string' ? ctx.id.trim() : '';
if (id === '') {
return { success: false, message: "浸酒订单id不能为空" };
}
const afterSale = {};
if ('notes' in ctx && typeof ctx.notes === 'string') {
afterSale.notes = ctx.notes.trim();
}
if ('waybillNo' in ctx && typeof ctx.waybillNo === 'string') {
afterSale.waybillNo = ctx.waybillNo.trim();
}
if (afterSale.notes && afterSale.notes.length > 300) {
return { success: false, message: "售后备注不能超过300个字符" };
}
if (afterSale.waybillNo && afterSale.waybillNo.length > 100) {
return { success: false, message: "物流单号不能超过100个字符" };
}
if (Object.keys(afterSale).length === 0) {
return { success: true, message: "售后信息没有变化" };
}
const { matchedCount } = await db.collection('chinese-medicine-order').updateOne({ _id: new ObjectId(id) }, { $set: { afterSale } });
if (matchedCount > 0) {
return { success: true, message: "更新售后信息成功" };
}
return { success: false, message: "更新售后信息失败" };
} catch (e) {
return { success: false, message: `更新售后信息错误: ${e.message}` };
}
}
async function getWineOrderStatus(ctx, db) {
try {
const rpNo = ObjectId.isValid(ctx.rpNo) ? ctx.rpNo : '';
if (!rpNo) {
return { success: false, message: '参数错误' }
}
const rx = await db.collection('diagnostic-record').findOne({ _id: new ObjectId(rpNo) });
if (!rx) {
return { success: false, message: '记录不存在' }
}
const order = await db.collection('chinese-medicine-order').findOne({ rpNo });
const rxExpired = !order && Date.now() < rx.expireTime;
const payExpired = order.status === 'unpay' && Date.now() > order.expireTime;
const orderExpired = order.status === 'expired';
if (rxExpired || payExpired || orderExpired) {
return { success: true, status: 'expired' }
}
if (Date.now() < rx.expireTime && (!order || order.status === 'unpay')) {
return { success: true, status: 'unpay', expireTime: rx.expireTime }
}
return { success: true, status: order?.status, message: '查询成功' }
} catch (e) {
return { success: false, message: e.message }
}
}
async function refundWineOrderFee(ctx, db) {
try {
const applyTime = Date.now();
const id = typeof ctx.id === 'string' ? ctx.id.trim() : '';
const orderNo = typeof ctx.orderNo === 'string' ? ctx.orderNo.trim() : '';
const operator = typeof ctx.operator === 'string' ? ctx.operator.trim() : '';
const operatorId = typeof ctx.operatorId === 'string' ? ctx.operatorId.trim() : '';
const reason = typeof ctx.reason === 'string' ? ctx.reason.trim() : '';
if (!id || !orderNo || !operator || !operatorId) {
return { success: false, message: "参数不能为空" };
}
if (reason.length > 200) {
return { success: false, message: "[邮政快递]退费原因不能超过200个字符" };
}
const order = await db.collection('chinese-medicine-order').findOne({ _id: new ObjectId(id), orderNo });
if (!order) {
return { success: false, message: '浸酒订单不存在' }
}
if (['goodsFeeRefunded', 'refunded'].includes(order.status)) {
return { success: false, message: "配药订单医保费用已退费" };
}
if (!['paid', 'shipped'].includes(order.status)) {
return { success: false, message: "配药订单状态不正确" };
}
const refundOrderId = common.generateUniqueStr('3JHR');
const res = await trade.refundUnionPayTrade({
tradeNo: order.tradeNo,
businessNo: order.orderNo,
businessType: 'chineseMedicineOrder',
refundAmount: devAmount || order.goodsFee,
refundOrderId,
});
if (!res.success) {
return { success: false, message: res.message || '退费失败' };
}
const refundRecord = {
amount: order.goodsFee,
applyTime,
platform: 'unionPay',
reason,
type: 'goodsFee',
refundSerialNo: refundOrderId,
refundTime: applyTime,
result: res.success ? 'refunded' : 'refund_fail',
operator,
operatorId
}
const refundRecords = order.refundRecords || [];
refundRecords.push(refundRecord);
await db.collection('chinese-medicine-order').updateOne({ _id: order._id }, { $set: { refundRecords } });
if (order.shippingFee === 0) {
await db.collection('chinese-medicine-order').updateOne({ _id: order._id }, { $set: { status: 'refunded' } });
} else if (order.shippingFee > 0) {
await db.collection('chinese-medicine-order').updateOne({ _id: order._id }, { $set: { status: 'goodsFeeRefunded' } });
}
if (order.shippingFee === 0 && order.shippingNo) {
const emsApi = require('../ems-express');
const { success } = await emsApi.cancelOrder({ logisticsOrderNo: order.orderNo, waybillNo: order.shippingNo, cancelReason: reason });
if (success) {
await db.collection('chinese-medicine-order').updateOne({ _id: order._id }, { $set: { deliveryCancelled: true } });
}
}
return { success: true, message: "费用退费成功" };
} catch (e) {
return { success: false, message: e.message }
}
}
async function refundWineOrderShippingFee(ctx, db) {
try {
const applyTime = Date.now();
const id = typeof ctx.id === 'string' ? ctx.id.trim() : '';
const orderNo = typeof ctx.orderNo === 'string' ? ctx.orderNo.trim() : '';
const operator = typeof ctx.operator === 'string' ? ctx.operator.trim() : '';
const operatorId = typeof ctx.operatorId === 'string' ? ctx.operatorId.trim() : '';
const reason = typeof ctx.reason === 'string' ? ctx.reason.trim() : '';
if (!id || !orderNo || !operator || !operatorId) {
return { success: false, message: "参数不能为空" };
}
if (reason.length > 200) {
return { success: false, message: "[邮政快递]退费原因不能超过200个字符" };
}
const order = await db.collection('chinese-medicine-order').findOne({ _id: new ObjectId(id), orderNo });
if (!order) {
return { success: false, message: '浸酒订单不存在' }
}
if ('goodsFeeRefunded' !== order.status) {
return { success: false, message: "配药订单状态不正确" };
}
const refundOrderId = common.generateUniqueStr('3JHR');
const res = await trade.refundUnionPayTrade({
tradeNo: order.tradeNo,
businessNo: order.orderNo,
businessType: 'chineseMedicineOrder',
refundAmount: order.shippingFee,
refundOrderId,
});
const refundRecord = {
amount: order.shippingFee,
applyTime,
platform: 'unionPay',
reason,
type: 'shippingFee',
refundSerialNo: refundOrderId,
refundTime: applyTime,
result: res.success ? 'refunded' : 'refund_fail',
operator,
operatorId
}
const refundRecords = order.refundRecords || [];
refundRecords.push(refundRecord);
await db.collection('chinese-medicine-order').updateOne({ _id: order._id }, { $set: { refundRecords } });
if (!res.success) {
return { success: false, message: res.message || '退费失败' };
}
await db.collection('chinese-medicine-order').updateOne({ _id: order._id }, { $set: { status: 'refunded' } });
const emsApi = require('../ems-express');
const { success } = await emsApi.cancelOrder({ logisticsOrderNo: order.orderNo, waybillNo: order.shippingNo, cancelReason: reason });
if (success) {
await db.collection('chinese-medicine-order').updateOne({ _id: order._id }, { $set: { deliveryCancelled: true } });
}
return { success: true, message: "费用退费成功" };
} catch (e) {
return { success: false, message: e.message }
}
}
// 定时任务
// 查询 超时未支付的浸酒订单
async function runChineseMedicineOrderSchedule(ctx, db) {
if (scheduleTaskIsRunning) return;
const logText = [`${'='.repeat(8)}浸酒订单定时任务开始${'='.repeat(8)}`];
scheduleTaskIsRunning = true;
try {
// 当日未支付且超时的订单
const list = await db.collection('chinese-medicine-order').find(
{
status: 'unpay',
expireTime: { $lt: Date.now() },
createTime: { $gt: dayjs().startOf('day').valueOf() }
}).toArray();
logText.push(`[${dayjs().format('YYYY-MM-DD HH:mm:ss')}]支付超时数: ${list.length}`);
for (let item of list) {
const { status } = await trade.checkUnionPayUnpay({ businessNo: item.orderNo, businessType: 'chineseMedicineOrder' });
if (status === 'unpay') {
await db.collection('chinese-medicine-order').updateOne({ _id: item._id }, { $set: { status: 'expired' } });
} else if (status === 'refunded') {
await db.collection('chinese-medicine-order').updateOne({ _id: item._id }, { $set: { status: 'refunded' } });
}
}
// 已经支付但是没有同步his状态的同步his
const paidList = await db.collection('chinese-medicine-order').find({
status: { $in: ['paid', 'shipped'] },
syncHisChargeStatus: { $exists: false },
createTime: { $gt: dayjs().startOf('day').valueOf() },
payTime: {
$gt: dayjs().startOf('day').valueOf(),
$lt: dayjs().subtract(5, 'minute').valueOf(),
}
}).toArray();
logText.push(`[${dayjs().format('YYYY-MM-DD HH:mm:ss')}]同步支付数: ${paidList.length}`);
for (let item of paidList) {
await syncHisWineOrderInfo(item, db);
}
const refundList = await db.collection('chinese-medicine-order').find({
status: { $in: ['goodsFeeRefunded', 'refunded'] },
syncHisChargeStatus: 'charged',
refundRecords: {
$elemMatch: {
type: 'goodsFee',
result: 'refunded',
refundTime: { $gt: dayjs().startOf('day').valueOf() }
}
}
}).toArray();
logText.push(`[${dayjs().format('YYYY-MM-DD HH:mm:ss')}]同步退款数: ${refundList.length}`);
for (let item of refundList) {
await syncHisRefundStatus(item, db);
}
// 已经支付但是没有发货的 发货
const shippedList = await db.collection('chinese-medicine-order').find(
{
status: 'paid',
pickUpType: 'delivery',
disabled: false,
createTime: { $gt: dayjs().startOf('day').valueOf() },
payTime: { $lt: dayjs().subtract(3, 'minute').valueOf() }
}).toArray();
logText.push(`[${dayjs().format('YYYY-MM-DD HH:mm:ss')}]待发货数: ${shippedList.length}`);
for (let item of shippedList) {
await createDeliveryOrder(item, db);
}
// 待同步his购药订单物流信息 同步his购药订单已收取运费或已退还运费信息
const updateDeliveryOrders = await db.collection('chinese-medicine-order').find({
$or: [
{ disabled: false, status: 'shipped', shippingNo: { $exists: true }, syncHisDelivery: { $exists: false }, payTime: { $gt: dayjs().startOf('day').valueOf() } }, // 已经收取运费 未同步his
{
disabled: false, status: 'refunded', shippingNo: { $exists: true }, syncHisDelivery: { $ne: 'refunded' }, refundRecords: {
$elemMatch: {
refundTime: { $gt: dayjs().startOf('day').valueOf() }
}
}
}, // 已退还运费 未同步his
]
}).toArray();
logText.push(`[${dayjs().format('YYYY-MM-DD HH:mm:ss')}]待同步物流数: ${updateDeliveryOrders.length}`);
for (let updateDeliveryOrder of updateDeliveryOrders) {
const region = updateDeliveryOrder.receiveInfo.region || [];
const address = updateDeliveryOrder.receiveInfo.address || '';
const invoice = updateDeliveryOrder.paperInvoice ? 1 : 0;
const fullAddress = region.join('') + address;
const shippingType = 'ems';
const payTime = updateDeliveryOrder.payTime ? dayjs(updateDeliveryOrder.payTime).format('YYYY-MM-DD HH:mm:ss') : undefined;
const backFlag = updateDeliveryOrder.status === 'shipped' ? 0 : 1; // 0 收取运费 | 1 退还运费
const { success } = await zytHis({ type: 'updateMedicinePurchaseDelivery', ...updateDeliveryOrder, shippingType, fullAddress, payTime, invoice, backFlag })
if (success) {
const target = backFlag === 0 ? 'charged' : 'refunded';
await db.collection('chinese-medicine-order').updateOne({ _id: updateDeliveryOrder._id }, { $set: { syncHisDelivery: target } });
}
}
} catch (e) {
console.log('执行定时任务出现错误: ', e.message)
}
scheduleTaskIsRunning = false;
logText.push(`${'='.repeat(8)}浸酒订单定时任务结束${'='.repeat(8)}`);
logText.forEach(item => console.log(item))
}
async function getWineOrderPatient(ctx, db) {
const patientId = typeof ctx.patientId === 'string' ? ctx.patientId.trim() : '';
const orderNo = typeof ctx.orderNo === 'string' ? ctx.orderNo.trim() : '';
if (!patientId || !orderNo) {
return { success: false, message: '参数错误' }
}
try {
const order = await db.collection('chinese-medicine-order').findOne({ disabled: false, patientId, orderNo });
if (!order) {
return { success: false, message: '订单不存在' }
}
const rx = await db.collection('diagnostic-record').findOne({ _id: new ObjectId(order.rpNo) });
if (!rx) {
return { success: false, message: '处方不存在' }
}
const anotherIdNo = typeof rx.idCard === 'string' ? rx.idCard.trim() : '';
if (!anotherIdNo) {
return { success: false, message: '处方中没有患者身份证号' }
}
return await zytHis({ type: 'getHisCustomer', anotherIdNo })
} catch (e) {
return { success: false, message: e.message }
}
}
async function reCreateWineEmsOrder(ctx, db) {
const orderNo = typeof ctx.orderNo === 'string' ? ctx.orderNo.trim() : '';
if (!orderNo) {
return { success: false, message: '参数错误' }
}
try {
const order = await db.collection('chinese-medicine-order').findOne({ disabled: false, orderNo, status: 'paid', pickUpType: 'delivery' });
if (!order) {
return { success: false, message: '订单不存在' }
}
if (order.shippingNo) {
return { success: false, message: '当前订单已创建邮政订单' }
}
if (!order.tradeNo) {
return { success: false, message: '支付订单号不存在' }
}
const res1 = await trade.checkUnionPayUnpay({ businessNo: order.orderNo, businessType: 'chineseMedicineOrder' });
const { status } = res1 || {};
if (!res1 || status !== 'paid') {
return { success: false, message: '银联订单支付状态异常' }
}
const res = await createDeliveryOrder(order, db);
return res
} catch (e) {
return { success: false, message: e.message }
}
}
async function wineTest(ctx, db) {
}