feat(store): dual business hours, avg price, and status lock
CI / verify (pull_request) Has been cancelled
CI / verify (pull_request) Has been cancelled
Support 1-2 hour segments and optional avgPrice; show bank settlement on HQ store detail; enforce pickup min 2 bottles; Chinese order statuses; block shop reopen after permanent close. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -6,6 +6,7 @@ import {
|
||||
} from '@nestjs/common';
|
||||
import { loadAppConfig, ClientApp, SmsScene } from '@dukang/shared-types';
|
||||
import { PARTNER_STAFF_ROLE_LABELS, PartnerStaffRole, type PartnerLeaderboardPeriod } from '@dukang/shared-types';
|
||||
import { validateBusinessHours } from '@dukang/domain';
|
||||
import { PrismaService } from '../../common/prisma/prisma.module';
|
||||
import { serializeBigInt } from '../../common/decorators/current-user.decorator';
|
||||
import { mapStoreCompat } from '../../common/compat/v31-compat';
|
||||
@@ -180,6 +181,21 @@ export class StoreService {
|
||||
const categoryId = parseBigIntParam(body.categoryId, '分类ID');
|
||||
await this.storeCategoryService.assertLeafCategoryId(categoryId);
|
||||
|
||||
const openTime = body.openTime ? String(body.openTime).trim() : '10:00';
|
||||
const closeTime = body.closeTime ? String(body.closeTime).trim() : '22:00';
|
||||
const openTime2 = body.openTime2 ? String(body.openTime2).trim() : '';
|
||||
const closeTime2 = body.closeTime2 ? String(body.closeTime2).trim() : '';
|
||||
const hoursCheck = validateBusinessHours([
|
||||
{ open: openTime, close: closeTime },
|
||||
...(openTime2 || closeTime2 ? [{ open: openTime2, close: closeTime2 }] : []),
|
||||
]);
|
||||
if (!hoursCheck.ok) throw new BadRequestException(hoursCheck.message);
|
||||
|
||||
const avgPriceRaw = body.avgPrice != null && body.avgPrice !== '' ? Number(body.avgPrice) : null;
|
||||
if (avgPriceRaw != null && (Number.isNaN(avgPriceRaw) || avgPriceRaw < 0)) {
|
||||
throw new BadRequestException('人均费用须为非负数字');
|
||||
}
|
||||
|
||||
const store = await this.prisma.store.create({
|
||||
data: {
|
||||
cityId: city.id,
|
||||
@@ -192,8 +208,11 @@ export class StoreService {
|
||||
district: String(body.district ?? ''),
|
||||
address: String(body.address),
|
||||
intro: body.intro ? String(body.intro) : null,
|
||||
openTime: body.openTime ? String(body.openTime) : '10:00',
|
||||
closeTime: body.closeTime ? String(body.closeTime) : '22:00',
|
||||
avgPrice: avgPriceRaw,
|
||||
openTime,
|
||||
closeTime,
|
||||
openTime2: openTime2 || null,
|
||||
closeTime2: closeTime2 || null,
|
||||
status: this.config.autoApproveStore ? 'OPEN' : 'PAUSED',
|
||||
auditStatus: this.config.autoApproveStore ? 'APPROVED' : 'PENDING',
|
||||
auditedAt: this.config.autoApproveStore ? new Date() : null,
|
||||
@@ -549,6 +568,9 @@ export class StoreService {
|
||||
where: { storeAccountId_storeId: { storeAccountId, storeId } },
|
||||
include: { store: true },
|
||||
});
|
||||
if (binding.store.status === 'CLOSED') {
|
||||
throw new BadRequestException('门店已永久关闭,无法在门店端开启或调整营业状态');
|
||||
}
|
||||
if (status === 'OPEN' && binding.store.auditStatus !== 'APPROVED') {
|
||||
throw new BadRequestException(
|
||||
binding.store.auditStatus === 'REJECTED'
|
||||
|
||||
Reference in New Issue
Block a user