You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
161 lines
4.1 KiB
161 lines
4.1 KiB
import { prisma } from "@/lib/prisma";
|
|
import type {
|
|
BusinessCustomerDto,
|
|
BusinessCustomerStatus,
|
|
} from "@/modules/customer/types";
|
|
import { ValidationError } from "@/modules/quote/types";
|
|
|
|
function serializeBusinessCustomer(row: {
|
|
customerId: string;
|
|
businessCustomerId: string;
|
|
name: string;
|
|
externalCode: string | null;
|
|
status: string;
|
|
remark: string | null;
|
|
createdAt: Date;
|
|
updatedAt: Date;
|
|
}): BusinessCustomerDto {
|
|
return {
|
|
customer_id: row.customerId,
|
|
business_customer_id: row.businessCustomerId,
|
|
name: row.name,
|
|
external_code: row.externalCode,
|
|
status: row.status as BusinessCustomerStatus,
|
|
remark: row.remark,
|
|
created_at: row.createdAt.toISOString(),
|
|
updated_at: row.updatedAt.toISOString(),
|
|
};
|
|
}
|
|
|
|
export async function listBusinessCustomers(customerId: string): Promise<BusinessCustomerDto[]> {
|
|
const rows = await prisma.businessCustomer.findMany({
|
|
where: { customerId, isDeleted: false },
|
|
orderBy: { createdAt: "desc" },
|
|
include: {
|
|
_count: {
|
|
select: {
|
|
users: {
|
|
where: { isDeleted: false, status: "active" },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
return rows.map((row) => ({
|
|
...serializeBusinessCustomer(row),
|
|
user_count: row._count.users,
|
|
}));
|
|
}
|
|
|
|
export async function createBusinessCustomer(input: {
|
|
customerId: string;
|
|
businessCustomerId: string;
|
|
name: string;
|
|
externalCode?: string | null;
|
|
remark?: string | null;
|
|
}): Promise<BusinessCustomerDto> {
|
|
const customerId = input.customerId.trim();
|
|
const businessCustomerId = input.businessCustomerId.trim();
|
|
const name = input.name.trim();
|
|
if (!customerId) {
|
|
throw new Error("租户标识不能为空");
|
|
}
|
|
if (!businessCustomerId) {
|
|
throw new Error("客户标识不能为空");
|
|
}
|
|
if (!name) {
|
|
throw new Error("客户名称不能为空");
|
|
}
|
|
const created = await prisma.businessCustomer.create({
|
|
data: {
|
|
customerId,
|
|
businessCustomerId,
|
|
name,
|
|
externalCode: input.externalCode?.trim() || null,
|
|
remark: input.remark?.trim() || null,
|
|
status: "active",
|
|
},
|
|
});
|
|
return serializeBusinessCustomer(created);
|
|
}
|
|
|
|
export async function updateBusinessCustomer(
|
|
customerId: string,
|
|
businessCustomerId: string,
|
|
input: {
|
|
name?: string;
|
|
externalCode?: string | null;
|
|
status?: BusinessCustomerStatus;
|
|
remark?: string | null;
|
|
},
|
|
): Promise<BusinessCustomerDto> {
|
|
const existing = await prisma.businessCustomer.findFirst({
|
|
where: { customerId, businessCustomerId, isDeleted: false },
|
|
});
|
|
if (!existing) {
|
|
throw new Error("客户不存在");
|
|
}
|
|
const data: {
|
|
name?: string;
|
|
externalCode?: string | null;
|
|
status?: BusinessCustomerStatus;
|
|
remark?: string | null;
|
|
} = {};
|
|
if (input.name !== undefined) {
|
|
const name = input.name.trim();
|
|
if (!name) {
|
|
throw new Error("客户名称不能为空");
|
|
}
|
|
data.name = name;
|
|
}
|
|
if (input.externalCode !== undefined) {
|
|
data.externalCode = input.externalCode?.trim() || null;
|
|
}
|
|
if (input.status !== undefined) {
|
|
data.status = input.status;
|
|
}
|
|
if (input.remark !== undefined) {
|
|
data.remark = input.remark?.trim() || null;
|
|
}
|
|
const updated = await prisma.businessCustomer.update({
|
|
where: {
|
|
customerId_businessCustomerId: {
|
|
customerId,
|
|
businessCustomerId,
|
|
},
|
|
},
|
|
data,
|
|
});
|
|
return serializeBusinessCustomer(updated);
|
|
}
|
|
|
|
export async function getBusinessCustomer(
|
|
customerId: string,
|
|
businessCustomerId: string,
|
|
): Promise<BusinessCustomerDto | null> {
|
|
const row = await prisma.businessCustomer.findFirst({
|
|
where: { customerId, businessCustomerId, isDeleted: false },
|
|
});
|
|
return row ? serializeBusinessCustomer(row) : null;
|
|
}
|
|
|
|
export async function assertBusinessCustomerBelongsToTenant(
|
|
customerId: string,
|
|
businessCustomerId?: string | null,
|
|
): Promise<void> {
|
|
if (!businessCustomerId) {
|
|
return;
|
|
}
|
|
const exists = await prisma.businessCustomer.count({
|
|
where: {
|
|
customerId,
|
|
businessCustomerId,
|
|
isDeleted: false,
|
|
status: "active",
|
|
},
|
|
});
|
|
if (!exists) {
|
|
throw new ValidationError("客户不存在或已停用");
|
|
}
|
|
}
|