门店账户多账号
This commit is contained in:
@@ -41,14 +41,26 @@ export class AdminStoresService {
|
||||
include: {
|
||||
cityRef: { select: { id: true, name: true, code: true } },
|
||||
partnerAccount: { select: { id: true, companyName: true } },
|
||||
account: { select: { id: true, phone: true, name: true, status: true } },
|
||||
bindings: {
|
||||
where: { storeAccount: { isPrimary: 1 } },
|
||||
take: 1,
|
||||
include: {
|
||||
storeAccount: { select: { id: true, phone: true, name: true, status: true } },
|
||||
},
|
||||
},
|
||||
coverResource: { select: { id: true, url: true } },
|
||||
},
|
||||
}),
|
||||
this.prisma.store.count({ where }),
|
||||
]);
|
||||
return serializeBigInt({
|
||||
items: items.map((s) => mapStoreCompat(s)),
|
||||
items: items.map((s) =>
|
||||
mapStoreCompat({
|
||||
...s,
|
||||
account: s.bindings[0]?.storeAccount ?? null,
|
||||
bindings: undefined,
|
||||
}),
|
||||
),
|
||||
total,
|
||||
page,
|
||||
pageSize,
|
||||
@@ -62,7 +74,11 @@ export class AdminStoresService {
|
||||
cityRef: true,
|
||||
partnerAccount: true,
|
||||
category: true,
|
||||
account: true,
|
||||
bindings: {
|
||||
where: { storeAccount: { isPrimary: 1 } },
|
||||
take: 1,
|
||||
include: { storeAccount: true },
|
||||
},
|
||||
coverResource: true,
|
||||
_count: { select: { redeemRecords: true, ratings: true } },
|
||||
},
|
||||
@@ -81,6 +97,8 @@ export class AdminStoresService {
|
||||
]);
|
||||
return serializeBigInt(mapStoreCompat({
|
||||
...store,
|
||||
account: store.bindings[0]?.storeAccount ?? null,
|
||||
bindings: undefined,
|
||||
media,
|
||||
audits,
|
||||
redeemCount: store._count.redeemRecords,
|
||||
@@ -165,7 +183,12 @@ export class AdminStoresService {
|
||||
const existingAccount = await this.prisma.storeAccount.findUnique({
|
||||
where: { phone: normalizedPhone },
|
||||
});
|
||||
if (existingAccount) throw new BadRequestException('该手机号已绑定门店');
|
||||
if (existingAccount && existingAccount.isPrimary !== 1) {
|
||||
throw new BadRequestException('该手机号已是门店子账号');
|
||||
}
|
||||
if (existingAccount && existingAccount.status !== 'ACTIVE') {
|
||||
throw new BadRequestException('该手机号对应门店账号已停用');
|
||||
}
|
||||
|
||||
const partnerAccountId = BigInt(dto.partnerAccountId);
|
||||
const partnerAccount = await this.prisma.partnerAccount.findUnique({
|
||||
@@ -191,9 +214,6 @@ export class AdminStoresService {
|
||||
district: dto.district ?? '',
|
||||
address: dto.address,
|
||||
intro: dto.intro ?? null,
|
||||
bankAccountName: dto.bankAccountName ?? null,
|
||||
bankAccountNo: dto.bankAccountNo ?? null,
|
||||
bankBranch: dto.bankBranch ?? null,
|
||||
openTime: '10:00',
|
||||
closeTime: '22:00',
|
||||
status: 'OPEN',
|
||||
@@ -258,13 +278,37 @@ export class AdminStoresService {
|
||||
},
|
||||
});
|
||||
|
||||
await this.prisma.storeAccount.create({
|
||||
data: {
|
||||
storeId: store.id,
|
||||
phone: normalizedPhone,
|
||||
name: dto.accountName ?? dto.name,
|
||||
},
|
||||
});
|
||||
const bankAccountName = dto.bankAccountName ?? null;
|
||||
const bankAccountNo = dto.bankAccountNo ?? null;
|
||||
const bankBranch = dto.bankBranch ?? null;
|
||||
|
||||
if (existingAccount) {
|
||||
await this.prisma.storeAccountStore.create({
|
||||
data: { storeAccountId: existingAccount.id, storeId: store.id },
|
||||
});
|
||||
if (bankAccountName || bankAccountNo || bankBranch) {
|
||||
await this.prisma.storeAccount.update({
|
||||
where: { id: existingAccount.id },
|
||||
data: {
|
||||
...(bankAccountName != null ? { bankAccountName } : {}),
|
||||
...(bankAccountNo != null ? { bankAccountNo } : {}),
|
||||
...(bankBranch != null ? { bankBranch } : {}),
|
||||
},
|
||||
});
|
||||
}
|
||||
} else {
|
||||
await this.prisma.storeAccount.create({
|
||||
data: {
|
||||
phone: normalizedPhone,
|
||||
name: dto.accountName ?? dto.name,
|
||||
isPrimary: 1,
|
||||
bankAccountName,
|
||||
bankAccountNo,
|
||||
bankBranch,
|
||||
bindings: { create: [{ storeId: store.id }] },
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return this.detailStore(store.id);
|
||||
}
|
||||
@@ -272,12 +316,37 @@ export class AdminStoresService {
|
||||
async createStoreAccount(dto: CreateStoreAccountDto) {
|
||||
const store = await this.prisma.store.findUnique({
|
||||
where: { id: BigInt(dto.storeId) },
|
||||
include: { account: true },
|
||||
include: { bindings: true },
|
||||
});
|
||||
if (!store) throw new BadRequestException('门店不存在');
|
||||
if (store.account) throw new BadRequestException('门店已有账户');
|
||||
const primaryBound = store.bindings.length > 0
|
||||
? await this.prisma.storeAccount.findFirst({
|
||||
where: {
|
||||
isPrimary: 1,
|
||||
bindings: { some: { storeId: store.id } },
|
||||
},
|
||||
})
|
||||
: null;
|
||||
if (primaryBound) throw new BadRequestException('门店已有主账号绑定');
|
||||
|
||||
const existing = await this.prisma.storeAccount.findUnique({ where: { phone: dto.phone } });
|
||||
if (existing) {
|
||||
if (existing.isPrimary !== 1) {
|
||||
throw new BadRequestException('该手机号已是门店子账号');
|
||||
}
|
||||
await this.prisma.storeAccountStore.create({
|
||||
data: { storeAccountId: existing.id, storeId: store.id },
|
||||
});
|
||||
return serializeBigInt(existing);
|
||||
}
|
||||
|
||||
const account = await this.prisma.storeAccount.create({
|
||||
data: { storeId: store.id, phone: dto.phone, name: dto.name },
|
||||
data: {
|
||||
phone: dto.phone,
|
||||
name: dto.name,
|
||||
isPrimary: 1,
|
||||
bindings: { create: [{ storeId: store.id }] },
|
||||
},
|
||||
});
|
||||
return serializeBigInt(account);
|
||||
}
|
||||
@@ -345,9 +414,11 @@ export class AdminStoresService {
|
||||
async listStoreAccounts(query: AdminStoreAccountsQueryDto) {
|
||||
const page = query.page ?? 1;
|
||||
const pageSize = query.pageSize ?? 20;
|
||||
const where: Prisma.StoreAccountWhereInput = {};
|
||||
const where: Prisma.StoreAccountWhereInput = { isPrimary: 1 };
|
||||
if (query.phone) where.phone = { contains: query.phone };
|
||||
if (query.storeId) where.storeId = BigInt(query.storeId);
|
||||
if (query.storeId) {
|
||||
where.bindings = { some: { storeId: BigInt(query.storeId) } };
|
||||
}
|
||||
if (query.status) where.status = query.status as Prisma.EnumAccountStatusFilter['equals'];
|
||||
|
||||
const [items, total] = await Promise.all([
|
||||
@@ -357,21 +428,53 @@ export class AdminStoresService {
|
||||
skip: (page - 1) * pageSize,
|
||||
take: pageSize,
|
||||
include: {
|
||||
store: { select: { id: true, name: true, status: true, cityName: true } },
|
||||
bindings: {
|
||||
include: {
|
||||
store: { select: { id: true, name: true, status: true, cityName: true } },
|
||||
},
|
||||
},
|
||||
_count: { select: { childAccounts: true, bindings: true } },
|
||||
},
|
||||
}),
|
||||
this.prisma.storeAccount.count({ where }),
|
||||
]);
|
||||
return serializeBigInt({ items, total, page, pageSize });
|
||||
const mapped = items.map((row) => ({
|
||||
...row,
|
||||
storeCount: row._count.bindings,
|
||||
staffCount: row._count.childAccounts,
|
||||
stores: row.bindings.map((b) => b.store),
|
||||
store: row.bindings[0]?.store ?? null,
|
||||
}));
|
||||
return serializeBigInt({ items: mapped, total, page, pageSize });
|
||||
}
|
||||
|
||||
async detailStoreAccount(id: bigint) {
|
||||
const account = await this.prisma.storeAccount.findUnique({
|
||||
where: { id },
|
||||
include: { store: { include: { cityRef: true, partnerAccount: true } } },
|
||||
include: {
|
||||
bindings: {
|
||||
include: {
|
||||
store: { include: { cityRef: true, partnerAccount: true } },
|
||||
},
|
||||
},
|
||||
childAccounts: {
|
||||
include: {
|
||||
bindings: {
|
||||
include: {
|
||||
store: { select: { id: true, name: true, status: true } },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
if (!account) throw new NotFoundException('门店账号不存在');
|
||||
return serializeBigInt(account);
|
||||
return serializeBigInt({
|
||||
...account,
|
||||
stores: account.bindings.map((b) => b.store),
|
||||
store: account.bindings[0]?.store ?? null,
|
||||
staff: account.childAccounts,
|
||||
});
|
||||
}
|
||||
|
||||
async updateStoreAccount(id: bigint, dto: UpdateStoreAccountDto) {
|
||||
|
||||
Reference in New Issue
Block a user