lrf402788946 4 роки тому
батько
коміт
42930d1a39

+ 76 - 0
app/controller/order/.order.js

@@ -0,0 +1,76 @@
+module.exports = {
+  create: {
+    requestBody: [
+      "order_no",
+      "!owner",
+      "!client",
+      "rq_send_time",
+      "send_time",
+      "rq_arrive_time",
+      "arrive_time",
+      "pre_money",
+      "goods",
+      "split",
+      "goods_bill",
+      "in_bill",
+      "out_bill",
+      "is_js",
+      "goods_status",
+      "status",
+      "remark",
+    ],
+  },
+  destroy: {
+    params: ["!id"],
+    service: "delete",
+  },
+  update: {
+    params: ["!id"],
+    requestBody: [
+      "order_no",
+      "!owner",
+      "!client",
+      "rq_send_time",
+      "send_time",
+      "rq_arrive_time",
+      "arrive_time",
+      "pre_money",
+      "goods",
+      "split",
+      "goods_bill",
+      "in_bill",
+      "out_bill",
+      "is_js",
+      "goods_status",
+      "status",
+      "remark",
+    ],
+  },
+  show: {
+    parameters: {
+      params: ["!id"],
+    },
+    service: "fetch",
+  },
+  index: {
+    parameters: {
+      query: {
+        order_no: "%order_no%",
+        owner: "owner",
+        client: "client",
+        "rq_send_time@start": "rq_send_time@start",
+        "rq_send_time@end": "rq_send_time@end",
+        "rq_arrive_time@start": "rq_arrive_time@start",
+        is_js: "is_js",
+        status: "status",
+      },
+    },
+    service: "query",
+    options: {
+      query: ["skip", "limit"],
+      sort: ["meta.createdAt"],
+      desc: true,
+      count: true,
+    },
+  },
+};

+ 16 - 0
app/controller/order/order.js

@@ -0,0 +1,16 @@
+'use strict';
+
+// const _ = require('lodash');
+const meta = require('./.order.js');
+const Controller = require('egg').Controller;
+const { CrudController } = require('naf-framework-mongoose/lib/controller');
+
+// 客户/供应商
+class OrderController extends Controller {
+  constructor(ctx) {
+    super(ctx);
+    this.service = this.ctx.service.order.order;
+  }
+}
+
+module.exports = CrudController(OrderController, meta);

+ 79 - 47
app/model/order.js

@@ -1,13 +1,25 @@
 'use strict';
 const Schema = require('mongoose').Schema;
+const moment = require('moment');
 const metaPlugin = require('naf-framework-mongoose/lib/model/meta-plugin');
+// 发货数据
+const sendList = new Schema({
+  split_id: { type: String, maxLength: 200 }, // 拆分的货物id
+  name: { type: String, maxLength: 200 }, // 货物名
+  number: { type: Number, maxLength: 200 }, // 数量
+  weight: { type: Number, maxLength: 200 }, // 重量
+  volume: { type: Number, maxLength: 200 }, // 体积
+  time: { type: String, maxLength: 200, default: moment().format('YYYY-MM-DD HH:mm:ss') }, // 收货时间
+  remark: { type: String, maxLength: 200 },
+});
 // 签收数据
 const arriveList = new Schema({
+  split_id: { type: String, maxLength: 200 }, // 拆分的货物id
   name: { type: String, maxLength: 200 }, // 货物名
   number: { type: Number, maxLength: 200 }, // 数量
   weight: { type: Number, maxLength: 200 }, // 重量
   volume: { type: Number, maxLength: 200 }, // 体积
-  time: { type: String, maxLength: 200 }, // 收货时间
+  time: { type: String, maxLength: 200, default: moment().format('YYYY-MM-DD HH:mm:ss') }, // 收货时间
   remark: { type: String, maxLength: 200 },
 });
 // 货物列表
