152 lines
4.1 KiB
TypeScript
152 lines
4.1 KiB
TypeScript
import { Provide } from '@midwayjs/core';
|
|
import { InjectEntityModel } from '@midwayjs/typeorm';
|
|
import { Order } from '../entity/order.entity';
|
|
import { Repository } from 'typeorm';
|
|
import { CustomerTag } from '../entity/customer_tag.entity';
|
|
|
|
@Provide()
|
|
export class CustomerService {
|
|
@InjectEntityModel(Order)
|
|
orderModel: Repository<Order>;
|
|
|
|
@InjectEntityModel(CustomerTag)
|
|
customerTagModel: Repository<CustomerTag>;
|
|
|
|
async getCustomerList(param: Record<string, any>) {
|
|
const {
|
|
current = 1,
|
|
pageSize = 10,
|
|
email,
|
|
tags,
|
|
sorterKey,
|
|
sorterValue,
|
|
state,
|
|
first_purchase_date,
|
|
customerId,
|
|
} = param;
|
|
const whereConds: string[] = [];
|
|
const havingConds: string[] = [];
|
|
|
|
if (email) {
|
|
whereConds.push(`o.customer_email LIKE '%${email}%'`);
|
|
}
|
|
if (state) {
|
|
whereConds.push(
|
|
`JSON_UNQUOTE(JSON_EXTRACT(o.billing, '$.state')) = '${state}'`
|
|
);
|
|
}
|
|
if (customerId) {
|
|
whereConds.push(`
|
|
o.customer_email = (
|
|
SELECT email FROM customer WHERE id = ${Number(customerId)}
|
|
)
|
|
`);
|
|
}
|
|
|
|
if (tags) {
|
|
const tagList = tags
|
|
.split(',')
|
|
.map(tag => `'${tag.trim()}'`)
|
|
.join(',');
|
|
havingConds.push(`
|
|
EXISTS (
|
|
SELECT 1 FROM customer_tag ct
|
|
WHERE ct.email = o.customer_email
|
|
AND ct.tag IN (${tagList})
|
|
)
|
|
`);
|
|
}
|
|
if (first_purchase_date) {
|
|
havingConds.push(
|
|
`DATE_FORMAT(MIN(o.date_paid), '%Y-%m') = '${first_purchase_date}'`
|
|
);
|
|
}
|
|
const baseQuery = `
|
|
${whereConds.length ? `WHERE ${whereConds.join(' AND ')}` : ''}
|
|
GROUP BY o.customer_email
|
|
${havingConds.length ? `HAVING ${havingConds.join(' AND ')}` : ''}
|
|
`;
|
|
|
|
let sql = `
|
|
select
|
|
o.customer_email as email,
|
|
MIN(date_created) as date_created,
|
|
MIN(date_paid) as first_purchase_date,
|
|
MAX(date_paid) as last_purchase_date,
|
|
COUNT(DISTINCT o.id) as orders,
|
|
SUM(total) as total,
|
|
ANY_VALUE(o.shipping) AS shipping,
|
|
ANY_VALUE(o.billing) AS billing,
|
|
(
|
|
SELECT JSON_ARRAYAGG(tag)
|
|
FROM customer_tag ct
|
|
WHERE ct.email = o.customer_email
|
|
) AS tags,
|
|
(
|
|
SELECT id FROM customer c WHERE c.email = o.customer_email
|
|
) as customerId,
|
|
yoone_stats.yoone_orders,
|
|
yoone_stats.yoone_total
|
|
FROM \`order\` o
|
|
LEFT JOIN (
|
|
SELECT
|
|
oo.customer_email,
|
|
COUNT(DISTINCT oi.orderId) AS yoone_orders,
|
|
SUM(oi.total) AS yoone_total
|
|
FROM order_item oi
|
|
JOIN \`order\` oo ON oi.orderId = oo.id
|
|
WHERE oi.name LIKE '%yoone%'
|
|
GROUP BY oo.customer_email
|
|
) yoone_stats ON yoone_stats.customer_email = o.customer_email
|
|
${baseQuery}
|
|
${
|
|
sorterKey
|
|
? `ORDER BY ${sorterKey} ${
|
|
sorterValue === 'descend' ? 'DESC' : 'ASC'
|
|
}`
|
|
: ''
|
|
}
|
|
limit ${pageSize} offset ${(current - 1) * pageSize}
|
|
`;
|
|
const countSql = `
|
|
SELECT COUNT(*) AS total FROM (
|
|
SELECT o.customer_email
|
|
FROM \`order\` o
|
|
${baseQuery}
|
|
) AS sub
|
|
`;
|
|
const [items, countResult] = await Promise.all([
|
|
this.orderModel.query(sql),
|
|
this.orderModel.query(countSql),
|
|
]);
|
|
|
|
const total = countResult[0]?.total || 0;
|
|
return {
|
|
items,
|
|
total,
|
|
current,
|
|
pageSize,
|
|
};
|
|
}
|
|
|
|
async addTag(email: string, tag: string) {
|
|
const isExist = await this.customerTagModel.findOneBy({ email, tag });
|
|
if (isExist) throw new Error(`${tag}已存在`);
|
|
return await this.customerTagModel.save({ email, tag });
|
|
}
|
|
|
|
async delTag(email: string, tag: string) {
|
|
const isExist = await this.customerTagModel.findOneBy({ email, tag });
|
|
if (!isExist) throw new Error(`${tag}不存在`);
|
|
return await this.customerTagModel.delete({ email, tag });
|
|
}
|
|
|
|
async getTags() {
|
|
const tags = await this.customerTagModel
|
|
.createQueryBuilder('tag')
|
|
.select('DISTINCT tag.tag', 'tag')
|
|
.getRawMany();
|
|
return tags.map(t => t.tag);
|
|
}
|
|
}
|