城市合伙人端的修改(后台)

This commit is contained in:
2026-07-12 10:19:39 +08:00
parent d0f0fa09af
commit 7f031cc4c2
74 changed files with 5430 additions and 975 deletions
@@ -0,0 +1,207 @@
import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common';
import { Prisma, WarehouseManagerType, WarehouseStatus } from '@prisma/client';
import { PrismaService } from '../../common/prisma/prisma.module';
import { serializeBigInt } from '../../common/decorators/current-user.decorator';
import { PartnerCityService } from './partner-city.service';
import type { AdminCityWarehousesQueryDto } from '../ops/dto/admin-query.dto';
export type CreateCityWarehouseInput = {
name: string;
address: string;
contactName: string;
contactPhone: string;
managerType: WarehouseManagerType;
partnerAccountId?: bigint;
status?: WarehouseStatus;
};
export type UpdateCityWarehouseInput = Partial<CreateCityWarehouseInput>;
@Injectable()
export class CityWarehouseService {
constructor(
private readonly prisma: PrismaService,
private readonly partnerCityService: PartnerCityService,
) {}
async listByCity(cityId: bigint) {
const rows = await this.prisma.cityWarehouse.findMany({
where: { cityId },
include: {
partnerAccount: { select: { id: true, companyName: true } },
},
orderBy: { createdAt: 'desc' },
});
return rows.map((row) => this.toDto(row));
}
async listAll(query: AdminCityWarehousesQueryDto) {
const page = query.page ?? 1;
const pageSize = query.pageSize ?? 20;
const where: Prisma.CityWarehouseWhereInput = {};
if (query.cityId) where.cityId = BigInt(query.cityId);
if (query.name) where.name = { contains: query.name };
if (query.managerType) where.managerType = query.managerType as Prisma.EnumWarehouseManagerTypeFilter['equals'];
if (query.status) where.status = query.status as Prisma.EnumWarehouseStatusFilter['equals'];
const [rows, total] = await Promise.all([
this.prisma.cityWarehouse.findMany({
where,
skip: (page - 1) * pageSize,
take: pageSize,
include: {
partnerAccount: { select: { id: true, companyName: true } },
city: { select: { id: true, name: true, code: true } },
},
orderBy: { createdAt: 'desc' },
}),
this.prisma.cityWarehouse.count({ where }),
]);
return serializeBigInt({
items: rows.map((row) => ({
...this.toDto(row),
cityName: row.city.name,
cityCode: row.city.code,
})),
total,
page,
pageSize,
});
}
async create(cityId: bigint, input: CreateCityWarehouseInput) {
await this.assertCityExists(cityId);
await this.validateManager(input.managerType, input.partnerAccountId, cityId);
const row = await this.prisma.cityWarehouse.create({
data: {
cityId,
name: input.name.trim(),
address: input.address.trim(),
contactName: input.contactName.trim(),
contactPhone: input.contactPhone.trim(),
managerType: input.managerType,
partnerAccountId: input.managerType === 'PARTNER' ? input.partnerAccountId : null,
status: input.status ?? 'ACTIVE',
},
include: {
partnerAccount: { select: { id: true, companyName: true } },
},
});
await this.syncManagedWarehouse(row.id, row.managerType as WarehouseManagerType, row.partnerAccountId);
return this.toDto(row);
}
async update(id: bigint, input: UpdateCityWarehouseInput) {
const current = await this.prisma.cityWarehouse.findUnique({ where: { id } });
if (!current) throw new NotFoundException('仓库不存在');
const managerType = input.managerType ?? (current.managerType as WarehouseManagerType);
const partnerAccountId =
managerType === 'PARTNER'
? input.partnerAccountId ?? current.partnerAccountId ?? undefined
: null;
await this.validateManager(managerType, partnerAccountId ?? undefined, current.cityId);
const row = await this.prisma.cityWarehouse.update({
where: { id },
data: {
...(input.name !== undefined ? { name: input.name.trim() } : {}),
...(input.address !== undefined ? { address: input.address.trim() } : {}),
...(input.contactName !== undefined ? { contactName: input.contactName.trim() } : {}),
...(input.contactPhone !== undefined ? { contactPhone: input.contactPhone.trim() } : {}),
...(input.managerType !== undefined ? { managerType: input.managerType } : {}),
...(input.managerType !== undefined || input.partnerAccountId !== undefined
? { partnerAccountId: managerType === 'PARTNER' ? partnerAccountId : null }
: {}),
...(input.status !== undefined ? { status: input.status } : {}),
},
include: {
partnerAccount: { select: { id: true, companyName: true } },
},
});
await this.syncManagedWarehouse(row.id, row.managerType as WarehouseManagerType, row.partnerAccountId);
return this.toDto(row);
}
async remove(id: bigint) {
const current = await this.prisma.cityWarehouse.findUnique({ where: { id } });
if (!current) throw new NotFoundException('仓库不存在');
await this.prisma.partnerAccount.updateMany({
where: { managedWarehouseId: id },
data: { managedWarehouseId: null },
});
await this.prisma.cityWarehouse.delete({ where: { id } });
return { ok: true, id: id.toString() };
}
private async syncManagedWarehouse(
warehouseId: bigint,
managerType: WarehouseManagerType,
partnerAccountId: bigint | null,
) {
await this.prisma.partnerAccount.updateMany({
where: { managedWarehouseId: warehouseId },
data: { managedWarehouseId: null },
});
if (managerType === 'PARTNER' && partnerAccountId) {
await this.prisma.partnerAccount.updateMany({
where: { id: partnerAccountId, managedWarehouseId: { not: warehouseId } },
data: { managedWarehouseId: null },
});
await this.prisma.partnerAccount.update({
where: { id: partnerAccountId },
data: { managedWarehouseId: warehouseId },
});
}
}
private validateManager(
managerType: WarehouseManagerType,
partnerAccountId: bigint | undefined,
cityId: bigint,
) {
if (managerType === 'PARTNER') {
if (!partnerAccountId) throw new BadRequestException('合伙人管仓须指定合伙人');
return this.partnerCityService.assertPartnerAccountBoundToCity(partnerAccountId, cityId);
}
}
private async assertCityExists(cityId: bigint) {
const city = await this.prisma.commonCity.findUnique({ where: { id: cityId } });
if (!city) throw new NotFoundException('开城城市不存在');
}
private toDto(row: {
id: bigint;
cityId: bigint;
name: string;
address: string;
contactName: string;
contactPhone: string;
managerType: string;
partnerAccountId: bigint | null;
status: string;
createdAt: Date;
updatedAt: Date;
partnerAccount?: { id: bigint; companyName: string | null } | null;
}) {
return serializeBigInt({
id: row.id.toString(),
cityId: row.cityId.toString(),
name: row.name,
address: row.address,
contactName: row.contactName,
contactPhone: row.contactPhone,
managerType: row.managerType,
partnerAccountId: row.partnerAccountId?.toString() ?? null,
partnerCompanyName: row.partnerAccount?.companyName ?? null,
status: row.status,
createdAt: row.createdAt.toISOString(),
updatedAt: row.updatedAt.toISOString(),
});
}
}