'use strict'; const { CrudService } = require('naf-framework-mongoose-free/lib/service'); const { BusinessError, ErrorCode } = require('naf-core').Error; const _ = require('lodash'); const assert = require('assert'); const Transaction = require('mongoose-transactions'); // class GoodsService extends CrudService { constructor(ctx) { super(ctx, 'goods'); this.model = this.ctx.model.Shop.Goods; this.goodsSpecmodel = this.ctx.model.Shop.GoodsSpec; this.tran = new Transaction(); } async beforeCreate(data) { // 为商品随机生成不重复的code if (!data.code) data.code = await this.makeCode(); await this.checkCode(data.code); return data; } async beforeUpdate(filter, update) { const id = _.get(filter, 'id', _.get(filter, '_id')); const code = _.get(update, 'code'); await this.checkCode(code, id); return { filter, update }; } async query(filter, { skip = 0, limit, sort, desc, projection } = {}) { // 处理排序 let condition = _.cloneDeep(filter); condition = this.dealFilter(condition); const pipeline = this.getQueryPipeline(condition); if (parseInt(skip)) pipeline.push({ $skip: parseInt(skip) }); if (parseInt(limit)) pipeline.push({ $limit: parseInt(limit) }); const rs = await this.model.aggregate(pipeline); return rs; } async count(filter) { let condition = _.cloneDeep(filter); condition = this.dealFilter(condition); const pipeline = this.getQueryPipeline(condition); pipeline.push({ $count: 'total' }); const total = await this.model.aggregate(pipeline); return _.get(_.head(total), 'total', 0); } getQueryPipeline(filter) { const pipeline = []; const { tags, spec_name, ...others } = filter; const $match = { ...others }; if (tags) { $match.tags = { $elemMatch: { $elemMatch: { $eq: tags } } }; } pipeline.push({ $match }); if (spec_name) { const $addFields = { goods_id: { $toString: '$_id' } }; const $lookup = { from: 'goodsSpec', localField: 'goods_id', foreignField: 'goods', pipeline: [{ $match: { name: new RegExp(spec_name) } }], as: 'sp', }; const $unwind = '$sp'; const $project = { sp: 0, goods_id: 0 }; pipeline.push({ $addFields }, { $lookup }, { $unwind }, { $project }); } pipeline.push({ $sort: { sort: -1 } }); return pipeline; } /** * 检查商品编码是否唯一,若传id,则将该id排除在外 * @param {String} code 商品唯一编码 * @param {String} id 商品id */ async checkCode(code, id) { if (!code) return; const query = { code }; if (id) query.id = { $ne: id }; const num = await this.model.find(query); if (num > 0) throw new BusinessError(ErrorCode.DATA_EXISTED, '该编码已被其他商品使用'); return; } // 生成商品编码 async makeCode() { let code = ''; let is_has = false; do { code = Math.random().toString(36).substring(3, 11); const num = await this.model.find({ code }); is_has = num > 0; } while (is_has); return code; } async toDuplicate({ id }) { const data = await this.model.findById(id); if (!data) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到数据'); let specList = await this.goodsSpecmodel.find({ goods: id }); if (specList.length > 0) specList = JSON.parse(JSON.stringify(specList)); const nd = JSON.parse(JSON.stringify(data)); nd.name = `${nd.name}-复制-${new Date().getTime()}`; delete nd.id; delete nd._id; delete nd.meta; delete nd.__v; try { const id = this.tran.insert('Goods', nd); specList = specList.map(i => { delete i.id; delete i._id; delete i.meta; delete i.__v; i.goods = id; return i; }); for (const i of specList) this.tran.insert('GoodsSpec', i); await this.tran.run(); } catch (error) { console.log(error); await this.tran.rollback(); } finally { this.tran.clean(); } } } module.exports = GoodsService;