forked from lxbfYeaaGbeDLMCi/deShanXiao
200 lines
5.3 KiB
TypeScript
200 lines
5.3 KiB
TypeScript
import { Request, Response } from "express";
|
||
import { getRepository } from "typeorm";
|
||
import dayjs from "dayjs";
|
||
import DeceasedRetail from "@/entity/DeceasedRetail";
|
||
import SeletedServiceList from "@/entity/SeletedServiceList";
|
||
import Deceased from "@/entity/Deceased";
|
||
import { handleError } from "@/util/globalMethods";
|
||
|
||
interface QueryParams {
|
||
startDate?: string;
|
||
endDate?: string;
|
||
serviceName?: string;
|
||
deceasedName?: string;
|
||
pageSize?: number;
|
||
pageNumber?: number;
|
||
guide?: string;
|
||
familyName: string;
|
||
}
|
||
|
||
interface SalesDetailItem {
|
||
id: string;
|
||
checkoutDate: string;
|
||
deceasedName: string;
|
||
gender: string;
|
||
age: number;
|
||
idCard: string;
|
||
contactPerson: string;
|
||
contactPhone: string;
|
||
serviceName: string;
|
||
price: number;
|
||
quantity: number;
|
||
amount: number;
|
||
remark: string;
|
||
}
|
||
|
||
export const getSalesDetails = async (req: Request, res: Response) => {
|
||
try {
|
||
const params = parseQueryParams(
|
||
req.method === "GET" ? req.query : req.body
|
||
);
|
||
const pageSize = Number(params.pageSize) || 10;
|
||
const pageNumber = Number(params.pageNumber) || 1;
|
||
|
||
// 第一步:查询 SeletedServiceList 和 DeceasedRetail
|
||
const initialQuery = getRepository(SeletedServiceList)
|
||
.createQueryBuilder("ssl")
|
||
.innerJoinAndMapOne(
|
||
"ssl.deceasedRetail",
|
||
DeceasedRetail,
|
||
"dr",
|
||
"FIND_IN_SET(ssl.id, dr.serviceItems) AND dr.retailState = 1 AND dr.cancelState = 0 "
|
||
);
|
||
|
||
if (pageSize !== 999999999) {
|
||
// 如果还没有连接 Deceased 表,需要确保连接
|
||
if (
|
||
(params.deceasedName || params.familyName) &&
|
||
!initialQuery.expressionMap.joinAttributes.some(
|
||
(join) => join.alias.name === "d"
|
||
)
|
||
) {
|
||
initialQuery.innerJoin(Deceased, "d", "d.id = dr.deceasedId");
|
||
}
|
||
if (params.startDate || params.endDate) {
|
||
initialQuery.andWhere("dr.checkoutDate BETWEEN :start AND :end", {
|
||
start:
|
||
params.startDate ||
|
||
dayjs().startOf("day").format("YYYY-MM-DD HH:mm:ss"),
|
||
end: params.endDate || dayjs().format("YYYY-MM-DD HH:mm:ss"),
|
||
});
|
||
}
|
||
|
||
// 服务名称条件
|
||
if (params.serviceName) {
|
||
initialQuery.andWhere("ssl.name LIKE :serviceName", {
|
||
serviceName: `%${params.serviceName}%`,
|
||
});
|
||
}
|
||
|
||
if (params.guide) {
|
||
initialQuery.andWhere("dr.guide LIKE :guide", {
|
||
guide: `%${params.guide}%`,
|
||
});
|
||
}
|
||
|
||
// 逝者姓名条件
|
||
if (params.deceasedName) {
|
||
initialQuery.andWhere(
|
||
"( d.name LIKE :deceasedName OR (dr.deceasedId = 0 AND dr.deceasedName LIKE :deceasedName))",
|
||
{
|
||
deceasedName: `%${params.deceasedName}%`,
|
||
}
|
||
);
|
||
}
|
||
|
||
// 逝者家属姓名条件
|
||
if (params.familyName) {
|
||
initialQuery.andWhere(
|
||
"( d.familyName LIKE :familyName OR (dr.deceasedId = 0 AND dr.familyName LIKE :familyName) )",
|
||
{
|
||
familyName: `%${params.familyName}%`,
|
||
}
|
||
);
|
||
}
|
||
}
|
||
|
||
// 执行初步查询
|
||
const initialResult = await initialQuery
|
||
.orderBy("dr.checkoutDate", "DESC")
|
||
.skip((pageNumber - 1) * pageSize)
|
||
.take(pageSize)
|
||
.getMany();
|
||
|
||
// 第二步:根据初步查询结果查询绑定 Deceased
|
||
|
||
const deceasedIds = initialResult
|
||
//@ts-ignore
|
||
.map((item) => item.deceasedRetail?.deceasedId)
|
||
.filter((id) => id !== undefined && id !== 0);
|
||
|
||
const deceasedMap = new Map();
|
||
if (deceasedIds.length > 0) {
|
||
const deceasedList = await getRepository(Deceased)
|
||
.createQueryBuilder("d")
|
||
.where("d.id IN (:...ids)", { ids: deceasedIds })
|
||
.getMany();
|
||
|
||
deceasedList.forEach((deceased) => {
|
||
deceasedMap.set(deceased.id, deceased);
|
||
});
|
||
}
|
||
|
||
// 合并结果
|
||
const result = initialResult.map((item) => {
|
||
//@ts-ignore
|
||
if (item.deceasedRetail?.deceasedId !== 0) {
|
||
//@ts-ignore
|
||
item.deceased = deceasedMap.get(item.deceasedRetail.deceasedId) || {};
|
||
} else {
|
||
//@ts-ignore
|
||
item.deceased = { ...item.deceasedRetail };
|
||
}
|
||
return item;
|
||
});
|
||
|
||
// 获取总记录数
|
||
const total = await initialQuery.getCount();
|
||
res.json({
|
||
code: 200,
|
||
data: {
|
||
list: result.map((item) => {
|
||
return {
|
||
...item,
|
||
// @ts-ignore
|
||
sum: Number(item.price).toFixed(2) * Number(item.quantity),
|
||
};
|
||
}),
|
||
pageSize,
|
||
pageNumber,
|
||
total,
|
||
},
|
||
});
|
||
} catch (error) {
|
||
handleError(res, error);
|
||
}
|
||
};
|
||
|
||
const parseQueryParams = (query: any): QueryParams => {
|
||
const {
|
||
startDate,
|
||
endDate,
|
||
serviceName,
|
||
deceasedName,
|
||
guide,
|
||
pageSize,
|
||
pageNumber,
|
||
familyName,
|
||
} = query;
|
||
|
||
const validateDate = (date: string, field: string) => {
|
||
if (date && !dayjs(date).isValid()) {
|
||
throw new Error(`${field}格式错误,请使用YYYY-MM-DD格式`);
|
||
}
|
||
};
|
||
|
||
validateDate(startDate, "开始日期");
|
||
validateDate(endDate, "结束日期");
|
||
|
||
return {
|
||
startDate: startDate?.trim(),
|
||
endDate: endDate?.trim(),
|
||
serviceName: serviceName?.trim(),
|
||
deceasedName: deceasedName?.trim(),
|
||
guide: guide?.trim(),
|
||
pageSize: pageSize ? parseInt(pageSize) : undefined,
|
||
pageNumber: pageNumber ? parseInt(pageNumber) : undefined,
|
||
familyName: familyName,
|
||
};
|
||
};
|