group.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  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. }
  17. /**
  18. * 生成团
  19. * @param {Object} orderDetail 订单详情数据
  20. * @param {Transaction} tran 数据库事务实例
  21. */
  22. async create(orderDetail, tran) {
  23. const { goods: goodsInfos, customer, shop } = orderDetail;
  24. const g = _.head(goodsInfos);
  25. const goods_id = _.get(g, 'goods._id');
  26. const goods = await this.goodsModel.findById(goods_id);
  27. const goodsSpec_id = _.get(g, '_id');
  28. const goodsSpec = await this.goodsSpecModel.findById(goodsSpec_id);
  29. const person_limit = _.get(goodsSpec, 'group_config.need_person');
  30. const leader = customer;
  31. const persons = [{ customer, status: '0', join_time: moment().format('YYYY-MM-DD HH:mm:ss') }];
  32. const obj = { shop, goods, goodsSpec, leader, persons, person_limit };
  33. const id = tran.insert('Group', obj);
  34. return id;
  35. }
  36. /**
  37. * 加入团
  38. * @param {String} customer 用户id
  39. * @param {String} group_id 团id
  40. * @param {Transaction} tran 数据库事务实例
  41. */
  42. async join(customer, group_id, tran) {
  43. const result = await this.checkGroupCanJoin({ id: group_id });
  44. if (!result.result) throw new BusinessError(ErrorCode.DATA_INVALID, result.msg);
  45. const data = await this.model.findById(group_id);
  46. if (!data) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到团信息');
  47. const { persons = [], person_limit } = data;
  48. const nps = JSON.parse(JSON.stringify(persons));
  49. nps.push({ customer, status: '0', join_time: moment().format('YYYY-MM-DD HH:mm:ss') });
  50. const updateData = { persons: nps };
  51. if (person_limit <= nps.length) updateData.status = '1';
  52. tran.update('Group', group_id, updateData);
  53. }
  54. // 检查是否可以加入团
  55. async checkGroupCanJoin({ id, customer }) {
  56. const data = await this.model.findById(id);
  57. if (!data) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到团数据');
  58. const { person_limit, persons = [], status } = data;
  59. if (status === '1') return { result: false, msg: '当前团已结束' };
  60. else if (status === '-1') return { result: false, msg: '当前团已关闭' };
  61. // 检查是否已经参团
  62. const cus = _.get(this.ctx, 'user._id', customer);
  63. if (!cus) throw new BusinessError(ErrorCode.NOT_LOGIN, '用户未登录');
  64. const r = data.persons.find(f => f.customer === cus);
  65. if (r) return { result: false, msg: '您已参团' };
  66. // 为0是正常的团员
  67. const realPersons = persons.filter(f => f.status === '0');
  68. if (realPersons.length < person_limit) return { result: true };
  69. return { result: false, msg: '当前参团人数已足够' };
  70. }
  71. /**
  72. * 团购退货(订单取消&售后退款/退货)
  73. * @param {Object} params 参数
  74. * @param params.group 团id
  75. * @param params.customer 用户id
  76. * @param tran
  77. */
  78. async refund({ group, customer }, tran) {
  79. const groupData = await this.model.findById(group);
  80. if (!groupData) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到拼团数据');
  81. const { persons, leader } = groupData;
  82. const newPersons = JSON.parse(JSON.stringify(persons));
  83. const findPersonCondition = (c1, c2) => c1 === c2;
  84. const p = newPersons.find(f => findPersonCondition(f.customer, customer));
  85. if (!p) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到要退团的用户');
  86. const i = newPersons.findIndex(f => findPersonCondition(f.customer, customer));
  87. p.status = '1';
  88. newPersons[i] = p;
  89. const updateData = { newPersons };
  90. // 团长退团了,根据入团时间降序,顺位成为团长
  91. if (leader === customer) {
  92. let newLeader;
  93. const orderList = _.orderBy(newPersons, [ 'status', 'join_time' ], [ 'asc', 'asc' ]);
  94. const head = _.head(orderList);
  95. if (head && head.status === '0') {
  96. newLeader = _.get(head, 'customer');
  97. updateData.leader = newLeader;
  98. }
  99. }
  100. tran.update('Group', group, updateData);
  101. }
  102. async beforeQuery(filter) {
  103. const gsv = _.get(filter, 'goodsSpec._id');
  104. const gv = _.get(filter, 'goods._id');
  105. if (gv) filter['goods._id'] = ObjectId(gv);
  106. if (gsv) filter['goodsSpec._id'] = ObjectId(gsv);
  107. return filter;
  108. }
  109. async afterQuery(filter, data) {
  110. data = JSON.parse(JSON.stringify(data));
  111. for (const i of data) {
  112. const { persons = [] } = i;
  113. for (const p of persons) {
  114. const user = await this.userModel.findById(p.customer, { name: 1, icon: 1 });
  115. p.name = _.get(user, 'name');
  116. p.icon = _.get(user, 'icon');
  117. }
  118. }
  119. return data;
  120. }
  121. }
  122. module.exports = GroupService;