Files
deShanXiao/backEnd/src/router/stats/controller/salesDetail.ts

200 lines
5.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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,
};
};