|
@@ -1,4 +1,5 @@
|
|
|
'use strict';
|
|
|
+const assert = require('assert');
|
|
|
const _ = require('lodash');
|
|
|
const { ObjectId } = require('mongoose').Types;
|
|
|
const { CrudService } = require('naf-framework-mongoose/lib/service');
|
|
@@ -18,7 +19,6 @@ class TransportService extends CrudService {
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
/**
|
|
|
* 签收
|
|
|
* @param {Object} data 运输单数据
|
|
@@ -26,15 +26,166 @@ class TransportService extends CrudService {
|
|
|
async sign(data) {
|
|
|
const { id, sign_time } = data;
|
|
|
const transport = await this.model.find({ _id: ObjectId(id) });
|
|
|
- if (!transport) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到运输单信息');
|
|
|
- const { split, no } = data;
|
|
|
+ if (!transport) {
|
|
|
+ throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到运输单信息');
|
|
|
+ }
|
|
|
+ const { goods, no } = data;
|
|
|
// 修改订单部分
|
|
|
- await this.os.arriveGoods(split, no);
|
|
|
+ await this.os.arriveGoods(goods, no);
|
|
|
// 修改运输单部分
|
|
|
transport.status = '1';
|
|
|
if (sign_time) transport.sign_time = sign_time;
|
|
|
return await transport.save();
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 运输核算信息组织
|
|
|
+ * @param {Object} { ids, type } ids:运输单id集合; type:once=>单趟 ; car=> 单车
|
|
|
+ */
|
|
|
+ async calculate({ ids }) {
|
|
|
+ // 获取要核算的运输列表
|
|
|
+ let tList = await this.model.find({ _id: ids.map(i => ObjectId(i)) });
|
|
|
+ if (tList.length > 0) tList = JSON.parse(JSON.stringify(tList));
|
|
|
+ const res = { inBill: await this.getInBill(tList), outBill: this.getOutBill(tList) };
|
|
|
+ // 计算合计
|
|
|
+ const count = {};
|
|
|
+ // 收入采用税后实收
|
|
|
+ count.im = _.round(
|
|
|
+ res.inBill.reduce((p, n) => p + (n.sh_ss || 0), 0),
|
|
|
+ 2
|
|
|
+ );
|
|
|
+ // 运输支出合计
|
|
|
+ count.om = _.round(
|
|
|
+ res.outBill.reduce((p, n) => p + (n.money || 0), 0),
|
|
|
+ 2
|
|
|
+ );
|
|
|
+ // 总计
|
|
|
+ count.total = _.round(count.im - count.om, 2);
|
|
|
+ res.count = count;
|
|
|
+ return res;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 单车核算
|
|
|
+ * @param {Object} { car_no, start, end } 车id, 开始时间, 结束时间: 时间默认为发货时间
|
|
|
+ */
|
|
|
+ async carCalculate({ car_no, start, end }) {
|
|
|
+ assert(start, '缺少时间范围-开始时间');
|
|
|
+ assert(end, '缺少时间范围-结束时间');
|
|
|
+ let query = { 'send_time@start': start, 'send_time@end': end, 'supplier.car_no': car_no };
|
|
|
+ let tList = await this.query(query);
|
|
|
+ if (tList.length > 0) tList = JSON.parse(JSON.stringify(tList));
|
|
|
+ const res = { inBill: await this.getInBill(tList), outBill: this.getOutBill(tList) };
|
|
|
+ // 日常维护部分
|
|
|
+ query = { 'date@start': start, 'date@end': end };
|
|
|
+ const daily = await this.ctx.service.car.daily.query({ car_no, ...query });
|
|
|
+ res.daily = daily;
|
|
|
+ // 计算合计
|
|
|
+ const count = {};
|
|
|
+ // 收入采用税后实收
|
|
|
+ count.im = _.round(
|
|
|
+ res.inBill.reduce((p, n) => p + (n.sh_ss || 0), 0),
|
|
|
+ 2
|
|
|
+ );
|
|
|
+ // 运输支出合计
|
|
|
+ count.om = _.round(
|
|
|
+ res.outBill.reduce((p, n) => p + (n.money || 0), 0),
|
|
|
+ 2
|
|
|
+ );
|
|
|
+ // 日常支出
|
|
|
+ count.dm = _.round(
|
|
|
+ res.daily.reduce((p, n) => p + (n.money || 0), 0),
|
|
|
+ 2
|
|
|
+ );
|
|
|
+ // 总计
|
|
|
+ count.total = _.round(count.im - count.om - count.dm, 2);
|
|
|
+ res.count = count;
|
|
|
+ return res;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将所选的运输单的收入整合至一个列表
|
|
|
+ * @param {Array} list 运输列表
|
|
|
+ */
|
|
|
+ async getInBill(list) {
|
|
|
+ // 原则,少查询,多操作
|
|
|
+ const split_ids = list.map(i => i.goods.map(g => g.split_id)).flat();
|
|
|
+ const orders = await this.ctx.model.Order.find({
|
|
|
+ 'split._id': split_ids.map(i => ObjectId(i)),
|
|
|
+ });
|
|
|
+ list = list.map(i => {
|
|
|
+ const { no, route } = i;
|
|
|
+ i.goods = i.goods.map(g => {
|
|
|
+ const order = orders.find(f =>
|
|
|
+ f.split.find(s => ObjectId(s._id).equals(g.split_id))
|
|
|
+ );
|
|
|
+ if (order) {
|
|
|
+ g.order_no = _.get(order, 'order_no');
|
|
|
+ g.no = no;
|
|
|
+ g.route = route;
|
|
|
+ }
|
|
|
+ return g;
|
|
|
+ });
|
|
|
+ return i.goods;
|
|
|
+ });
|
|
|
+ return _.flattenDeep(list);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将所选的运输单的运输支出整合至一个列表
|
|
|
+ * @param {Array} list 运输列表
|
|
|
+ */
|
|
|
+ getOutBill(list) {
|
|
|
+ list = list.map(i => {
|
|
|
+ const { no, route } = i;
|
|
|
+ i.out_bill = i.out_bill.map(o => {
|
|
|
+ o.no = no;
|
|
|
+ o.route = route;
|
|
|
+ return o;
|
|
|
+ });
|
|
|
+ return i.out_bill;
|
|
|
+ });
|
|
|
+ return _.flattenDeep(list);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 核算准备导出
|
|
|
+ * @param {Object} { type, ...query } type:单车(car)/单趟(once); query:查询条件
|
|
|
+ */
|
|
|
+ async toExport({ type, ...query }) {
|
|
|
+ let data = {};
|
|
|
+ if (type === 'car') data = await this.carCalculate(query);
|
|
|
+ else data = await this.calculate(query);
|
|
|
+ const res = await this.export({ data, ...query });
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 核算整理数据导出
|
|
|
+ * @param {Object} Object { data } data:数据
|
|
|
+ */
|
|
|
+ async export({ data, car_no }) {
|
|
|
+ // console.log(data);
|
|
|
+ // 获取车牌号
|
|
|
+ const car = await this.ctx.model.Car.findById(car_no);
|
|
|
+ if (car) car_no = car.car_no;
|
|
|
+ const arr = [];
|
|
|
+ const alignStyle = { vertical: 'middle', horizontal: 'center' };
|
|
|
+ // 根据内容,计算标题单元格结束位置的字母
|
|
|
+ const keys = Object.keys(data);
|
|
|
+ let ecell = '';
|
|
|
+ if (keys.includes('daily')) ecell = 'L1';
|
|
|
+ else ecell = '';
|
|
|
+ const headObj = {
|
|
|
+ content: '核算单',
|
|
|
+ scell: 'A1',
|
|
|
+ ecell,
|
|
|
+ alignment: alignStyle,
|
|
|
+ };
|
|
|
+ arr.push(headObj);
|
|
|
+ // 先拼count
|
|
|
+
|
|
|
+ await this.ctx.service.util.excel.toExcel({ data: arr });
|
|
|
+ }
|
|
|
}
|
|
|
module.exports = TransportService;
|