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; @InjectRepository(Customer) customerModel!: Repository; @InjectRepository(CustomerBuilding) buildingModel!: Repository; @InjectRepository(SysUserRole) userRoleModel!: Repository; @InjectRepository(SysRole) roleModel!: Repository; private async isAdmin(userId: number): Promise { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 }; } }