123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- 'use strict';
- const assert = require('assert');
- const _ = require('lodash');
- const { ObjectId } = require('mongoose').Types;
- const { CrudService } = require('naf-framework-mongoose/lib/service');
- const { BusinessError, ErrorCode } = require('naf-core').Error;
- class OrderService extends CrudService {
- constructor(ctx) {
- super(ctx, 'order');
- this.model = this.ctx.model.Order;
- }
- /**
- * 新添订单
- * @param {Object} data 订单数据
- */
- async create(data) {
- const res = await this.model.create(data);
- // 复制进split中
- if (!res) throw new BusinessError(ErrorCode.SERVICE_FAULT, '订单创建失败');
- await this.copyToSplit(res._id);
- try {
- this.record(res._id, { method: 'create' });
- } catch (error) {
- this.logger.error(`订单id:${res.id}记录创建失败:${error.toString()}`);
- }
- return res;
- }
- /**
- * 修改订单
- * @param {Object} { id, ...data } 要修改的订单数据
- */
- async update({ id, ...data }) {
- const res = await this.model.findById(id);
- const { goods: newGoods, ...info } = data;
- let { goods: oldGoods, split } = res;
- if (oldGoods) oldGoods = JSON.parse(JSON.stringify(oldGoods));
- if (split) split = JSON.parse(JSON.stringify(split));
- // 找到删除项
- // oldGoods中有,但是newGoods中却没有的数据,就是要删除的;且需要检验被删除的数据有没有被拆分
- oldGoods = oldGoods.map(og => {
- const need_delete = newGoods.find(f => ObjectId(f._id).equals(og._id));
- if (!need_delete) {
- const sobj = split.find(f => ObjectId(f.pid).equals(og._id));
- if (sobj) {
- // 查找其有没有被拆分
- const r = split.find(f => ObjectId(f.pid).equals(sobj._id));
- if (r) throw new BusinessError(ErrorCode.DATA_INVALID, '无法删除已被拆分过的货物');
- const s_index = split.findIndex(f => ObjectId(f.pid).equals(og._id));
- split.splice(s_index, 1);
- }
- return undefined;
- }
- return og;
- });
- oldGoods = _.compact(oldGoods);
- // 判断是否有修改项
- const updateRes = await this.goodsUpdate(oldGoods, newGoods, split);
- if (updateRes) {
- const { oldGoods: ogs, split: splist } = updateRes;
- if (ogs) oldGoods = ogs;
- if (splist) split = splist;
- }
- // 判断有没有新添的数据
- const addGoods = newGoods.filter(f => !f._id);
- if (addGoods.length > 0) {
- // 有新增货物项
- // TODO,复制到split中和oldGoods中
- for (const ng of addGoods) {
- oldGoods.push(ng);
- }
- }
- res.goods = oldGoods;
- res.split = split;
- // console.group('oldGoods');
- // console.log(oldGoods);
- // console.groupEnd();
- // console.group('split');
- // console.log(split);
- // console.groupEnd();
- await this.model.update({ _id: ObjectId(id) }, info);
- await res.save();
- this.copyToSplit(id);
- try {
- this.record(res._id, { method: 'update' });
- } catch (error) {
- this.logger.error(`订单id:${res.id}记录创建失败:${error.toString()}`);
- }
- return;
- }
- /**
- * 检查并处理有修改的货物:拆分就不允许修改了
- * @param {Array} oldGoods 查出修改前的货物列表
- * @param {Array} newGoods 修改后的货物列表
- * @param {Array} split 原拆分货物列表,用来检查是否可以修改
- */
- async goodsUpdate(oldGoods, newGoods, split) {
- oldGoods = oldGoods.map(og => {
- const is_split = split.find(f => ObjectId(f.pid).equals(og._id) && f.type === '1');
- if (is_split) return og;
- // 没有拆分,可以直接更换
- const ng = newGoods.find(f => ObjectId(f._id).equals(og._id));
- if (ng) return { ...ng, update: true };
- return og;
- });
- // 修改拆分货物列表
- const toUpdateSplit = oldGoods.filter(f => f.update);
- split = split.map(i => {
- const res = toUpdateSplit.find(f => ObjectId(f._id).equals(i.pid));
- if (res) {
- const obj = this.goodsCopy(res);
- return obj;
- }
- return i;
- });
- // 将oldGoods的update摘出去
- oldGoods = oldGoods.map(i => _.omit(i, [ 'update' ]));
- return { oldGoods, split };
- }
- /**
- * 将货物复制成拆分货物的数据并返回
- * @param {Object} data 货物列表的每项
- * @return split
- */
- goodsCopy(data) {
- const split = _.pick(data, [
- 'name',
- 'number',
- 'weight',
- 'volume',
- 'transport_type',
- 'remark',
- ]);
- split.pid = data._id;
- return split;
- }
- /**
- * 根据订单id,复制货物 到 拆分货物,只是复制,其他操作在各自的方法中,这里只是复制
- * @param {String} id 订单id
- */
- async copyToSplit(id) {
- const order = await this.model.findById(id);
- if (!order) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到订单');
- const { goods, split } = order;
- for (const g of goods) {
- const has = split.find(f => ObjectId(f.pid).equals(g._id));
- if (!has) {
- order.split.push(this.goodsCopy(g));
- }
- }
- await order.save();
- }
- /**
- * 发货,添加记录及修改状态
- * @param {Array} goods 发货的货物列表
- * @param {String} no 运输单号
- * @param {String} time 发货日期
- */
- async sendGoods(goods, no, time) {
- for (const g of goods) {
- const { split_id, name, number, weight, volume } = g;
- const order = await this.model.findOne({ 'split._id': ObjectId(split_id) });
- if (!order) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, `未找到该${name}所在的订单信息`);
- const obj = { split_id, name, number, weight, volume, no, time };
- // 添加该货物的发货记录
- order.send_time.push(obj);
- // 修改该货物的状态
- const good = order.split.id(split_id);
- good.status = '1';
- order.goods_status = await this.checkGoodsStatus(order.split);
- await order.save();
- // 更新记录
- let message = `${name}已发货(数量:${number};重量:${weight}吨;体积:${volume}m³)`;
- const all_send = order.split.every(e => e.status === '0');
- if (all_send) message = `${message}; 所有货物已发出`;
- try {
- this.record(order._id, { method: 'send', message });
- } catch (error) {
- this.logger.error(`订单id:${order.id}记录创建失败:${error.toString()}`);
- }
- }
- }
- /**
- * 签收,添加记录及修改状态
- * @param {Array} goods 签收的货物列表
- * @param {String} no 运输单号
- * @param {String} time 签收时间
- */
- async arriveGoods(goods, no, time) {
- for (const g of goods) {
- const { split_id, name, number, weight, volume } = g;
- const order = await this.model.findOne({ 'split._id': ObjectId(split_id) });
- if (!order) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, `未找到该${name}所在的订单信息`);
- const obj = { split_id, name, number, weight, volume, no };
- if (time) obj.time = time;
- // 添加收货记录
- order.arrive_time.push(obj);
- // 修改该货物的状态
- const good = order.split.id(split_id);
- good.status = '-1';
- order.goods_status = await this.checkGoodsStatus(order.split);
- await order.save();
- // 更新记录
- let message = `${name}已签收(数量:${number};重量:${weight}吨;体积:${volume}m³)`;
- const all_arrive = order.split.every(e => e.status === '-1');
- if (all_arrive) message = `${message}; 所有货物已签收`;
- try {
- this.record(order._id, { method: 'arrive', message });
- } catch (error) {
- this.logger.error(`订单id:${order.id}记录创建失败:${error.toString()}`);
- }
- }
- }
- /**
- * 检查拆分货物列表,更新goods_status
- * @param {Array} splitList 拆分货物列表
- */
- async checkGoodsStatus(splitList) {
- // 未发车
- const res = splitList.every(e => e.status === '0');
- if (res) return '未发货';
- // 检查是否全发车的货物
- const all_send = splitList.every(e => e.status === '1');
- if (all_send) return '所有货物已发出';
- // 检查是否全到达了
- const all_arrive = splitList.every(e => e.status === '-1');
- if (all_arrive) return '所有货物全部到达';
- // 检查是否有发货的
- const is_send = splitList.some(e => e.status === '1');
- // 检查是否有到达的
- const is_arrive = splitList.some(e => e.status === '-1');
- const word = [];
- if (is_send)word.push('部分货物已发出');
- if (is_arrive)word.push('部分货物已到达');
- if (word.length > 0) return word.join(';');
- return '状态错误';
- }
- /**
- * 订单操作记录
- * @param {String} id 订单id
- * @param {Object} {method:方法, message:自定义文字} 参数
- */
- async record(id, { method, message }) {
- const order = await this.model.findById(id);
- if (!order) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, `未找到订单,传入id:${id}`);
- const { authorization } = this.ctx.request.header;
- let user = decodeURI(authorization);
- if (!user) { throw new BusinessError(ErrorCode.USER_NOT_EXIST, '未找到操作人'); }
- user = JSON.parse(user);
- const { id: userid, name: username } = user;
- const record = { opera: username, operaid: userid };
- // 创建记录
- if (method === 'create') record.message = `${username}创建订单`;
- else if (method === 'update') record.message = `${username}修改订单`;
- else if (method === 'in') record.message = `${username}修改收入`;
- else if (method === 'out') record.message = `${username}修改支出`;
- else if (method === 'split') record.message = `${username}拆分货物`;
- else if (method === 'send' || method === 'arrive') record.message = `${message}`;
- order.record.push(record);
- await order.save();
- }
- }
- module.exports = OrderService;
|