lrf il y a 2 ans
Parent
commit
42017b7ffa

+ 3 - 2
app/controller/shop/config/.goodsRate.js

@@ -1,6 +1,6 @@
 module.exports = {
   create: {
-    requestBody: ['customer', 'shop', 'goods', 'goodsSpec', 'reply', 'goods_score', 'shop_score', 'transport_score'],
+    requestBody: ['orderDetail', 'customer', 'shop', 'goods', 'goodsSpec', 'reply', 'goods_score', 'shop_score', 'transport_score'],
   },
   destroy: {
     params: ['!id'],
@@ -8,7 +8,7 @@ module.exports = {
   },
   update: {
     params: ['!id'],
-    requestBody: ['customer', 'shop', 'goods', 'goodsSpec', 'reply', 'goods_score', 'shop_score', 'transport_score'],
+    requestBody: ['orderDetail', 'customer', 'shop', 'goods', 'goodsSpec', 'reply', 'goods_score', 'shop_score', 'transport_score'],
   },
   show: {
     parameters: {
@@ -25,6 +25,7 @@ module.exports = {
         shop: 'shop',
         goods: 'goods',
         goodsSpec: 'goodsSpec',
+        orderDetail: 'orderDetail',
       },
       // options: {
       //   "meta.state": 0 // 默认条件

+ 16 - 0
app/controller/statistics/bill.js

@@ -0,0 +1,16 @@
+'use strict';
+const Controller = require('egg').Controller;
+const { CrudController } = require('naf-framework-mongoose-free/lib/controller');
+
+//
+class BillController extends Controller {
+  constructor(ctx) {
+    super(ctx);
+    this.service = this.ctx.service.statistics.bill;
+  }
+  async getBill() {
+    const data = await this.service.getBill(this.ctx.query);
+    this.ctx.ok({ data });
+  }
+}
+module.exports = CrudController(BillController, {});

+ 1 - 1
app/controller/trade/config/.orderDetail.js

@@ -24,7 +24,7 @@ module.exports = {
         order: 'order',
         shop: 'shop',
         customer: 'customer',
-        address: 'address',
+        address: 'address._id',
         no: 'no',
         'pay_time@start': 'pay_time@start',
         'pay_time@end': 'pay_time@end',

+ 2 - 0
app/model/shop/goodsRate.js

@@ -12,6 +12,7 @@ const reply = [{
 // 商品评价
 const goodsRate = {
   customer: { type: String, required: false, zh: '用户', ref: 'User.User' }, //
+  orderDetail: { type: String, required: false, zh: '订单', ref: 'Trade.OrderDetail' }, //
   shop: { type: String, required: false, zh: '店铺', ref: 'Shop.Shop' }, //
   goods: { type: String, required: false, zh: '商品', ref: 'Shop.Goods' }, //
   goodsSpec: { type: String, required: false, zh: '规格', ref: 'Shop.GoodsSpec' }, //
@@ -27,6 +28,7 @@ schema.index({ customer: 1 });
 schema.index({ shop: 1 });
 schema.index({ goods: 1 });
 schema.index({ goodsSpec: 1 });
+schema.index({ orderDetail: 1 });
 
 schema.plugin(metaPlugin);
 

+ 54 - 0
app/service/statistics/bill.js

@@ -0,0 +1,54 @@
+'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');
+
+// 对账
+class BillService extends CrudService {
+  constructor(ctx) {
+    super(ctx, 'bill');
+    this.orderDetailModel = this.ctx.model.Trade.OrderDetail;
+    this.afterSaleModel = this.ctx.model.Trade.AfterSale;
+  }
+  /**
+   * 生成店铺对账单
+   ** 根据店铺id,开始时间和结束时间,形成对账单
+   * @param {Object} query 查询条件
+   */
+  async getBill(query) {
+    const { shop, start, end } = query;
+    assert(start, '缺少开始时间');
+    assert(end, '缺少结束时间');
+    const pipline = [];
+    // TODO: 商店过滤
+    // 时间过滤
+    const q = { $match: { $and: [{ pay_time: { $gte: start } }, { pay_time: { $lte: end } }] } };
+    pipline.push(q);
+    // #region 整理数据
+    // 整理最外层的orderDetail,没用的裁掉
+    const $project = {
+      type: 1,
+      total_detail: 1,
+      no: 1,
+      goods: {
+        _id: 1,
+        sell_money: 1,
+        buy_num: 1,
+        freight: 1,
+        group_config: { money: 1 },
+        name: 1,
+        goods: { name: 1 },
+      },
+    };
+    pipline.push({ $project });
+    // 按规格平铺开
+    pipline.push({ $unwind: '$goods' });
+    // #endregion
+    const orderList = await this.orderDetailModel.aggregate(pipline);
+    return orderList;
+
+  }
+}
+
+module.exports = BillService;

+ 96 - 15
app/service/trade/orderDetail.js

@@ -13,6 +13,8 @@ class OrderDetailService extends CrudService {
     this.orderModel = this.ctx.model.Trade.Order;
     this.goodsSpecModel = this.ctx.model.Shop.GoodsSpec;
     this.userCouponModel = this.ctx.model.User.UserCoupon;
+    this.goodsRateModel = this.ctx.model.Shop.GoodsRate;
+    this.afterSaleModel = this.ctx.model.Trade.AfterSale;
     this.tran = new Transaction();
   }
   async searchOrderTransport({ id }) {
@@ -129,24 +131,103 @@ class OrderDetailService extends CrudService {
     return res;
   }
 
-  async afterQuery(filter, data) {
-    data = JSON.parse(JSON.stringify(data));
-    for (const i of data) {
+
+  async query(filter, { skip = 0, limit, sort, desc, projection } = {}) {
+    // 处理排序
+    if (sort && _.isString(sort)) {
+      sort = { [sort]: desc ? -1 : 1 };
+    } else if (sort && _.isArray(sort)) {
+      sort = sort.map(f => ({ [f]: desc ? -1 : 1 })).reduce((p, c) => ({ ...p, ...c }), {});
+    }
+    let condition = _.cloneDeep(filter);
+    condition = await this.beforeQuery(condition);
+    condition = this.dealFilter(condition);
+    // 过滤出ref字段
+    const pipline = [{ $sort: { 'meta.createdAt': -1 } }];
+    pipline.push({ $match: condition });
+    // 整理字段
+    // 店铺需要的字段
+    pipline.push({ $addFields: { shop_id: { $toObjectId: '$shop' } } });
+    pipline.push({
+      $lookup: {
+        from: 'shop',
+        localField: 'shop_id',
+        foreignField: '_id',
+        as: 'shopInfo',
+      },
+    });
+    pipline.push({ $addFields: { customer_id: { $toObjectId: '$customer' } } });
+    pipline.push({
+      $lookup: {
+        from: 'user',
+        localField: 'customer_id',
+        foreignField: '_id',
+        as: 'customerInfo',
+      },
+    });
+
+    pipline.push({ $unwind: '$shopInfo' });
+    pipline.push({ $unwind: '$customerInfo' });
+    const lastProject = {
+      $project: {
+        _id: 1,
+        type: 1,
+        order: 1,
+        buy_time: 1,
+        pay_time: 1,
+        status: 1,
+        no: 1,
+        group: 1,
+        goods: {
+          _id: 1,
+          sell_money: 1,
+          freight: 1,
+          name: 1,
+          buy_num: 1,
+          group_config: 1,
+          goods: { name: 1, file: 1 },
+          file: 1,
+        },
+        shop: {
+          _id: '$shopInfo._id',
+          name: '$shopInfo.name',
+        },
+        customer: {
+          _id: '$customerInfo._id',
+          name: '$customerInfo.name',
+        },
+      },
+    };
+    pipline.push(lastProject);
+    const qPipline = _.cloneDeep(pipline);
+    if (parseInt(skip) >= 0) qPipline.push({ $skip: parseInt(skip) });
+    if (parseInt(limit)) qPipline.push({ $limit: parseInt(limit) });
+    const rs = await this.model.aggregate(qPipline);
+    const list = [];
+    for (const i of rs) {
       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);
+      const obj = _.cloneDeep(i);
+      const real_pay = this.ctx.service.util.orderDetail.computedRealPay(obj);
+      obj.real_pay = real_pay;
+      obj.buy_num_total = goods.reduce((p, n) => this.ctx.plus(p, n.buy_num), 0);
+      for (const og of obj.goods) {
+        const { file = [] } = og;
+        const gfile = _.get(og, 'goods.file', []);
+        const nf = [ ...file, ...gfile ];
+        const url = _.get(_.head(nf), 'url');
+        og.url = url;
+        delete og.file;
+        delete og.goods.file;
       }
-      i.real_pay = this.ctx.service.util.orderDetail.computedRealPay(i);
+      // 评价与售后
+      const rate = await this.goodsRateModel.findOne({ orderDetail: obj._id }, { _id: 1 });
+      obj.rate = _.get(rate, '_id');
+      const asum = await this.afterSaleModel.count({ orderDetail: obj._id });
+      obj.is_afterSale = asum > 0;
+      list.push(obj);
     }
-    return data;
+
+    return list;
   }
 }
 

+ 13 - 0
app/z_router/statistics/bill.js

@@ -0,0 +1,13 @@
+'use strict';
+// 路由配置
+const path = require('path');
+const regPath = path.resolve('app', 'public', 'routerRegister');
+const routerRegister = require(regPath);
+const rkey = 'statistics/bill';
+const ckey = 'statistics.bill';
+const keyZh = '账单';
+const routes = [{ method: 'get', path: `${rkey}/getBill`, controller: `${ckey}.getBill`, name: `${ckey}getBill`, zh: `${keyZh}账单` }];
+
+module.exports = app => {
+  routerRegister(app, routes, keyZh, rkey, ckey);
+};

+ 1 - 0
app/z_router/statistics/index.js

@@ -3,4 +3,5 @@
  */
 module.exports = app => {
   require('./admin')(app); // 中台统计
+  require('./bill')(app); // 账单
 };