@@ -2,6 +2,7 @@ import {
|
||||
BadRequestException,
|
||||
ForbiddenException,
|
||||
Injectable,
|
||||
Logger,
|
||||
NotFoundException,
|
||||
} from '@nestjs/common';
|
||||
import { loadAppConfig, ClientApp, SmsScene } from '@dukang/shared-types';
|
||||
@@ -22,6 +23,7 @@ import {
|
||||
TestWhitelistService,
|
||||
normalizeTestPhone,
|
||||
} from '../../common/test-whitelist/test-whitelist.service';
|
||||
import { WecomMessagePushService } from '../../integrations/wecom/wecom-message-push.service';
|
||||
|
||||
function haversineMeters(lat1: number, lng1: number, lat2: number, lng2: number): number {
|
||||
const toRad = (d: number) => (d * Math.PI) / 180;
|
||||
@@ -61,6 +63,7 @@ function parseOptionalCoord(value: unknown, kind: 'lat' | 'lng' = 'lng'): number
|
||||
@Injectable()
|
||||
export class StoreService {
|
||||
private readonly config = loadAppConfig();
|
||||
private readonly logger = new Logger(StoreService.name);
|
||||
|
||||
constructor(
|
||||
private readonly prisma: PrismaService,
|
||||
@@ -70,8 +73,33 @@ export class StoreService {
|
||||
private readonly storeCategoryService: StoreCategoryService,
|
||||
private readonly tencentLbs: TencentLbsProvider,
|
||||
private readonly testWhitelist: TestWhitelistService,
|
||||
private readonly wecomPush: WecomMessagePushService,
|
||||
) {}
|
||||
|
||||
/** 门店进入 PENDING 时通知企微(失败不挡业务) */
|
||||
private notifyStoreAuditPending(opts: {
|
||||
storeName: string;
|
||||
cityName?: string | null;
|
||||
partnerLabel?: string | null;
|
||||
submitType: '新建' | '重提';
|
||||
}) {
|
||||
const now = new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' });
|
||||
const lines = [
|
||||
`**门店审核待处理 · ${opts.submitType}**`,
|
||||
`门店:${opts.storeName}`,
|
||||
opts.cityName ? `城市:${opts.cityName}` : null,
|
||||
opts.partnerLabel ? `合伙人:${opts.partnerLabel}` : null,
|
||||
`时间:${now}`,
|
||||
].filter(Boolean);
|
||||
void this.wecomPush
|
||||
.dispatchMarkdown('store.audit_pending', lines.join('\n'), { applyMention: false })
|
||||
.catch((e) =>
|
||||
this.logger.warn(
|
||||
`store.audit_pending wecom push failed: ${e instanceof Error ? e.message : String(e)}`,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
private async whitelistPhoneSet(): Promise<Set<string>> {
|
||||
const rows = await this.prisma.commonTestWhitelistPhone.findMany({
|
||||
select: { phone: true },
|
||||
@@ -559,6 +587,19 @@ export class StoreService {
|
||||
extraJson: { storeName: store.name, phone: normalizedPhone },
|
||||
});
|
||||
|
||||
if (!this.config.autoApproveStore) {
|
||||
const partner = await this.prisma.partnerAccount.findUnique({
|
||||
where: { id: primaryId },
|
||||
select: { name: true, phone: true },
|
||||
});
|
||||
this.notifyStoreAuditPending({
|
||||
storeName: store.name,
|
||||
cityName: store.cityName,
|
||||
partnerLabel: partner?.name || partner?.phone || String(primaryId),
|
||||
submitType: '新建',
|
||||
});
|
||||
}
|
||||
|
||||
return serializeBigInt({
|
||||
store: mapStoreCompat({
|
||||
...store,
|
||||
@@ -716,6 +757,16 @@ export class StoreService {
|
||||
remark: '合伙人修改资料后重新提交审核',
|
||||
},
|
||||
});
|
||||
const partner = await this.prisma.partnerAccount.findUnique({
|
||||
where: { id: primaryId },
|
||||
select: { name: true, phone: true },
|
||||
});
|
||||
this.notifyStoreAuditPending({
|
||||
storeName: updated.name,
|
||||
cityName: updated.cityName,
|
||||
partnerLabel: partner?.name || partner?.phone || String(primaryId),
|
||||
submitType: '重提',
|
||||
});
|
||||
}
|
||||
|
||||
return this.partnerGetStore(partnerAccountId, storeId);
|
||||
@@ -739,6 +790,11 @@ export class StoreService {
|
||||
if (store.auditStatus === 'PENDING') {
|
||||
throw new BadRequestException('门店审核中,暂不可修改资料');
|
||||
}
|
||||
if (store.auditStatus === 'APPROVED') {
|
||||
throw new BadRequestException(
|
||||
'已营业门店修改门头照/环境图须通过「提交变更」由总部审核通过后生效',
|
||||
);
|
||||
}
|
||||
|
||||
const coverUrl = body.coverUrl !== undefined ? String(body.coverUrl ?? '').trim() : undefined;
|
||||
const hasEnv = body.envPhotoUrls !== undefined;
|
||||
@@ -825,6 +881,16 @@ export class StoreService {
|
||||
remark: '合伙人重新上传资料后重新提交审核',
|
||||
},
|
||||
});
|
||||
const partner = await this.prisma.partnerAccount.findUnique({
|
||||
where: { id: primaryId },
|
||||
select: { name: true, phone: true },
|
||||
});
|
||||
this.notifyStoreAuditPending({
|
||||
storeName: store.name,
|
||||
cityName: store.cityName,
|
||||
partnerLabel: partner?.name || partner?.phone || String(primaryId),
|
||||
submitType: '重提',
|
||||
});
|
||||
}
|
||||
|
||||
return this.partnerGetStore(partnerAccountId, storeId);
|
||||
|
||||
Reference in New Issue
Block a user