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 DispatchPrice from "../entity/dispatch_price.entity"; // 创建/更新可写入字段白名单(priceCode 只读,服务端生成) const WRITABLE_FIELDS = ["dispatchType", "priceType", "priceMode", "unitPrice", "unit", "status", "remark"]; // 计价方式 → 默认单位兜底 const MODE_UNIT: Record = { 1: "次", 2: "小时" }; @Provide() export class DispatchPriceService { @InjectRepository(DispatchPrice) dispatchPriceModel!: Repository; // 价格编码规则:DG + 东八区 yyyymmdd + 3 位序号(当日已有记录数 +1),唯一冲突时递增重试 1 次 private async generatePriceCode(): Promise { const now = new Date(); const d = new Date(now.getTime() + 8 * 60 * 60 * 1000); const yyyymmdd = `${d.getUTCFullYear()}${String(d.getUTCMonth() + 1).padStart(2, "0")}${String(d.getUTCDate()).padStart(2, "0")}`; const prefix = `DG${yyyymmdd}`; const count = await this.dispatchPriceModel.count({ where: { priceCode: { [Op.like]: `${prefix}%` } } }); let seq = count + 1; for (let i = 0; i <= 1; i++) { const code = `${prefix}${String(seq).padStart(3, "0")}`; const exists = await this.dispatchPriceModel.findOne({ where: { priceCode: code } }); if (!exists) return code; seq++; } throw new Error("价格编码生成冲突,请重试"); } // 仅保留白名单字段 private pickWritable(data: any): any { const payload: any = {}; for (const key of WRITABLE_FIELDS) { if (data[key] !== undefined) payload[key] = data[key]; } return payload; } async list(query: any, ctx: Context): Promise { const page = Number(query.page) || 1; const pageSize = Math.min(Number(query.pageSize) || 10, 200); const where: any = {}; if (query.keyword) { where.priceCode = { [Op.like]: `%${query.keyword}%` }; } if (query.dispatchType !== undefined && query.dispatchType !== "") where.dispatchType = query.dispatchType; if (query.priceMode !== undefined && query.priceMode !== "") where.priceMode = Number(query.priceMode); if (query.status !== undefined && query.status !== "") where.status = Number(query.status); const { count, rows } = await this.dispatchPriceModel.findAndCountAll({ where, limit: pageSize, offset: (page - 1) * pageSize, order: [["id", "DESC"]] }); return { code: 200, message: "获取勘察费用列表成功", data: { list: rows.map((r) => r.toJSON()), total: count, page: Number(page), pageSize: Number(pageSize) } }; } async detail(id: number): Promise { const record = await this.dispatchPriceModel.findByPk(id); if (!record) return { code: 404, message: "价目不存在", data: null }; return { code: 200, message: "获取勘察费用详情成功", data: record.toJSON() }; } async create(data: any, ctx: Context): Promise { if (!data.dispatchType) return { code: 400, message: "派单类型不能为空", data: null }; if (data.unitPrice === undefined || data.unitPrice === null || data.unitPrice === "") { return { code: 400, message: "单价不能为空", data: null }; } const payload = this.pickWritable(data); if (payload.priceMode === undefined || payload.priceMode === null) payload.priceMode = 1; if (payload.status === undefined || payload.status === null) payload.status = 1; if (!payload.unit) payload.unit = MODE_UNIT[Number(payload.priceMode)] || "次"; try { payload.priceCode = await this.generatePriceCode(); const created = await this.dispatchPriceModel.create(payload); return { code: 200, message: "创建勘察费用成功", data: created.toJSON() }; } catch (err: any) { // 唯一冲突:重新生成编码后重试 1 次 if (err instanceof UniqueConstraintError) { try { payload.priceCode = await this.generatePriceCode(); const created = await this.dispatchPriceModel.create(payload); 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.dispatchPriceModel.findByPk(id); if (!record) return { code: 404, message: "价目不存在", data: null }; const payload = this.pickWritable(data); await record.update(payload); return { code: 200, message: "更新勘察费用成功", data: record.toJSON() }; } async delete(id: number, ctx: Context): Promise { const record = await this.dispatchPriceModel.findByPk(id); if (!record) return { code: 404, message: "价目不存在", data: null }; await record.destroy(); return { code: 200, message: "删除勘察费用成功", data: null }; } async updateStatus(id: number, status: number, ctx: Context): Promise { if (status !== 0 && status !== 1) return { code: 400, message: "状态值非法", data: null }; const record = await this.dispatchPriceModel.findByPk(id); if (!record) return { code: 404, message: "价目不存在", data: null }; await record.update({ status }); return { code: 200, message: "更新勘察费用状态成功", data: null }; } }