group.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. 'use strict';
  2. const { CrudService } = require('naf-framework-mongoose-free/lib/service');
  3. const { BusinessError, ErrorCode } = require('naf-core').Error;
  4. const _ = require('lodash');
  5. const assert = require('assert');
  6. const moment = require('moment');
  7. const { ObjectId } = require('mongoose').Types;
  8. //
  9. class GroupService extends CrudService {
  10. constructor(ctx) {
  11. super(ctx, 'group');
  12. this.model = this.ctx.model.Group.Group;
  13. this.goodsModel = this.ctx.model.Shop.Goods;
  14. this.goodsSpecModel = this.ctx.model.Shop.GoodsSpec;
  15. this.userModel = this.ctx.model.User.User;
  16. this.orderModel = this.ctx.model.Trade.Order;
  17. }
  18. /**
  19. * 生成团
  20. * @param {Object} orderDetail 订单详情数据
  21. * @param {Transaction} tran 数据库事务实例
  22. */
  23. async create(orderDetail, tran) {
  24. const { goods: goodsInfos, customer, shop } = orderDetail;
  25. const g = _.head(goodsInfos);
  26. const goods_id = _.get(g, 'goods._id');
  27. const goods = await this.goodsModel.findById(goods_id);
  28. const goodsSpec_id = _.get(g, '_id');
  29. const goodsSpec = await this.goodsSpecModel.findById(goodsSpec_id);
  30. const person_limit = _.get(goodsSpec, 'group_config.need_person');
  31. const leader = customer;
  32. const persons = [{ customer, status: '0', join_time: moment().format('YYYY-MM-DD HH:mm:ss') }];
  33. const obj = { shop, goods, goodsSpec, leader, persons, person_limit };
  34. const id = tran.insert('Group', obj);
  35. return id;
  36. }
  37. /**
  38. * 加入团
  39. * @param {String} customer 用户id
  40. * @param {String} group_id 团id
  41. * @param {Transaction} tran 数据库事务实例
  42. */
  43. async join(customer, group_id, tran) {
  44. const result = await this.checkGroupCanJoin({ id: group_id, customer });
  45. if (!result.result) throw new BusinessError(ErrorCode.DATA_INVALID, result.msg);
  46. const data = await this.model.findById(group_id);
  47. if (!data) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到团信息');
  48. const { persons = [], person_limit } = data;
  49. const nps = JSON.parse(JSON.stringify(persons));
  50. nps.push({ customer, status: '0', join_time: moment().format('YYYY-MM-DD HH:mm:ss') });
  51. const updateData = { persons: nps };
  52. if (person_limit <= nps.length) updateData.status = '1';
  53. tran.update('Group', group_id, updateData);
  54. }
  55. // 检查是否可以加入团
  56. async checkGroupCanJoin({ id, customer }) {
  57. const data = await this.model.findById(id);
  58. if (!data) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到团数据');
  59. const { person_limit, persons = [], status } = data;
  60. if (status === '1') return { result: false, msg: '当前团已结束' };
  61. else if (status === '-1') return { result: false, msg: '当前团已关闭' };
  62. // 检查是否已经参团
  63. const cus = _.get(this.ctx, 'user._id', customer);
  64. if (!cus) throw new BusinessError(ErrorCode.NOT_LOGIN, '用户未登录');
  65. const r = data.persons.find(f => f.customer === cus);
  66. if (r) return { result: false, msg: '您已参团' };
  67. // 为0是正常的团员
  68. const realPersons = persons.filter(f => f.status === '0');
  69. if (realPersons.length < person_limit) return { result: true };
  70. return { result: false, msg: '当前参团人数已足够' };
  71. }
  72. /**
  73. * 团购退货(订单取消&售后退款/退货)
  74. * @param {Object} params 参数
  75. * @param params.group 团id
  76. * @param params.customer 用户id
  77. * @param tran
  78. */
  79. async refund({ group, customer }, tran) {
  80. let groupData = await this.model.findById(group);
  81. if (!groupData) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到拼团数据');
  82. groupData = JSON.parse(JSON.stringify(groupData));
  83. const { persons, leader, status } = groupData;
  84. // 检查团状态,如果已经结束,就不需要该团这边的数据了
  85. if (status !== '0') return;
  86. const newPersons = JSON.parse(JSON.stringify(persons));
  87. const findPersonCondition = (c1, c2) => ObjectId(c1).equals(c2);
  88. const p = newPersons.find(f => findPersonCondition(f.customer, customer));
  89. if (!p) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到要退团的用户');
  90. const i = newPersons.findIndex(f => findPersonCondition(f.customer, customer));
  91. p.status = '1';
  92. p.out_time = moment().format('YYYY-MM-DD HH:mm:ss');
  93. newPersons[i] = p;
  94. const updateData = { persons: newPersons };
  95. // 团长退团了,根据入团时间降序,顺位成为团长
  96. if (ObjectId(leader).equals(customer)) {
  97. let newLeader;
  98. const orderList = _.orderBy(newPersons.filter(f => f.customer !== customer), [ 'status', 'join_time' ], [ 'asc', 'asc' ]);
  99. const head = _.head(orderList);
  100. console.log(head);
  101. if (head && head.status === '0') {
  102. newLeader = _.get(head, 'customer');
  103. updateData.leader = newLeader;
  104. }
  105. }
  106. // 判断是否都退团了
  107. const allRefund = newPersons.every(e => e.status === '1');
  108. if (allRefund) updateData.status = '-1';
  109. console.log(updateData);
  110. tran.update('Group', group, updateData);
  111. }
  112. /**
  113. * 获取团信息
  114. * @param {Object} query 地址参数
  115. * @param {String} query.order_id 订单id
  116. */
  117. async getGroup({ order_id }) {
  118. assert(order_id, '缺少订单信息');
  119. const order = await this.orderModel.findById(order_id, { group: 1, customer: 1 });
  120. if (!order) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到订单信息');
  121. let group = _.get(order, 'group');
  122. if (!ObjectId.isValid(group)) {
  123. const customer = _.get(order, 'customer');
  124. const groupData = await this.model.findOne({ 'persons.customer': customer }, { _id: 1 }).sort({ 'meta.createdAt': -1 });
  125. group = _.get(groupData, '_id');
  126. }
  127. return group;
  128. }
  129. async beforeQuery(filter) {
  130. const gsv = _.get(filter, 'goodsSpec._id');
  131. if (gsv) filter['goodsSpec._id'] = ObjectId(gsv);
  132. const gv = _.get(filter, 'goods._id');
  133. if (gv) filter['goods._id'] = ObjectId(gv);
  134. const p = _.get(filter, 'persons.customer');
  135. if (p) {
  136. filter['persons.status'] = '0';
  137. }
  138. return filter;
  139. }
  140. async afterQuery(filter, data) {
  141. data = JSON.parse(JSON.stringify(data));
  142. for (const i of data) {
  143. const { persons = [] } = i;
  144. for (const p of persons) {
  145. const user = await this.getUserInfo(p.customer);
  146. p.name = _.get(user, 'name');
  147. p.icon = _.get(user, 'icon');
  148. }
  149. }
  150. return data;
  151. }
  152. async afterFetch(filter, data) {
  153. data = JSON.parse(JSON.stringify(data));
  154. const { persons = [] } = data;
  155. for (const p of persons) {
  156. const user = await this.getUserInfo(p.customer);
  157. p.name = _.get(user, 'name');
  158. p.icon = _.get(user, 'icon');
  159. }
  160. return data;
  161. }
  162. async getUserInfo(id) {
  163. const user = await this.userModel.findById(id, { name: 1, icon: 1 });
  164. return user;
  165. }
  166. }
  167. module.exports = GroupService;