177 lines
6.8 KiB
TypeScript
177 lines
6.8 KiB
TypeScript
import { Provide } from "@midwayjs/core";
|
|
import { InjectRepository } from "@midwayjs/sequelize";
|
|
import { Repository } from "sequelize-typescript";
|
|
import { Op, UniqueConstraintError } from "sequelize";
|
|
import { Context } from "@midwayjs/koa";
|
|
import CustomerEquipment from "../entity/customer_equipment.entity";
|
|
import Customer from "../entity/customer.entity";
|
|
import CustomerBuilding from "../entity/customer_building.entity";
|
|
import SysUserRole from "../entity/sysUserRole.entity";
|
|
import SysRole from "../entity/sysRole.entity";
|
|
|
|
@Provide()
|
|
export class CustomerEquipmentService {
|
|
@InjectRepository(CustomerEquipment)
|
|
equipmentModel!: Repository<CustomerEquipment>;
|
|
|
|
@InjectRepository(Customer)
|
|
customerModel!: Repository<Customer>;
|
|
|
|
@InjectRepository(CustomerBuilding)
|
|
buildingModel!: Repository<CustomerBuilding>;
|
|
|
|
@InjectRepository(SysUserRole)
|
|
userRoleModel!: Repository<SysUserRole>;
|
|
|
|
@InjectRepository(SysRole)
|
|
roleModel!: Repository<SysRole>;
|
|
|
|
private async isAdmin(userId: number): Promise<boolean> {
|
|
const userRoles = await this.userRoleModel.findAll({ where: { userId }, include: [this.roleModel] });
|
|
return userRoles.some((ur) => (ur as any).role?.roleCode === "ADMIN");
|
|
}
|
|
|
|
private async isCustomerOwner(userId: number, customerId: number): Promise<boolean> {
|
|
if (await this.isAdmin(userId)) return true;
|
|
const customer = await this.customerModel.findByPk(customerId);
|
|
return !!customer && customer.salesmanId === userId;
|
|
}
|
|
|
|
private async generateEquipCode(retry: number = 0): Promise<string> {
|
|
const now = new Date();
|
|
const offsetMs = now.getTime() + 8 * 60 * 60 * 1000;
|
|
const dateLocal = new Date(offsetMs);
|
|
const yyyy = dateLocal.getUTCFullYear();
|
|
const mm = String(dateLocal.getUTCMonth() + 1).padStart(2, "0");
|
|
const dd = String(dateLocal.getUTCDate()).padStart(2, "0");
|
|
const yyyymmdd = `${yyyy}${mm}${dd}`;
|
|
|
|
const lastRecord = await this.equipmentModel.findOne({
|
|
where: { equipCode: { [Op.like]: `EQ${yyyymmdd}%` } },
|
|
order: [["equip_code", "DESC"]]
|
|
});
|
|
|
|
let newSeq = 1;
|
|
if (lastRecord) {
|
|
const lastNo = lastRecord.equipCode;
|
|
const seqStr = lastNo.slice(-3);
|
|
const seq = parseInt(seqStr, 10) || 0;
|
|
newSeq = seq + 1;
|
|
}
|
|
|
|
const newSeqStr = String(newSeq).padStart(3, "0");
|
|
const result = `EQ${yyyymmdd}${newSeqStr}`;
|
|
|
|
const exists = await this.equipmentModel.findOne({ where: { equipCode: result } });
|
|
if (exists) {
|
|
if (retry < 1) {
|
|
return this.generateEquipCode(retry + 1);
|
|
}
|
|
throw new Error("设备编码生成冲突,请重试");
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
async list(query: any, ctx: Context): Promise<any> {
|
|
const page = Number(query.page) || 1;
|
|
const pageSize = Number(query.pageSize) || 10;
|
|
const userId = ctx.state.user.userId;
|
|
const where: any = {};
|
|
|
|
if (query.keyword) {
|
|
where[Op.or] = [
|
|
{ equipCode: { [Op.like]: `%${query.keyword}%` } },
|
|
{ equipName: { [Op.like]: `%${query.keyword}%` } },
|
|
{ equipType: { [Op.like]: `%${query.keyword}%` } },
|
|
{ location: { [Op.like]: `%${query.keyword}%` } }
|
|
];
|
|
}
|
|
if (query.customerId !== undefined) where.customerId = query.customerId;
|
|
if (query.buildingId !== undefined) where.buildingId = query.buildingId;
|
|
if (query.equipType) where.equipType = query.equipType;
|
|
|
|
if (!(await this.isAdmin(userId))) {
|
|
const myCustomers = await this.customerModel.findAll({ where: { salesmanId: userId }, attributes: ["id"] });
|
|
const ids = myCustomers.map((c) => c.id);
|
|
if (ids.length === 0) {
|
|
return { code: 200, message: "获取客户设备列表成功", data: { list: [], total: 0, page: Number(page), pageSize: Number(pageSize) } };
|
|
}
|
|
if (where.customerId !== undefined) {
|
|
if (!ids.includes(where.customerId)) {
|
|
return { code: 200, message: "获取客户设备列表成功", data: { list: [], total: 0, page: Number(page), pageSize: Number(pageSize) } };
|
|
}
|
|
} else {
|
|
where.customerId = { [Op.in]: ids };
|
|
}
|
|
}
|
|
|
|
const { count, rows } = await this.equipmentModel.findAndCountAll({
|
|
where,
|
|
limit: pageSize,
|
|
offset: (page - 1) * pageSize,
|
|
order: [["created_at", "DESC"]]
|
|
});
|
|
|
|
return { code: 200, message: "获取客户设备列表成功", data: { list: rows.map((r) => r.toJSON()), total: count, page: Number(page), pageSize: Number(pageSize) } };
|
|
}
|
|
|
|
async detail(id: number, ctx: Context): Promise<any> {
|
|
const record = await this.equipmentModel.findByPk(id);
|
|
if (!record) return { code: 404, message: "客户设备不存在", data: null };
|
|
if (!(await this.isCustomerOwner(ctx.state.user.userId, record.customerId))) return { code: 403, message: "无权限访问该设备", data: null };
|
|
return { code: 200, message: "获取客户设备详情成功", data: record.toJSON() };
|
|
}
|
|
|
|
async create(data: any, ctx: Context): Promise<any> {
|
|
if (!(await this.isCustomerOwner(ctx.state.user.userId, data.customerId))) return { code: 403, message: "无权限为该客户创建设备", data: null };
|
|
|
|
try {
|
|
data.equipCode = await this.generateEquipCode();
|
|
const created = await this.equipmentModel.create(data);
|
|
return { code: 200, message: "创建客户设备成功", data: created.toJSON() };
|
|
} catch (err: any) {
|
|
if (err instanceof UniqueConstraintError && err.errors?.some((e) => e.path === "equip_code" || e.path === "uk_equip_code")) {
|
|
try {
|
|
const equipCode = await this.generateEquipCode();
|
|
const created = await this.equipmentModel.create({ ...data, equipCode });
|
|
return { code: 200, message: "创建客户设备成功", data: created.toJSON() };
|
|
} catch (_e) {
|
|
return { code: 400, message: "设备编码冲突,请重试", data: null };
|
|
}
|
|
}
|
|
throw err;
|
|
}
|
|
}
|
|
|
|
async update(id: number, data: any, ctx: Context): Promise<any> {
|
|
const record = await this.equipmentModel.findByPk(id);
|
|
if (!record) return { code: 404, message: "客户设备不存在", data: null };
|
|
if (!(await this.isAdmin(ctx.state.user.userId))) {
|
|
if (!(await this.isCustomerOwner(ctx.state.user.userId, record.customerId))) return { code: 403, message: "无权限修改该设备", data: null };
|
|
delete data.customerId;
|
|
}
|
|
|
|
delete data.equipCode;
|
|
delete data.createdAt;
|
|
delete data.created_at;
|
|
|
|
try {
|
|
await record.update(data);
|
|
return { code: 200, message: "更新客户设备成功", data: record.toJSON() };
|
|
} catch (err: any) {
|
|
if (err instanceof UniqueConstraintError) {
|
|
return { code: 400, message: "设备编码已存在", data: null };
|
|
}
|
|
throw err;
|
|
}
|
|
}
|
|
|
|
async delete(id: number, ctx: Context): Promise<any> {
|
|
const record = await this.equipmentModel.findByPk(id);
|
|
if (!record) return { code: 404, message: "客户设备不存在", data: null };
|
|
if (!(await this.isCustomerOwner(ctx.state.user.userId, record.customerId))) return { code: 403, message: "无权限删除该设备", data: null };
|
|
await record.destroy();
|
|
return { code: 200, message: "删除客户设备成功", data: null };
|
|
}
|
|
} |