137 lines
3.7 KiB
TypeScript
137 lines
3.7 KiB
TypeScript
import {
|
|
Injectable,
|
|
NotFoundException,
|
|
BadRequestException,
|
|
} from '@nestjs/common';
|
|
import { InjectRepository } from '@nestjs/typeorm';
|
|
import { Repository } from 'typeorm';
|
|
import { Merchant } from '@/entities/merchant.entity';
|
|
import {
|
|
ApplyMerchantDto,
|
|
UpdateMerchantDto,
|
|
QueryMerchantDto,
|
|
} from './dto/merchant.dto';
|
|
|
|
@Injectable()
|
|
export class MerchantService {
|
|
constructor(
|
|
@InjectRepository(Merchant)
|
|
private merchantRepo: Repository<Merchant>,
|
|
) {}
|
|
|
|
async apply(sellerId: number, dto: ApplyMerchantDto) {
|
|
const existing = await this.merchantRepo.findOne({ where: { sellerId } });
|
|
if (existing) {
|
|
throw new BadRequestException('您已提交过商家申请');
|
|
}
|
|
|
|
const merchant = this.merchantRepo.create({ sellerId, ...dto });
|
|
return this.merchantRepo.save(merchant);
|
|
}
|
|
|
|
async findBySellerId(sellerId: number) {
|
|
return this.merchantRepo.findOne({ where: { sellerId } });
|
|
}
|
|
|
|
async findById(id: number) {
|
|
const merchant = await this.merchantRepo.findOne({ where: { id } });
|
|
if (!merchant) throw new NotFoundException('商家不存在');
|
|
return merchant;
|
|
}
|
|
|
|
async update(id: number, dto: UpdateMerchantDto) {
|
|
const merchant = await this.findById(id);
|
|
// 审核通过或审核拒绝后修改信息,需要重新进入审核
|
|
if (merchant.status === 'approved' || merchant.status === 'rejected') {
|
|
await this.merchantRepo.update(id, {
|
|
...dto,
|
|
status: 'pending',
|
|
rejectReason: '',
|
|
});
|
|
} else {
|
|
await this.merchantRepo.update(id, dto);
|
|
}
|
|
return this.findById(id);
|
|
}
|
|
|
|
async findPublic(query: QueryMerchantDto) {
|
|
const { page = 1, pageSize = 10, keyword, city } = query;
|
|
const safePage = Number(page) || 1;
|
|
const safePageSize = Number(pageSize) || 10;
|
|
const qb = this.merchantRepo
|
|
.createQueryBuilder('m')
|
|
.where('m.status = :status', { status: 'approved' });
|
|
|
|
if (keyword) {
|
|
qb.andWhere('m.shop_name LIKE :kw', { kw: `%${keyword}%` });
|
|
}
|
|
if (city) {
|
|
qb.andWhere('m.city = :city', { city });
|
|
}
|
|
|
|
qb.orderBy('m.rating', 'DESC');
|
|
qb.skip((safePage - 1) * safePageSize).take(safePageSize);
|
|
|
|
const [list, total] = await qb.getManyAndCount();
|
|
return {
|
|
list,
|
|
total,
|
|
page: safePage,
|
|
pageSize: safePageSize,
|
|
totalPages: Math.ceil(total / safePageSize),
|
|
};
|
|
}
|
|
|
|
async findAll(query: QueryMerchantDto) {
|
|
const { page = 1, pageSize = 10, keyword, status, city } = query;
|
|
const qb = this.merchantRepo.createQueryBuilder('m');
|
|
|
|
if (keyword) {
|
|
qb.andWhere('(m.shop_name LIKE :kw OR m.phone LIKE :kw)', {
|
|
kw: `%${keyword}%`,
|
|
});
|
|
}
|
|
if (status) {
|
|
qb.andWhere('m.status = :status', { status });
|
|
}
|
|
if (city) {
|
|
qb.andWhere('m.city = :city', { city });
|
|
}
|
|
|
|
qb.orderBy('m.createdAt', 'DESC');
|
|
qb.skip((page - 1) * pageSize).take(pageSize);
|
|
|
|
const [list, total] = await qb.getManyAndCount();
|
|
return {
|
|
list,
|
|
total,
|
|
page,
|
|
pageSize,
|
|
totalPages: Math.ceil(total / pageSize),
|
|
};
|
|
}
|
|
|
|
async approve(id: number) {
|
|
await this.merchantRepo.update(id, { status: 'approved' });
|
|
return { message: '商家已通过审核' };
|
|
}
|
|
|
|
async reject(id: number, reason: string) {
|
|
await this.merchantRepo.update(id, {
|
|
status: 'rejected',
|
|
rejectReason: reason,
|
|
});
|
|
return { message: '商家已拒绝' };
|
|
}
|
|
|
|
async freeze(id: number) {
|
|
await this.merchantRepo.update(id, { status: 'frozen' });
|
|
return { message: '店铺已冻结' };
|
|
}
|
|
|
|
async unfreeze(id: number) {
|
|
await this.merchantRepo.update(id, { status: 'approved' });
|
|
return { message: '店铺已解冻' };
|
|
}
|
|
}
|