'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 moment = require('moment'); const { ObjectId } = require('mongoose').Types; // class GroupService extends CrudService { constructor(ctx) { super(ctx, 'group'); this.model = this.ctx.model.Group.Group; this.goodsModel = this.ctx.model.Shop.Goods; this.goodsSpecModel = this.ctx.model.Shop.GoodsSpec; this.userModel = this.ctx.model.User.User; this.orderModel = this.ctx.model.Trade.Order; this.joinErrorRefundCode = _.get(this.app, 'config.errcode.groupJoinRefund'); } /** * 生成团 * @param {Object} orderDetail 订单详情数据 * @param {Transaction} tran 数据库事务实例 */ async create(orderDetail, tran) { const { goods: goodsInfos, customer, shop } = orderDetail; const g = _.head(goodsInfos); const goods_id = _.get(g, 'goods._id'); const goods = await this.goodsModel.findById(goods_id); const goodsSpec_id = _.get(g, '_id'); const goodsSpec = await this.goodsSpecModel.findById(goodsSpec_id); const person_limit = _.get(goodsSpec, 'group_config.need_person'); const leader = customer; const persons = [{ customer, status: '0', join_time: moment().format('YYYY-MM-DD HH:mm:ss') }]; const obj = { shop, goods, goodsSpec, leader, persons, person_limit }; const id = tran.insert('Group', obj); return id; } /** * 加入团 * @param {String} customer 用户id * @param {String} group_id 团id * @param {Transaction} tran 数据库事务实例 */ async join(customer, group_id, tran) { const result = await this.checkGroupCanJoin({ id: group_id, customer }); if (!result.result) throw new BusinessError(this.joinErrorRefundCode, result.msg); const data = await this.model.findById(group_id); if (!data) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到团信息'); const { persons = [], person_limit } = data; const nps = JSON.parse(JSON.stringify(persons)); nps.push({ customer, status: '0', join_time: moment().format('YYYY-MM-DD HH:mm:ss') }); const updateData = { persons: nps }; if (person_limit <= nps.length) updateData.status = '1'; tran.update('Group', group_id, updateData); } // 检查是否可以加入团 async checkGroupCanJoin({ id, customer }) { const data = await this.model.findById(id); if (!data) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到团数据'); const { person_limit, persons = [], status } = data; if (status === '1') return { result: false, msg: '当前团已结束' }; else if (status === '-1') return { result: false, msg: '当前团已关闭' }; // 检查是否已经参团 const cus = _.get(this.ctx, 'user._id', customer); if (!cus) throw new BusinessError(ErrorCode.NOT_LOGIN, '用户未登录'); const r = data.persons.find(f => f.customer === cus); if (r) return { result: false, msg: '您已参团' }; // 为0是正常的团员 const realPersons = persons.filter(f => f.status === '0'); if (realPersons.length < person_limit) return { result: true }; return { result: false, msg: '当前参团人数已足够' }; } /** * 团购退货(订单取消&售后退款/退货) * @param {Object} params 参数 * @param params.group 团id * @param params.customer 用户id * @param tran */ async refund({ group, customer }, tran) { let groupData = await this.model.findById(group); if (!groupData) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到拼团数据'); groupData = JSON.parse(JSON.stringify(groupData)); const { persons, leader, status } = groupData; // 检查团状态,如果已经结束,就不需要该团这边的数据了 if (status !== '0') return; const newPersons = JSON.parse(JSON.stringify(persons)); const findPersonCondition = (c1, c2) => ObjectId(c1).equals(c2); const p = newPersons.find(f => findPersonCondition(f.customer, customer)); if (!p) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到要退团的用户'); const i = newPersons.findIndex(f => findPersonCondition(f.customer, customer)); p.status = '1'; p.out_time = moment().format('YYYY-MM-DD HH:mm:ss'); newPersons[i] = p; const updateData = { persons: newPersons }; // 团长退团了,根据入团时间降序,顺位成为团长 if (ObjectId(leader).equals(customer)) { let newLeader; const orderList = _.orderBy(newPersons.filter(f => f.customer !== customer), [ 'status', 'join_time' ], [ 'asc', 'asc' ]); const head = _.head(orderList); if (head && head.status === '0') { newLeader = _.get(head, 'customer'); updateData.leader = newLeader; } } // 判断是否都退团了 const allRefund = newPersons.every(e => e.status === '1'); if (allRefund) updateData.status = '-1'; tran.update('Group', group, updateData); } /** * 获取团信息 * @param {Object} query 地址参数 * @param {String} query.order_id 订单id */ async getGroup({ order_id }) { assert(order_id, '缺少订单信息'); const order = await this.orderModel.findById(order_id, { group: 1 }); if (!order) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到订单信息'); const group = _.get(order, 'group'); return group; } async beforeQuery(filter) { const gsv = _.get(filter, 'goodsSpec._id'); if (gsv) filter['goodsSpec._id'] = ObjectId(gsv); const gv = _.get(filter, 'goods._id'); if (gv) filter['goods._id'] = ObjectId(gv); // const p = _.get(filter, 'persons.customer'); // if (p) { // filter['persons.status'] = '0'; // } return filter; } async afterQuery(filter, data) { data = JSON.parse(JSON.stringify(data)); for (const i of data) { const { persons = [] } = i; for (const p of persons) { const user = await this.getUserInfo(p.customer); p.name = _.get(user, 'name'); p.icon = _.get(user, 'icon'); } } return data; } async afterFetch(filter, data) { data = JSON.parse(JSON.stringify(data)); const { persons = [] } = data; for (const p of persons) { const user = await this.getUserInfo(p.customer); p.name = _.get(user, 'name'); p.icon = _.get(user, 'icon'); } return data; } async getUserInfo(id) { const user = await this.userModel.findById(id, { name: 1, icon: 1 }); return user; } } module.exports = GroupService;