123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- '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;
|