123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- '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');
- const moment = require('moment');
- //
- class ActOrderService extends CrudService {
- constructor(ctx) {
- super(ctx, 'actorder');
- this.model = this.ctx.model.Trade.ActOrder;
- this.orderDetailModel = this.ctx.model.Trade.OrderDetail;
- this.orderModel = this.ctx.model.Trade.Order;
- this.platformActModel = this.ctx.model.System.PlatformAct;
- this.gjaModel = this.ctx.model.Shop.GoodsJoinAct;
- this.tran = new Transaction();
- }
- /**
- * 创建订单与活动的关系
- * @param {String} id 订单id
- * @param {Object} data 订单数据
- * @param {Transaction} tran 数据库事务实例
- */
- async create(id, data, tran) {
- // 检查活动类型为1的 活动,再查下面的商品
- const actList = await this.platformActModel.find({ is_use: '0', type: { $ne: '0' } }, { _id: 1 });
- if (actList.length <= 0) return;
- // 整理出订单内的商品id
- const odGoods = data.goods.map(i => {
- const { _id: spec_id, goods } = i;
- const goods_id = _.get(goods, '_id');
- return { spec_id, goods_id };
- });
- const actOrderList = [];
- // 循环所有活动,找当前购买的商品,是否出现在这些活动之中,如果出现,就需要添加关系
- for (const act of actList) {
- const { _id: platformAct } = act;
- const query = { goods: odGoods.map(i => i.goods_id), platformAct };
- const goodsList = await this.gjaModel.find(query);
- // 获取受影响的商品
- const influenceGoods = goodsList.map(i => i.goods);
- if (influenceGoods.length <= 0) continue;
- const actOrder = { platform_act: platformAct, order_detail: id };
- // 用受影响的 商品id, 在 odGoods 中 找到对应的数据作为 actOrder的goods
- actOrder.goods = odGoods.filter(f => influenceGoods.includes(f.goods_id));
- actOrderList.push(actOrder);
- }
- for (const data of actOrderList) {
- tran.insert('ActOrder', data);
- }
- }
- // 改为聚合查询
- async query(filter, { skip = 0, limit, sort, desc, projection } = {}) {
- const { platform_act, order_detail, is_deal, goods } = filter;
- const pipeline = [];
- const modelMatch = {};
- if (platform_act) modelMatch.platform_act = platform_act;
- if (order_detail) modelMatch.order_detail = order_detail;
- if (is_deal) modelMatch.is_deal = is_deal;
- if (Object.keys(modelMatch).length > 0) pipeline.push({ $match: modelMatch });
- // 表关联
- pipeline.push({ $addFields: { order_detail_id: { $toObjectId: '$order_detail' } } });
- const odLookUp = {
- from: 'orderDetail',
- localField: 'order_detail_id',
- foreignField: '_id',
- as: 'odi',
- };
- // 加入查询条件, 限制下订单状态
- const odPipeline = [{ $match: { status: { $in: [ '1', '2-', '2', '3' ] } } }];
- if (goods) {
- odPipeline.push({ $match: { 'goods.goods.name': new RegExp(goods) } });
- }
- odPipeline.push({ $project: { name: 1, pay_time: 1, no: 1, customer: 1, shop: 1, status: 1, address: { name: 1, phone: 1, address: 1 } } });
- odPipeline.push({ $addFields: { shop_id: { $toObjectId: '$shop' } } });
- odPipeline.push({
- $lookup: {
- from: 'shop',
- localField: 'shop_id',
- foreignField: '_id',
- pipeline: [{ $project: { name: 1 } }],
- as: 'shopInfo',
- },
- });
- odPipeline.push({ $addFields: { customer_id: { $toObjectId: '$customer' } } });
- odPipeline.push({
- $lookup: {
- from: 'user',
- localField: 'customer_id',
- foreignField: '_id',
- pipeline: [{ $project: { name: 1 } }],
- as: 'cInfo',
- },
- });
- odPipeline.push({
- $project: {
- _id: 0,
- order_detail: '$_id',
- name: 1,
- pay_time: 1,
- no: 1,
- custumer_name: { $first: '$cInfo.name' },
- shop_name: { $first: '$shopInfo.name' },
- status: 1,
- address: { name: 1, phone: 1, address: 1 },
- },
- });
- odLookUp.pipeline = odPipeline;
- pipeline.push({ $lookup: odLookUp });
- pipeline.push({ $unwind: '$odi' });
- pipeline.push({ $replaceRoot: { newRoot: { $mergeObjects: [ '$$ROOT', '$$ROOT.odi' ] } } });
- pipeline.push({ $project: { odi: 0 } });
- // 查询管道
- const fp = _.cloneDeep(pipeline);
- pipeline.push({ $sort: { pay_time: 1 } });
- if (_.isNumber(skip) && skip > 0) pipeline.push(skip);
- if (_.isNumber(limit) && limit > 0) pipeline.push(limit);
- const data = await this.model.aggregate(fp);
- // 总数管道
- const tp = _.cloneDeep(pipeline);
- tp.push({ $count: 'total' });
- const tr = await this.model.aggregate(tp);
- return { data, total: _.get(_.head(tr), 'total', 0) };
- }
- /**
- * 获取本单最大退款金额
- * @param {String} id 数据id
- */
- async getRefundMaxMoney({ id }) {
- const data = await this.model.findById(id);
- if (!data) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到活动订单');
- const { order_detail, goods } = data;
- const orderDetail = await this.orderDetailModel.findById(order_detail);
- if (!orderDetail) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到订单信息');
- const moneyDetail = this.ctx.service.util.orderDetail.moneyDetail(orderDetail);
- let maxMoney = 0;
- // 判断订单类型,取出不同的实付价格
- let priceKey;
- if (_.get(orderDetail, 'type', '0') === '1') priceKey = 'ggrp';
- else priceKey = 'grp';
- for (const g of goods) {
- // 该规格总价明细
- const detail = _.get(moneyDetail, g.spec_id);
- if (!detail) continue;
- // 改规格实际支付价格
- const rp = _.get(detail, priceKey, 0);
- maxMoney = this.ctx.plus(maxMoney, rp);
- }
- // 找total_detail中的act字段,减掉 活动相关 已经退款的金额;
- const act = _.get(orderDetail, 'total_detail.act', []);
- const isRefundParts = act.reduce((p, n) => this.ctx.plus(p, n.money), 0);
- const canRefundParts = this.ctx.minus(maxMoney, isRefundParts);
- return canRefundParts;
- }
- /**
- * 批量返现
- * @param {Object} body 参数体
- * @param {Array} body.data 返现数组数据
- * @property {Number} money 退款金额
- * @property {String} id 数据id
- */
- async toRefund({ data }) {
- for (const i of data) {
- const { id, money, no } = i;
- const max = await this.getRefundMaxMoney({ id });
- if (this.ctx.minus(max, money) < 0) throw new BusinessError(ErrorCode.DATA_INVALID, `订单号:${no} 超过最大退款金额`);
- }
- try {
- const failed = [];
- for (const i of data) {
- const { id: act_id, money } = i;
- const obj = { act_id, money, time: moment().format('YYYY-MM-DD HH:mm:ss') };
- const actOrder = await this.model.findById(act_id, 'order_detail');
- const { order_detail } = actOrder;
- const orderDetail = await this.orderDetailModel.findById(order_detail, 'total_detail');
- const total_detail = _.get(orderDetail, 'total_detail', {});
- // 组织退款信息 {order_no,out_refund_no,money,reson}
- const refundData = await this.toMakeRefundData(i);
- obj.data = refundData;
- total_detail.act = [ ..._.get(total_detail, 'act', []), obj ];
- try {
- // 退款
- await this.ctx.service.trade.pay.refund(refundData);
- this.tran.update('OrderDetail', order_detail, { total_detail });
- } catch (error) {
- // next
- failed.push(obj);
- console.log(error);
- }
- }
- await this.tran.run();
- } catch (error) {
- await this.tran.rollback();
- } finally {
- this.tran.clean();
- }
- }
- /**
- * 根据促销返现数据生成退款数据
- * @param {Object} data 前端退款数据
- */
- async toMakeRefundData(data) {
- const { id, money } = data;
- const obj = { money, reason: '促销返现' };
- const actOrder = await this.model.findById(id);
- if (!actOrder) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到活动订单');
- const orderDetail = await this.orderDetailModel.findById(actOrder.order_detail, 'order');
- if (!orderDetail) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到订单信息');
- const order = await this.orderModel.findById(orderDetail.order, 'pay');
- if (!order) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到支付订单信息');
- const order_no = _.get(order, 'pay.pay_no');
- if (!order_no) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到支付单号');
- obj.order_no = order_no;
- const out_refund_no = `${order_no}-r-${_.random(10000, 99999)}`;
- obj.out_refund_no = out_refund_no;
- return obj;
- }
- }
- module.exports = ActOrderService;
|