'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 { ObjectId } = require('mongoose').Types; const Transaction = require('mongoose-transactions'); // class OrderDetailService extends CrudService { constructor(ctx) { super(ctx, 'orderdetail'); this.model = this.ctx.model.Trade.OrderDetail; this.orderModel = this.ctx.model.Trade.Order; this.goodsSpecModel = this.ctx.model.Shop.GoodsSpec; this.userCouponModel = this.ctx.model.User.UserCoupon; this.tran = new Transaction(); } async searchOrderTransport({ id }) { const orderDetail = await this.model.findById(id); if (!id) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到订单信息'); const { transport = {} } = orderDetail; const { shop_transport_no: no, shop_transport_type: type } = transport; if (!no || !type) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '缺少快递信息'); const res = await this.ctx.service.util.kd100.search({ no, type }); return res; } /** * 创建:用户支付完成后的订单 * @param {Object} body 请求参数体 * @param body.order_id 下单的id * @param {Transaction} tran 数据库事务实例 */ async create({ order_id }, tran) { assert(order_id, '缺少支付订单信息'); const order = await this.orderModel.findById(order_id); if (!order) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到支付订单的数据'); const { customer, address, goods: shopGoods, no, status, buy_time, pay, total_detail: otd } = order; if (status === '0') throw new BusinessError(ErrorCode.DATA_INVALID, '订单未支付'); const orderDetailData = { customer, address, order: order_id, buy_time, pay_time: _.get(pay, 'pay_time'), status }; const shopMoneyDetail = this.ctx.service.util.order.shopMoneyDetail(order); // 分订单计数器 let noTimes = 1; for (const s of shopGoods) { const shop = _.get(s, 'shop'); const remarks = _.get(s, 'remarks'); const goodsList = _.get(s, 'goods', []); const detailNo = `${no}-${noTimes}`; const total_detail = shopMoneyDetail[shop]; // 优惠部分分割 if (_.get(otd, 'discount_detail')) { // 如果有优惠部分,那就得找,优惠里面有没有对应的商品规格 const discount_detail = this.getGoodsListDiscountDetail(goodsList, _.get(otd, 'discount_detail')); total_detail.discount_detail = discount_detail; } noTimes++; const obj = { ...orderDetailData, shop, goods: goodsList, no: detailNo, total_detail, remarks }; // #region 团购 const type = _.get(order, 'type'); if (type === '1') { // 说明是团购,需要找订单中有没有团的id let group = _.get(order, 'group'); if (!group) { // 需要创建团,这是团长支付的单子,开团 group = await this.ctx.service.group.group.create(obj, tran); } else { // 需要参团操作,这是团员的单子,将人加入团中 await this.ctx.service.group.group.join(obj, tran); } obj.type = '1'; obj.group = group; } // #endregion tran.insert('OrderDetail', obj); // arr.push(obj); } // await this.model.insertMany(arr); } async afterUpdate(filter, body, data) { const status = _.get(data, 'status'); if (status === '3') { // 处理积分,签收再加 await this.ctx.service.user.point.addPoints(data._id); } return data; } /** * 将商品规格列表中,优惠的部分提取出来,分单用 * @param {Array} goodsList 某店的商品列表 * @param {Object} odd discount_detail 支付订单的优惠券设置 */ getGoodsListDiscountDetail(goodsList, odd) { const result = {}; for (const uc_id in odd) { const detail = odd[uc_id]; const obj = {}; for (const g of goodsList) { const { _id } = g; const gdd = detail[_id]; if (gdd) obj[_id] = gdd; } result[uc_id] = obj; } return result; } /** * 计算某店铺的金额总计 * @param {Array} goodsList 商品规格列表 */ getTotalDetail(goodsList) { const goods_total = goodsList.reduce((p, n) => this.ctx.plus(p, this.ctx.multiply(n.sell_money, n.buy_num)), 0); const freight_total = goodsList.reduce((p, n) => this.ctx.plus(p, this.ctx.multiply(n.freight, n.buy_num)), 0); return { goods_total, freight_total }; } async fetch(filter) { assert(filter); filter = await this.beforeFetch(filter); const { _id, id } = filter; if (_id || id) filter = { _id: ObjectId(_id || id) }; const { populate } = this.getRefMods(); let res = await this.model.findOne(filter).populate(populate).exec(); res = await this.afterFetch(filter, res); return res; } async afterQuery(filter, data) { data = JSON.parse(JSON.stringify(data)); for (const i of data) { const { goods } = i; const buy_num_total = goods.reduce((p, n) => this.ctx.plus(p, n.buy_num), 0); i.buy_num_total = buy_num_total; let discount = 0; const dd = _.get(i, 'total_detail.discount_detail', {}); for (const uc_id in dd) { const obj = _.get(dd, uc_id, {}); const values = Object.values(obj); if (!values.every(e => _.isNumber(e))) continue; const dm = values.reduce((p, n) => this.ctx.plus(p, n), 0); discount = this.ctx.plus(discount, dm); } i.real_pay = this.ctx.service.util.orderDetail.computedRealPay(i); } return data; } } module.exports = OrderDetailService;