@@ -16,6 +28,7 @@ const goods = new Schema({
   number: { type: Number, maxLength: 200 }, // 数量
   weight: { type: Number, maxLength: 200 }, // 重量
   volume: { type: Number, maxLength: 200 }, // 体积
+  transport_type: { type: String, maxLength: 200, default: '直达' }, // 该货物的运输类型: 直达;转运
   remark: { type: String, maxLength: 200 },
 });
 
@@ -27,17 +40,49 @@ const splitGoods = new Schema({
   number: { type: Number, maxLength: 200, default: 0 }, // 数量
   weight: { type: Number, maxLength: 200 }, // 重量
   volume: { type: Number, maxLength: 200 }, // 体积
-  remark: { type: String, maxLength: 200 },
+  transport_type: { type: String, maxLength: 200, default: '0' }, // 该货物的运输类型: 0=>直达;1=>转运
+  remark: { type: String, maxLength: 200 }, // remark属于拆分过后的,只有原货物进行复制,拆分后的不需要复制,可以自己编辑
   pid: { type: String, maxLength: 200, required: true }, // 来源id;type为0时,从goods中去找;1时,就都是这个文档的事了
-  type: { type: String, maxLength: 200, default: '0' }, // 0=>原始数据;1=>拆分数据,
-  status: { type: String, maxLength: 200, default: '0' }, // 0=>未装车; 1=>运输中; 2=>已到达
+  type: { type: String, maxLength: 200, default: '0' }, // 0=>货物列表原始数据;1=>拆分数据;
+  status: { type: String, maxLength: 200, default: '0' }, // -1=>已到达; 0=>未装车; 1=>运输中; 2=>转运地签收; 3=>转运中
+});
+
+// 订单记录
+const recordList = new Schema({
+  opera: { type: String, maxLength: 200 }, // 操作人
+  operaid: { type: String, maxLength: 200 }, // 操作人id
+  message: { type: String, maxLength: 200 }, // 操作
+  time: { type: String, default: moment().format('YYYY-MM-DD HH:mm:ss') }, // 操作时间
+});
+
+// 货物收入
+const goods_bill = new Schema({
+  name: { type: String, maxlength: 200 }, // 货物名称
+  // TODO 2种模式:合同+项目+线路+计费方式/计费方式
+  number: { type: Number, maxLength: 200 }, // 数量
+  weight: { type: Number, maxLength: 200 }, // 重量
+  volume: { type: Number, maxLength: 200 }, // 体积
+  taxes: { type: String, maxLength: 200 }, // 税率
+  sq_ys: { type: Number, maxLength: 200 }, // 税前应收
+  sq_ss: { type: Number, maxLength: 200 }, // 税前实收
+  sh_ys: { type: Number, maxLength: 200 }, // 税后应收
+  sh_ss: { type: Number, maxLength: 200 }, // 税后实收
+});
+
+// 收入/支出项
+const cost_bill = new Schema({
+  item: { type: String, maxlength: 200 }, // 支出项
+  taxes: { type: String, maxLength: 200 }, // 税率
+  sq_ys: { type: Number, maxLength: 200 }, // 税前应收
+  sq_ss: { type: Number, maxLength: 200 }, // 税前实收
+  sh_ys: { type: Number, maxLength: 200 }, // 税后应收
+  sh_ss: { type: Number, maxLength: 200 }, // 税后实收
 });
 
 // 订单
 const order = {
   order_no: {
     type: String,
-    required: true,
     maxLength: 200,
     field: { label: '订单号', filter: true },
   },
@@ -47,6 +92,11 @@ const order = {
     maxLength: 200,
     field: { label: '订单创建人' },
   },
+  principal: {
+    type: String,
+    maxLength: 200,
+    field: { label: '当前订单负责人' },
+  },
   client: {
     type: String,
     required: true,
@@ -55,39 +105,33 @@ const order = {
   },
   rq_send_time: {
     type: String,
-    required: true,
     maxLength: 200,
     field: { label: '要求发货日期' },
   },
   send_time: {
-    type: String,
-    required: true,
+    type: [ sendList ],
     maxLength: 200,
     field: { label: '发货日期' },
   },
   rq_arrive_time: {
     type: String,
-    required: true,
     maxLength: 200,
     field: { label: '要求到达日期' },
   },
   // 到达日期有问题:应该有多种货物不同到达日期 或 某种货物被拆分,不同的到达日期
   // 但是这并不影响要求 到达日期
-  arrive: {
+  arrive_time: {
     type: [ arriveList ],
-    required: true,
     maxLength: 200,
     field: { label: '到达日期' },
   },
   pre_money: {
     type: String,
-    required: true,
     maxLength: 200,
-    field: { label: '预金额', type: 'number' },
+    field: { label: '预金额', type: 'number' },
   },
   goods: {
     type: [ goods ],
-    required: true,
     maxLength: 200,
     field: {
       label: '货物',
@@ -96,7 +140,6 @@ const order = {
   },
   split: {
     type: [ splitGoods ],
-    required: true,
     maxLength: 200,
     field: {
       label: '货物拆分列表',
@@ -104,47 +147,33 @@ const order = {
     },
   },
   goods_bill: {
-    type: Array,
-    required: true,
+    type: [ goods_bill ],
     maxLength: 200,
     field: { label: '货物收入单据' },
   },
   in_bill: {
-    type: Array,
-    required: true,
+    type: [ cost_bill ],
     maxLength: 200,
     field: { label: '收入-服务单据' },
   },
   out_bill: {
-    type: Array,
-    required: true,
+    type: [ cost_bill ],
     maxLength: 200,
     field: { label: '支出-服务单据' },
   },
-  transport_bill: {
-    type: Array,
-    required: true,
-    maxLength: 200,
-    field: {
-      label: '运输支出单据',
-      remark: `主要问题在这,这里的运输单据要映射到运输表中;且可以修改;有可能有多条数据,比如此单是往返单,货物可能一开始没有填全,只填了去的货物,而途中,此单可能变成单程单,之后可能空车回来或者参与其他单.
-        还可能此单原来是单程单,之后需要在这单上加些货物回来,就变成往返单,或可以运输结束的单子
-        还有可能是:此单需要多段运输,每段运输都需要记录
-        `,
-    },
-  },
+  // 运输单与订单的关系: 订单的拆分货物id会在运输单的货物列表中
   is_js: {
-    type: String,
+    type: Boolean,
     maxLength: 200,
-    default: '0',
+    default: false,
     field: {
       label: '结算状态',
       filter: 'select',
       type: 'radio',
-      format: (i => (i === '0' ? '未结算' : '已结算')).toString(),
+      format: (i => (i ? '已结算' : '未结算')).toString(),
       list: [
-        { label: '未结算', value: '0' },
-        { label: '已结算', value: '1' },
+        { label: '未结算', value: false },
+        { label: '已结算', value: true },
       ],
     },
   },
@@ -155,15 +184,15 @@ const order = {
     field: {
       label: '货物状态',
       filter: 'select',
-      type: 'radio',
+      type: 'text',
       remark: `查看拆分列表中
         1)所有的货物状态都为0 => 未发车
-        2)至少1个0,其余全为1,没有2=> 部分货物未发车 ; 部分运输中
-        3)至少1个0,至少1个1,至少1个2=> 部分货物未发车 ; 部分运输中 ; 部分货物已到达
-        4)至少1个0,没有1,其余全为2=> 部分货物未发车 ; 部分货物已到达
-        5)没有0,全为1,没有2 => 所有货物运输中
-        4)没有0,至少1个1,其余全为2 => 所有货物运输中 ; 部分货物已到达
-        6)没有0,没有1,全为2 => 所有货物已到达
+        2)至少1个0,其余全为1||全为2||全为3,没有-1=> 部分货物未发车 ; 部分运输中
+        3)至少1个0,至少1个1||至少1个2||至少1个3,至少1个-1=> 部分货物未发车 ; 部分运输中 ; 部分货物已到达
+        4)至少1个0,没有1&&没有2&&没有3,其余全为-1=> 部分货物未发车 ; 部分货物已到达
+        5)没有0,全为1||全为2||全为3,没有-1 => 所有货物运输中
+        4)没有0,至少1个1||至少1个2||至少1个3,其余全为-1 => 所有货物运输中 ; 部分货物已到达
+        6)没有0,没有1&&没有2&&没有3,全为-1 => 所有货物已到达
       `,
     },
   },
@@ -172,7 +201,7 @@ const order = {
     maxLength: 200,
     default: '0',
     field: {
-      label: '状态',
+      label: '数据状态',
       filter: 'select',
       type: 'radio',
       format: (i => (i === '0' ? '正常' : '冻结')).toString(),
@@ -185,7 +214,6 @@ const order = {
   }, // 状态:0=>使用;1禁用
   remark: {
     type: String,
-    required: false,
     maxLength: 200,
     field: {
       label: '备注',
@@ -193,6 +221,10 @@ const order = {
       options: { autosize: { minRows: 3, maxRows: 5 } },
     },
   },
+  record: {
+    type: [ recordList ],
+    field: { label: '订单记录' },
+  },
 };
 
 const schema = new Schema(order, { toJSON: { virtuals: true } });

+ 142 - 0
app/model/transport.js

@@ -0,0 +1,142 @@
+'use strict';
+const moment = require('moment');
+const Schema = require('mongoose').Schema;
+const metaPlugin = require('naf-framework-mongoose/lib/model/meta-plugin');
+// 货物列表
+const goodsList = new Schema({
+  name: { type: String, maxlength: 200 }, // 货物名称
+  number: { type: Number, maxLength: 200 }, // 数量
+  weight: { type: Number, maxLength: 200 }, // 重量
+  volume: { type: Number, maxLength: 200 }, // 体积
+  taxes: { type: String, maxLength: 200 }, // 税率
+  sq_ys: { type: Number, maxLength: 200 }, // 税前应收
+  sq_ss: { type: Number, maxLength: 200 }, // 税前实收
+  sh_ys: { type: Number, maxLength: 200 }, // 税后应收
+  sh_ss: { type: Number, maxLength: 200 }, // 税后实收
+  split_id: { type: String, maxLength: 200 }, // 拆分的货物id
+});
+// 运输支出
+const bill = new Schema({
+  item: { type: String, maxlength: 200 }, // 支出项
+  taxes: { type: String, maxLength: 200 }, // 税率
+  sq_ys: { type: Number, maxLength: 200 }, // 税前应收
+  sq_ss: { type: Number, maxLength: 200 }, // 税前实收
+  sh_ys: { type: Number, maxLength: 200 }, // 税后应收
+  sh_ss: { type: Number, maxLength: 200 }, // 税后实收
+});
+// 运输方信息
+const supplier = new Schema({
+  car_no: { type: String, maxlength: 200 }, // 车牌号,0/2使用
+  client: { type: String, maxlength: 200 }, // 客户
+  treaty: { type: String, maxlength: 200 }, // 合同
+  item: { type: String, maxlength: 200 }, // 项目
+  route: { type: String, maxlength: 200 }, // 线路
+  mode: { type: String, maxlength: 200 }, // 计费方式
+  taxes: { type: String, maxLength: 200 }, // 税率
+});
+// 车辆日常维护
+const transport = {
+  no: {
+    type: String,
+    required: true,
+    field: { label: '运输单号' },
+  },
+  owner: {
+    type: String,
+    required: true,
+    maxLength: 200,
+    field: { label: '运输单负责人', remark: '谁装的车就是谁' },
+  },
+  supply_type: {
+    type: String,
+    required: true,
+    field: {
+      label: '运输单位类型',
+      list: [
+        { label: '自运', value: '0' },
+        { label: '供应商', value: '1' },
+        { label: '第三方单位', value: '2' },
+      ],
+    },
+  },
+  supplier: {
+    type: supplier,
+    required: true,
+    maxLength: 200,
+    field: {
+      label: '运输单位信息',
+      remark: `0=>这里就是车牌号
+              1=>这里就是供应商至计费方式的信息
+              2=>这里就是 个体(车号) 等一次性单位
+      `,
+    },
+  },
+  goods: {
+    type: [ goodsList ],
+    field: { label: '货物列表' },
+  },
+  sign_time: {
+    type: String,
+    field: { label: '签收时间' },
+  },
+  out_bill: {
+    type: [ bill ],
+    maxLength: 200,
+    field: { label: '运输支出单据' },
+  },
+  remark: {
+    type: String,
+    required: false,
+    maxLength: 200,
+    field: {
+      label: '备注',
+      type: 'textarea',
+      options: { autosize: { minRows: 3, maxRows: 5 } },
+    },
+  },
+  status: {
+    type: String,
+    maxLength: 200,
+    default: '0',
+    field: {
+      label: '状态',
+      filter: 'select',
+      type: 'radio',
+      format: (i => (i === '0' ? '运输中' : '已签到')).toString(),
+      list: [
+        { label: '运输中', value: '0' },
+        { label: '已签到', value: '1' },
+      ],
+    },
+  },
+  is_js: {
+    type: Boolean,
+    maxLength: 200,
+    default: false,
+    field: {
+      label: '结算状态',
+      filter: 'select',
+      type: 'radio',
+      format: (i => (i ? '已结算' : '未结算')).toString(),
+      list: [
+        { label: '未结算', value: false },
+        { label: '已结算', value: true },
+      ],
+    },
+  },
+};
+
+const schema = new Schema(transport, { toJSON: { virtuals: true } });
+schema.index({ id: 1 });
+schema.index({ car_no: 1 });
+schema.index({ money: 1 });
+schema.index({ item: 1 });
+schema.index({ date: 1 });
+schema.index({ status: 1 });
+
+schema.plugin(metaPlugin);
+
+module.exports = app => {
+  const { mongoose } = app;
+  return mongoose.model('Transport', schema, 'transport');
+};

+ 1 - 0
app/router.js

@@ -16,5 +16,6 @@ module.exports = app => {
   require('./router/personnel')(app); // 人员设置
   require('./router/client')(app); // 客户/供应商相关
   require('./router/car')(app); // 车辆相关
+  require('./router/order')(app); // 订单相关
 
 };

+ 11 - 0
app/router/order.js

@@ -0,0 +1,11 @@
+'use strict';
+/**
+ * @param {Egg.Application} app - egg application
+ */
+module.exports = app => {
+  const prefix = '/api/servicezhwl';
+  const index = 'order';
+  const { router, controller } = app;
+  router.resources('order', `${prefix}/order`, controller[index].order); // index、create、show、destroy
+  router.post('order', `${prefix}/order/update/:id`, controller[index].order.update);
+};

+ 1 - 1
app/service/car/car.js

@@ -4,7 +4,7 @@ const assert = require('assert');
 const _ = require('lodash');
 const { ObjectId } = require('mongoose').Types;
 const { CrudService } = require('naf-framework-mongoose/lib/service');
-const { ZhwlcarError, ErrorCode } = require('naf-core').Error;
+const { BusinessError, ErrorCode } = require('naf-core').Error;
 
 class CarService extends CrudService {
   constructor(ctx) {

+ 1 - 1
app/service/car/daily.js

@@ -4,7 +4,7 @@ const assert = require('assert');
 const _ = require('lodash');
 const { ObjectId } = require('mongoose').Types;
 const { CrudService } = require('naf-framework-mongoose/lib/service');
-const { ZhwlcarError, ErrorCode } = require('naf-core').Error;
+const { BusinessError, ErrorCode } = require("naf-core").Error;
 
 class DailyService extends CrudService {
   constructor(ctx) {

+ 1 - 1
app/service/client/client.js

@@ -4,7 +4,7 @@ const assert = require('assert');
 const _ = require('lodash');
 const { ObjectId } = require('mongoose').Types;
 const { CrudService } = require('naf-framework-mongoose/lib/service');
-const { ZhwldriverError, ErrorCode } = require('naf-core').Error;
+const { BusinessError, ErrorCode } = require('naf-core').Error;
 
 class ClientService extends CrudService {
   constructor(ctx) {

+ 1 - 1
app/service/client/item.js

@@ -4,7 +4,7 @@ const assert = require('assert');
 const _ = require('lodash');
 const { ObjectId } = require('mongoose').Types;
 const { CrudService } = require('naf-framework-mongoose/lib/service');
-const { ZhwldriverError, ErrorCode } = require('naf-core').Error;
+const { BusinessError, ErrorCode } = require('naf-core').Error;
 
 class ItemService extends CrudService {
   constructor(ctx) {

+ 1 - 1
app/service/client/mode.js

@@ -4,7 +4,7 @@ const assert = require('assert');
 const _ = require('lodash');
 const { ObjectId } = require('mongoose').Types;
 const { CrudService } = require('naf-framework-mongoose/lib/service');
-const { ZhwldriverError, ErrorCode } = require('naf-core').Error;
+const { BusinessError, ErrorCode } = require('naf-core').Error;
 
 class ModeService extends CrudService {
   constructor(ctx) {

+ 1 - 1
app/service/client/route.js

@@ -4,7 +4,7 @@ const assert = require('assert');
 const _ = require('lodash');
 const { ObjectId } = require('mongoose').Types;
 const { CrudService } = require('naf-framework-mongoose/lib/service');
-const { ZhwldriverError, ErrorCode } = require('naf-core').Error;
+const { BusinessError, ErrorCode } = require('naf-core').Error;
 
 class RouteService extends CrudService {
   constructor(ctx) {

+ 1 - 1
app/service/client/treaty.js

@@ -4,7 +4,7 @@ const assert = require('assert');
 const _ = require('lodash');
 const { ObjectId } = require('mongoose').Types;
 const { CrudService } = require('naf-framework-mongoose/lib/service');
-const { ZhwldriverError, ErrorCode } = require('naf-core').Error;
+const { BusinessError, ErrorCode } = require('naf-core').Error;
 
 class TreatyService extends CrudService {
   constructor(ctx) {

+ 16 - 0
app/service/order/order.js

@@ -0,0 +1,16 @@
+'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;
+  }
+}
+
+module.exports = OrderService;

+ 1 - 1
app/service/personnel/driver.js

@@ -4,7 +4,7 @@ const assert = require('assert');
 const _ = require('lodash');
 const { ObjectId } = require('mongoose').Types;
 const { CrudService } = require('naf-framework-mongoose/lib/service');
-const { ZhwldriverError, ErrorCode } = require('naf-core').Error;
+const { BusinessError, ErrorCode } = require('naf-core').Error;
 
 class DriverService extends CrudService {
   constructor(ctx) {

+ 1 - 1
app/service/test.js

@@ -4,7 +4,7 @@ const assert = require('assert');
 const _ = require('lodash');
 const { ObjectId } = require('mongoose').Types;
 const { CrudService } = require('naf-framework-mongoose/lib/service');
-const { TestError, ErrorCode } = require('naf-core').Error;
+const { BusinessError, ErrorCode } = require('naf-core').Error;
 
 class TestService extends CrudService {
   constructor(ctx) {