123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782 |
- 'use strict';
- const _ = require('lodash');
- const assert = require('assert');
- 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;
- this.util = this.ctx.service.util.util;
- }
- /**
- * 新添订单
- * @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;
- 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' && f.status === '0'
- );
- 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 this.model.update({ _id: order._id }, order);
- // 更新记录
- 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 this.model.update({ _id: order._id }, order);
- // 更新记录
- 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 {Object} data 订单数据
- */
- async principalChange(data) {
- const { principal, _id } = data;
- const res = await this.model.update({ _id: ObjectId(_id) }, { principal });
- try {
- // 跨库查询该用户姓名
- const user = await this.ctx.service.util.httpUtil.cget(
- `/user/${principal}`,
- 'userAuth',
- { _tenant: 'zhwl' }
- );
- const message = `变更订单负责人 ${user.name}`;
- this.record(_id, { method: 'principal', message });
- } catch (error) {
- this.logger.error(`订单id:${res.id}记录创建失败:${error.toString()}`);
- }
- return res;
- }
- /**
- * 订单操作记录
- * @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 === 'js') record.message = `${username}结算订单`;
- else if (
- method === 'send' ||
- method === 'arrive' ||
- method === 'principal' ||
- method === 'outJs'
- ) {
- record.message = `${message}`;
- }
- order.record.push(record);
- await order.save();
- }
- /**
- * 客户结算查询
- * @param {Object} query 查询条件
- */
- async clientCalculate(query) {
- query = this.util.turnDateRangeQuery(this.util.turnFilter(query));
- let list = await this.model
- .$where('this.split.every(i=>i.status=== "-1")')
- .find({ ...query, is_js: false })
- .populate([
- {
- path: 'client',
- model: 'Client',
- },
- {
- path: 'item',
- model: 'Item',
- },
- {
- path: 'route',
- model: 'Route',
- },
- {
- path: 'treaty',
- model: 'Treaty',
- },
- {
- path: 'goods',
- populate: [
- {
- path: 'mode',
- model: 'Mode',
- },
- ],
- },
- ]);
- if (list.length > 0) list = JSON.parse(JSON.stringify(list));
- // 组织数据
- list = this.toResetOrder(list);
- return list;
- }
- /**
- * 整合订单信息
- * @param {Array} list 订单列表
- */
- toResetOrder(list) {
- list = list.map(i => {
- i = this.orderReset(i);
- i = this.orderIn(i);
- return i;
- });
- return list;
- }
- /**
- * 将客户相关信息转换
- * @param {Object} order 订单信息
- */
- orderReset(order) {
- order = JSON.parse(JSON.stringify(order));
- const { client, item, route, treaty } = order;
- if (client && _.isObject(client)) {
- order.client_id = _.get(client, '_id');
- order.client = _.get(client, 'name');
- }
- if (item && _.isObject(item)) {
- order.item_id = _.get(item, '_id');
- order.item = _.get(item, 'name');
- }
- if (route && _.isObject(route)) {
- order.route_id = _.get(route, '_id');
- order.route = _.get(route, 'name');
- }
- if (treaty && _.isObject(treaty)) {
- order.treaty_id = _.get(treaty, '_id');
- order.treaty = _.get(treaty, 'number');
- }
- return order;
- }
- /**
- * 计算收入总价
- * @param {Object} order 订单信息
- */
- orderIn(order) {
- const { goods, in_bill } = order;
- const gi = goods.reduce((p, n) => p + (n.sh_ss || 0), 0);
- const bi = in_bill.reduce((p, n) => p + (n.sh_ss || 0), 0);
- const sh_ss = gi + bi;
- order.sh_ss = sh_ss;
- return order;
- }
- /**
- * 选择指定的订单,导出收入excel
- * @param {Object} query 查询条件
- * @property Array ids 订单id集合
- */
- async clientExport(query) {
- const { ids } = query;
- let list = await this.model
- .find({ _id: ids.map(i => ObjectId(i)) })
- .populate([
- {
- path: 'client',
- model: 'Client',
- },
- {
- path: 'item',
- model: 'Item',
- },
- {
- path: 'route',
- model: 'Route',
- },
- {
- path: 'treaty',
- model: 'Treaty',
- },
- {
- path: 'goods',
- populate: [
- {
- path: 'mode',
- model: 'Mode',
- },
- ],
- },
- ]);
- if (list.length > 0) list = JSON.parse(JSON.stringify(list));
- // 处理信息
- const arr = [];
- // 获取头
- const { header, otherList } = this.getHeader(list);
- // 已经被占用的行数
- let ouse = 1;
- for (const order of list) {
- // 计算这个订单的开始行和结束行位置
- const os = ouse + 1; // 订单开始行数
- const { goods } = order;
- // 整理共同部分数据
- const edata = this.getPublicExcelData(order, os);
- // 再处理额外项的头数据
- const odata = this.getOtherInExcelData(order, os, otherList);
- arr.push({ ...edata, ...odata });
- // 处理完后,更新被占用行数
- ouse = ouse + goods.length;
- }
- // 处理头
- let pkeys = Object.keys(header);
- pkeys = pkeys.map(i => {
- const reg = /[^a-zA-Z]/i;
- const res = i.replace(reg, '');
- return res;
- });
- let lastData = arr.map(i => ({ content: i })); // this.toResetExcelData(pkeys, arr);
- lastData.push({ content: header });
- const alignment = { vertical: 'middle', horizontal: 'center' };
- lastData = lastData.map(i => ({ ...i, alignment }));
- const res = await this.ctx.service.util.excel.toExcel({ data: lastData });
- return res;
- }
- /**
- * 合并处理数据
- * @param {Array} keys 列字母数组
- * @param {Array} data excel数据(不含头)
- */
- toResetExcelData(keys, data) {
- const reg = /[^a-zA-Z]/i;
- const arr = [];
- const clear = [];
- for (const key of keys) {
- // 找出每列的内容
- const col = data.map(i => {
- const lks = Object.keys(i);
- const r = lks.find(f => {
- const rr = f.replace(reg, '');
- return rr === key;
- });
- if (r) return { key: r, value: _.get(i, r) };
- });
- // 同一列满足以下条件可以合并:
- // 1,值相同;2数字连贯;3指定范围内
- // 先查范围
- const head = _.head(col);
- if (!head) continue;
- const letter = head.key.replace(reg, '');
- const r3 = this.mergeRange(letter);
- if (!r3) continue;
- const l = col.length;
- const ul = _.uniqBy(col, 'value').length;
- if (ul === l) continue;
- // 可以合并,需要重新拼个Object,{scell,ecell,content}
- // scell 是上面head的key, ecell是last获取key,content,随意拿出一个就行
- const obj = {};
- obj.scell = _.get(head, 'key');
- obj.ecell = _.get(_.last(col), 'key');
- obj.content = _.get(head, 'value');
- clear.push(_.get(head, 'key'), _.get(_.last(col), 'key'));
- arr.push(obj);
- }
- // 将scell和ecell都干掉
- data = data.map(i => {
- i = _.omitBy(i, (value, key) => {
- return clear.includes(key);
- });
- return { content: i };
- });
- data = [ ...data, ...arr ];
- return data;
- }
- /**
- * 查询该列是否可以合并
- * @param {String} letter 字母
- */
- mergeRange(letter) {
- const arr = [ 'U', 'Z', 'AA', 'AB', 'AC' ];
- return !arr.includes(letter);
- }
- /**
- * 整理成excel数据(先整理固定部分,即不包含额外收入部分)
- * @param {Object} order 订单信息
- * @param {Number} os 该订单开始行数
- */
- getPublicExcelData(order, os) {
- // 如果不需要合并,那一个订单也就是1个object,如果需要合并,那就是多个object,
- // 即使是多个object也没问题,因为控制的是每个单元格,所以出问题一定是单元格没弄明白
- // 除了货物,方式外,其他的固定项都需要判断是否需要合并单元格,所以先处理货物,方式
- const arr = [];
- const content = {};
- const { goods } = order;
- // 货物,方式部分
- for (let i = 0; i < goods.length; i++) {
- const good = goods[i];
- const {
- mode,
- name,
- costname = '运费',
- sq_ys,
- sq_ss,
- sh_ys,
- sh_ss,
- } = good;
- const { name: modeName, price, is_lf, send_type, computed_type } = mode;
- content[`S${i + os}`] = modeName;
- content[`T${i + os}`] = price;
- content[`U${i + os}`] = name;
- content[`V${i + os}`] = costname;
- content[`W${i + os}`] = is_lf ? '是' : '否';
- content[`X${i + os}`] = send_type;
- content[`Y${i + os}`] = computed_type;
- content[`Z${i + os}`] = sq_ys;
- content[`AA${i + os}`] = sq_ss;
- content[`AB${i + os}`] = sh_ys;
- content[`AC${i + os}`] = sh_ss;
- // 订单
- content[`A${i + os}`] = _.get(order, 'order_no');
- content[`AD${i + os}`] = _.get(order, 'remark');
- // 客户部分一定合并,不在这里处理
- content[`B${i + os}`] = _.get(order.client, 'name');
- content[`C${i + os}`] = _.get(order.client, 'address');
- content[`D${i + os}`] = _.get(order.client, 'legal');
- content[`E${i + os}`] = _.get(order.client, 'mobile');
- content[`F${i + os}`] = _.get(order.client, 'taxes_no');
- content[`G${i + os}`] = _.get(order.client, 'account_bank');
- content[`H${i + os}`] = _.get(order.client, 'account');
- // 合同部分
- content[`I${i + os}`] = _.get(order.treaty, 'number');
- content[`J${i + os}`] = _.get(order.treaty, 'jf');
- content[`K${i + os}`] = _.get(order.treaty, 'yf');
- content[`L${i + os}`] = _.get(order.treaty, 'period');
- content[`M${i + os}`] = _.get(order.treaty, 'settle_up');
- // 项目
- content[`N${i + os}`] = _.get(order.item, 'name');
- content[`O${i + os}`] = _.get(order.item, 'taxes');
- // 线路
- content[`P${i + os}`] = _.get(order.route, 'name');
- content[`Q${i + os}`] = _.get(order.route, 's_p');
- content[`R${i + os}`] = _.get(order.route, 'e_p');
- }
- arr.push(content);
- return content;
- }
- /**
- * 填充额外收入项
- * @param {Object} order 订单信息
- * @param {Number} os 该订单开始行数
- * @param {Array} inList 额外收入项
- */
- getOtherInExcelData(order, os, inList) {
- const obj = {};
- const { in_bill } = order;
- for (const oin of inList) {
- const { key, item, value } = oin;
- const r = in_bill.find(f => f.item === item);
- if (r) {
- obj[`${key}${os}`] = _.get(r, value);
- }
- }
- return obj;
- }
- /**
- * 获取导出的订单头
- * @param {Array} list 选择的订单
- */
- getHeader(list) {
- const obj = {};
- // 同一客户下:B-H一定是合并的
- // 同一订单下: A,AD1一定是合并的
- // 订单部分
- obj.A1 = '订单编号';
- // 客户部分
- obj.B1 = '客户名称';
- obj.C1 = '地址';
- obj.D1 = '法人';
- obj.E1 = '联系电话';
- obj.F1 = '税号';
- obj.G1 = '开户行';
- obj.H1 = '银行账号';
- // 合同部分
- obj.I1 = '合同编号';
- obj.J1 = '甲方';
- obj.K1 = '乙方';
- obj.L1 = '合同周期';
- obj.M1 = '结算方式';
- // 项目部分
- obj.N1 = '项目名称';
- obj.O1 = '税率';
- // 线路部分
- obj.P1 = '线路名称';
- obj.Q1 = '起始地';
- obj.R1 = '目的地';
- // 方式部分
- obj.S1 = '方式名称';
- obj.T1 = '价格';
- // 货物部分
- obj.U1 = '货物名称';
- obj.V1 = '费用名称'; // 固定全是运费
- // 方式部分
- obj.W1 = '量份收费'; // 需要换成 是/否
- obj.X1 = '发货方式';
- obj.Y1 = '计费方式';
- // 货物部分
- obj.Z1 = '税前应收';
- obj.AA1 = '税前实收';
- obj.AB1 = '税后应收';
- obj.AC1 = '税后实收';
- // 订单部分
- obj.AD1 = '订单备注';
- // 处理额外收入头部
- const in_item = _.uniqBy(list.map(i => i.in_bill).flat(), 'item');
- const arr = [];
- let i = 31;
- for (const inInfo of in_item) {
- const { item } = inInfo;
- const fl = this.ctx.service.util.excel.numberToLetter(_.floor(i / 26));
- // const sl = this.ctx.service.util.excel.numberToLetter(i % 26);
- const sqyl = this.ctx.service.util.excel.numberToLetter(i % 26);
- obj[`${fl}${sqyl}1`] = `${item}税前应收`;
- arr.push({ key: `${fl}${sqyl}`, item, value: 'sq_ys' });
- i++;
- const sqsl = this.ctx.service.util.excel.numberToLetter(i % 26);
- obj[`${fl}${sqsl}1`] = `${item}税前实收`;
- arr.push({ key: `${fl}${sqsl}`, item, value: 'sq_ss' });
- i++;
- const shyl = this.ctx.service.util.excel.numberToLetter(i % 26);
- obj[`${fl}${shyl}1`] = `${item}税后应收`;
- arr.push({ key: `${fl}${shyl}`, item, value: 'sh_ys' });
- i++;
- const shsl = this.ctx.service.util.excel.numberToLetter(i % 26);
- obj[`${fl}${shsl}1`] = `${item}税后实收`;
- arr.push({ key: `${fl}${shsl}`, item, value: 'sh_ss' });
- i++;
- }
- return { header: obj, otherList: arr };
- }
- /**
- * 订单结算
- * @param {Object} {ids} 要结算的订单
- */
- async js({ ids, client, owner, ...info }) {
- assert(ids, '缺少订单信息');
- assert(client, '缺少客户信息');
- assert(owner, '缺少创建人信息');
- const params = { ids, client, owner };
- const bill = await this.ctx.model.Bill.create({
- params,
- client,
- owner,
- ...info,
- });
- if (!bill) {
- throw new BusinessError(ErrorCode.DATABASE_FAULT, '结算单创建失败');
- }
- const res = await this.model.updateMany(
- { _id: ids.map(i => ObjectId(i)) },
- { is_js: true }
- );
- try {
- for (const id of ids) {
- this.record(id, { method: 'js' });
- }
- } catch (error) {
- this.logger.error(`订单id:${res.id}记录创建失败:${error.toString()}`);
- }
- }
- /**
- * 支出结算
- * @param {Object} {ids,client,car_no} ids:订单id列表,client:客户id,car_no:车牌号(第三方)/车辆id(自运)
- */
- async outJs({ ids, client, car_no }) {
- const orderList = await this.model.find({
- _id: ids.map(i => ObjectId(i)),
- });
- for (const order of orderList) {
- const { out_bill, _id } = order;
- let target;
- let res;
- if (client) {
- res = out_bill.filter(f => f.client === client);
- const cInfo = await this.ctx.model.Client.findById(client);
- if (!cInfo) { throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到指定供应商'); }
- target = _.get(cInfo, 'name');
- } else {
- res = out_bill.filter(f => f.car_no === car_no);
- const reg = new RegExp('[\\u4E00-\\u9FFF]+', 'g');
- if (reg.test(car_no)) {
- target = car_no;
- } else {
- const cInfo = await this.ctx.model.Car.findById(car_no);
- if (!cInfo) { throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到指定车辆'); }
- target = cInfo.car_no;
- }
- }
- for (const bill of res) {
- bill.is_js = true;
- }
- order.save();
- try {
- this.record(_id, { method: 'outJs', message: `结算 ${target} 支出` });
- } catch (error) {
- this.logger.error(`订单id:${res.id}记录创建失败:${error.toString()}`);
- }
- }
- }
- }
- module.exports = OrderService;
|