同城有仓按仓库绑定承运商自动推单或自管填单,无仓/跨城走总部快递;新增仓配注册表、FulfillmentService 及三端运单追踪。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { FulfillmentProviderStatus, FulfillmentProviderType } from '@prisma/client';
|
||||
import { PrismaService } from '../../common/prisma/prisma.module';
|
||||
import { serializeBigInt } from '../../common/decorators/current-user.decorator';
|
||||
|
||||
export type CreateFulfillmentProviderInput = {
|
||||
code: string;
|
||||
name: string;
|
||||
type: FulfillmentProviderType;
|
||||
status?: FulfillmentProviderStatus;
|
||||
configJson?: string;
|
||||
capabilitiesJson?: string;
|
||||
};
|
||||
|
||||
export type UpdateFulfillmentProviderInput = Partial<CreateFulfillmentProviderInput>;
|
||||
|
||||
type Capabilities = {
|
||||
createShipment?: boolean;
|
||||
getTrack?: boolean;
|
||||
callback?: boolean;
|
||||
cancel?: boolean;
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class FulfillmentProviderService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
async listActiveApiProviders() {
|
||||
const rows = await this.prisma.fulfillmentProvider.findMany({
|
||||
where: { status: 'ACTIVE', type: 'API' },
|
||||
orderBy: { name: 'asc' },
|
||||
});
|
||||
return rows.map((row) => this.toDto(row));
|
||||
}
|
||||
|
||||
async listAll() {
|
||||
const rows = await this.prisma.fulfillmentProvider.findMany({
|
||||
orderBy: { createdAt: 'desc' },
|
||||
});
|
||||
return rows.map((row) => this.toDto(row));
|
||||
}
|
||||
|
||||
async getById(id: bigint) {
|
||||
const row = await this.prisma.fulfillmentProvider.findUnique({ where: { id } });
|
||||
if (!row) throw new NotFoundException('仓配承运商不存在');
|
||||
return this.toDto(row);
|
||||
}
|
||||
|
||||
async create(input: CreateFulfillmentProviderInput) {
|
||||
const code = input.code.trim().toUpperCase();
|
||||
if (!/^[A-Z0-9_]+$/.test(code)) {
|
||||
throw new BadRequestException('承运商编码仅支持大写字母、数字和下划线');
|
||||
}
|
||||
const existing = await this.prisma.fulfillmentProvider.findUnique({ where: { code } });
|
||||
if (existing) throw new BadRequestException('承运商编码已存在');
|
||||
|
||||
const row = await this.prisma.fulfillmentProvider.create({
|
||||
data: {
|
||||
code,
|
||||
name: input.name.trim(),
|
||||
type: input.type,
|
||||
status: input.status ?? 'ACTIVE',
|
||||
configJson: input.configJson?.trim() || null,
|
||||
capabilitiesJson: input.capabilitiesJson?.trim() || null,
|
||||
},
|
||||
});
|
||||
return this.toDto(row);
|
||||
}
|
||||
|
||||
async update(id: bigint, input: UpdateFulfillmentProviderInput) {
|
||||
await this.getById(id);
|
||||
const row = await this.prisma.fulfillmentProvider.update({
|
||||
where: { id },
|
||||
data: {
|
||||
...(input.name !== undefined ? { name: input.name.trim() } : {}),
|
||||
...(input.type !== undefined ? { type: input.type } : {}),
|
||||
...(input.status !== undefined ? { status: input.status } : {}),
|
||||
...(input.configJson !== undefined ? { configJson: input.configJson?.trim() || null } : {}),
|
||||
...(input.capabilitiesJson !== undefined
|
||||
? { capabilitiesJson: input.capabilitiesJson?.trim() || null }
|
||||
: {}),
|
||||
},
|
||||
});
|
||||
return this.toDto(row);
|
||||
}
|
||||
|
||||
parseCapabilities(raw: string | null): Capabilities | null {
|
||||
if (!raw) return null;
|
||||
try {
|
||||
return JSON.parse(raw) as Capabilities;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private toDto(row: {
|
||||
id: bigint;
|
||||
code: string;
|
||||
name: string;
|
||||
type: string;
|
||||
status: string;
|
||||
configJson: string | null;
|
||||
capabilitiesJson: string | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}) {
|
||||
return serializeBigInt({
|
||||
id: row.id.toString(),
|
||||
code: row.code,
|
||||
name: row.name,
|
||||
type: row.type,
|
||||
status: row.status,
|
||||
capabilities: this.parseCapabilities(row.capabilitiesJson),
|
||||
hasConfig: Boolean(row.configJson),
|
||||
createdAt: row.createdAt.toISOString(),
|
||||
updatedAt: row.updatedAt.toISOString(),
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user