'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 moment = require('moment'); const Transaction = require('mongoose-transactions'); // class AfterSaleService extends CrudService { constructor(ctx) { super(ctx, 'aftersale'); this.model = this.ctx.model.Trade.AfterSale; this.orderDetailModel = this.ctx.model.Trade.OrderDetail; this.tran = new Transaction(); } async create({ order_id, goods_id, ...others }) { const orderDetail = await this.orderDetailModel.findById(order_id); if (!orderDetail) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到订单信息'); // 查询该商品是不是申请退款,如果是申请退款,查看是否有记录,如果有记录,是否已经退款 const type = _.get(others, 'type'); if (type === '0') { const record = await this.model.find({ order_detail: order_id, 'goods._id': goods_id, type: '0' }); if (record) { const rs = _.get(record, 'status'); if (rs === '0' || rs === '1') throw new BusinessError(ErrorCode.DATA_EXISTED, '已申请退款,正在等待处理'); else if (rs === '-1') throw new BusinessError(ErrorCode.DATA_EXISTED, '该商品已退款'); } } else { // 如果是换货/维修,那么可以重复多次,也就是需要查当前该货物是否有未结束的售后,如果有,则不能添加 const num = await this.model.count({ order_detail: order_id, 'goods._id': goods_id, type, status: [ '2', '3' ] }); if (num) throw new BusinessError(ErrorCode.DATA_INVALID, '商品正在售后中'); } const { goods: goodsList } = orderDetail; const goods = goodsList.find(f => ObjectId(f._id).equals(goods_id)); if (!goods) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未在当前订单中搜索到要售后的商品'); const { shop, customer } = orderDetail; const apply_time = moment().format('YYYY-MM-DD HH:mm:ss'); const obj = { order_detail: order_id, customer, shop, goods, ...others, apply_time, status: '0' }; await this.model.create(obj); } async update(filter, update, { projection } = {}) { assert(filter); assert(update); const beforeUpdateResult = await this.beforeUpdate(filter, update); filter = beforeUpdateResult.filter; update = beforeUpdateResult.update; const { _id, id } = filter; if (_id || id) filter = { _id: ObjectId(_id || id) }; // 检查数据是否存在 const entity = await this.model.findOne(filter).exec(); if (!entity) throw new BusinessError(ErrorCode.DATA_NOT_EXIST); // 修改数据 try { this.tran.update('AfterSale', entity._id, update); await this.tran.run(); const type = _.get(entity, 'type'); const status = _.get(update, 'status'); // 同意退款,则直接进行退款,然后再将状态修改为已退款 if (type === '0' && status === '1') { await this.toRefund({ afterSale_id: entity._id, goods_id: _.get(entity, 'goods._id') }, this.tran); this.tran.update('AfterSale', entity._id, { status: '-1' }); } await this.tran.run(); } catch (error) { console.error(error); await this.tran.rollback(); throw new BusinessError(ErrorCode.SERVICE_FAULT, '售后:修改失败'); } const reSearchData = await this.model.findOne(filter, projection).exec(); return reSearchData; } /** * 退款 * @param {Object} param 参数 * @param param.afterSale_id 售后申请id * @param param.goods_id 商品规格id * @param {Transaction} tran 事务的实例 */ async toRefund({ afterSale_id, goods_id }, tran) { const data = await this.model.findById(afterSale_id); if (!data) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到售后信息'); const { populate } = this.ctx.service.trade.orderDetail.getRefMods(); const orderDetail = await this.orderDetailModel.findById(data.order_detail).populate(populate); if (!orderDetail) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到售后信息的订单'); // 计算商品原价 let money = this.ctx.multiply(_.get(data, 'goods.sell_money'), _.get(data, 'goods.buy_num')); const reason = _.get(data, 'desc'); const order_no = _.get(orderDetail, 'order.pay.pay_no'); if (!order_no) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到支付订单号'); // 查查优惠中,是否有这个商品:将这个商品的每一个优惠券的优惠部分都加一起,然后用原价-优惠价=实付价 const discount_detail = _.get(orderDetail, 'total_detail.discount_detail'); if (discount_detail) { let discountMoney = 0; for (const uc_id in discount_detail) { const detail = discount_detail[uc_id]; const gd = detail[goods_id]; if (gd && !_.get(gd, 'refund', false)) { discountMoney = this.ctx.plus(discountMoney, gd.discountMoney); gd.refund = true; } } money = this.ctx.minus(money, discountMoney); } // 找下当前这个订单有多少次售后记录 let num = await this.model.count({ order_detail: data.order_detail }); num += 1; // 组成退款单号 const out_refund_no = `${order_no}-r${num}`; const obj = { reason, money, order_no, out_refund_no }; // 退款请求 await this.ctx.service.trade.pay.refund(obj); // 检查优惠券是否都退了 let allRefund = true; for (const dd of discount_detail) { for (const d in dd) { if (!_.get(d, 'refund')) { allRefund = false; break; } } } if (allRefund) { // 优惠券部分全都退了,那就把优惠券退了 const couponIds = Object.keys(discount_detail); for (const id of couponIds) { tran.update('UserCoupon', id, { status: '0' }); } } // 修改订单详情的优惠券标记 tran.update('OrderDetail', orderDetail._id, { 'total_detail.discount_detail': discount_detail }); } } module.exports = AfterSaleService;