333
schangxiang@126.com
2025-09-19 18966e02fb573c7e2bb0c6426ed792b38b910940
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
import * as sql from "mssql";
import { Post } from "egg-shell-decorators";
import BaseController from "../baseController";
import { SaleOrderPrint } from "../../entity/outbound/manufacture/saleOrderPrint";
import { Like, In, Raw } from "typeorm";
import { SaleOuterList } from "../../entity/outbound/sale/saleOuterList";
import { vSaleOrderPrintListGroup } from "../../entity/outbound/manufacture/vSaleOrderPrintListGroup";
import { SaleOuter } from "../../entity/outbound/sale/saleOuter";
import { SaleOrder } from "../../entity/outbound/sale/saleOrder";
import { SaleOrderList } from "../../entity/outbound/sale/saleOrderList";
// import { TMSWayBill } from "../../entity/express/tms/tmsWayBill";
// import { TMSWayBillList } from "../../entity/express/tms/tmsWayBillList";
 
/**
 * 波次打包
 */
export default class OutScanBatchController extends BaseController {
  //#region 获取快递单对应的销售订单的信息 GetData
  @Post()
  public async getData() {
    let userInfo = await this.userInfo;
    let { ctx } = this;
    let body = ctx.request.body;
    //也可以是 销售订单号,因为有可能生成波次以后,没有打印面单,所以扫描不了快递单号,
    //但是打印了捡配单,可以扫描销售单号
    let orderPrintCode = body.orderPrintCode;
    //#region 需要扫描波次号
    if (!orderPrintCode) {
      this.info.msg = "波次号不能为空!";
      ctx.body = this.info;
      return;
    }
 
    try {
      let orderPrint = await this.dbRead.findOne(SaleOrderPrint, {
        orderPrintCode: orderPrintCode,
        userProduct_Id: userInfo.userProduct_Id
      });
      if (!orderPrint) {
        this.info.msg = "波次不存在!";
        ctx.body = this.info;
        return;
      }
 
      let query = `
                SELECT L.order_Id, L.orderCode, L.productModel, SUM(L.quantityOrder) AS quantityOrder,MAX(positionName) AS positionName, L.productCode, L.productSpec, L.productName,
                    SUM(quantityOuter) AS quantityOuter, MAX(salePrice) AS salePrice, MAX(orderList_Id) AS orderList_Id, 
                    MAX(mobile) AS mobile, MAX(telephone) AS telephone, MAX(clientShortName) AS clientShortName, MAX(shippingAddress) AS shippingAddress,
                    max(relationCode) as relationCode, max(relationCode2) as relationCode2, max(relationCode3) as relationCode3, 
                    max(relationCode4) as relationCode4, max(relationCode5) as relationCode5, 
                    max(middleBarcode) as middleBarcode, max(middleunitConvert) as middleunitConvert, max(bigBarcode) as bigBarcode, 
                    max(unitConvert) as unitConvert,MAX(weight) AS weight ,MAX(totalWeight) AS totalWeight,max(shippingName) as shippingName
                FROM
                (
                    SELECT L.order_Id, L.orderCode, L.productModel, L.quantityOrder,L.positionName, L.productCode, L.productSpec, L.productName, 
                        ISNULL(quantityOuter,0) AS quantityOuter, 
                        (SELECT TOP 1 salePrice FROM dbo.vBase_ProductInfo_SKU WHERE product_Id=L.product_Id) AS salePrice,
                        orderList_Id, O.mobile, O.telephone, O.clientShortName, O.shippingAddress,
                        v.relationCode, v.relationCode2, v.relationCode3, v.relationCode4, v.relationCode5,
            v.middleBarcode, v.middleunitConvert, v.bigBarcode, v.unitConvert,v.weight,L.totalWeight,o.shippingName
                    FROM dbo.Sale_OrderPrint m INNER JOIN dbo.Sale_OrderPrintList L ON m.orderPrint_Id=L.orderPrint_Id
                    INNER JOIN dbo.Sale_Order O ON L.order_Id=O.order_Id INNER JOIN dbo.vBase_ProductInfo_SKU v ON L.product_Id=v.product_Id
                    WHERE m.orderPrint_Id=@0 and quantityOrder - ISNULL(quantityOuter, 0)>0
                ) L
                GROUP BY L.order_Id, L.orderCode, L.productModel, L.productCode, L.productSpec, L.productName;`;
 
      let dataList = await this.dbRead.query(query, [orderPrint.orderPrint_Id]);
 
      if (dataList.length == 0) {
        this.info.msg = "未找到对应的订单明细数据";
      } else {
        this.info.result = true;
        this.info.data = dataList;
 
        //获得最大箱号值
        let _oCaseNumber = await this.dbRead.findOne(SaleOuterList, {
          select: ["caseNumber"],
          where: {
            outerList_Id: Raw(
              () => `exists(Select 1 from Sale_Outer Where outer_Id=SaleOuterList.outer_Id And userProduct_Id=${userInfo.userProduct_Id})`
            ),
            caseNumber: Like("%" + orderPrintCode + "%")
          },
          order: {
            caseNumber: "DESC"
          }
        });
        let caseNumber = "";
        if (_oCaseNumber == null) {
          caseNumber = orderPrintCode + "-01";
        } else {
          let oCaseNumber = _oCaseNumber.caseNumber;
          let caseNumbers = oCaseNumber.split("-");
          let num = parseInt(caseNumbers[caseNumbers.length - 1]);
          let num1 = "0000" + ++num;
          caseNumber = orderPrintCode + "-" + num1.substring(num1.length - 2);
        }
        this.info.dynamic = caseNumber;
      }
      ctx.body = this.info;
      //#endregion
 
      var orderInfo = await this.dbRead.findOne(SaleOrderPrint, {
        orderPrintCode: orderPrintCode
      });
      this.info.data2 = orderInfo;
    } catch (error) {
      this.info.result = false;
      this.info.msg = error.message;
    }
    ctx.body = this.info;
  }
  //#endregion
 
  //#region  保存扫描结果(部分打包)
  /// <summary>
  /// 部分打包
  /// </summary>
  /// <returns></returns>
  @Post()
  public async partialSaveScan() {
    let { ctx } = this;
    let body = ctx.request.body;
    let userInfo = await ctx.helper.userInfo();
 
    let where = "";
    let orderPrintCode = body.orderPrintCode;
    let wrapperBarcode = body.wrapperBarcode;
    let newExpressCode = body.newExpressCode;
    let weight = body.weight || 0;
    let isFullContainerLoad = orderPrintCode.indexOf("ZJ") === 0 ? 1 : 0; // 是否整拣
 
    //每个订单明细的扫描数量
    let dataList = body.dataList;
 
    try {
      let list: Array<any> = [];
      for (var model of dataList) {
        let order_Id = model.order_Id;
        let orderCode = model.orderCode;
        let caseNumber = model.caseNumber;
        let orderlist_id = model.orderList_Id;
        let scancount = model.scanCount;
        let weight = model.weight;
        let totalWeight = model.totalWeight;
        list.push({
          order_Id: order_Id,
          orderCode: orderCode,
          caseNumber: caseNumber,
          orderList_Id: orderlist_id,
          scanCount: scancount,
          weight: weight,
          totalWeight: totalWeight
        });
      }
      //#region 校验
      if (!orderPrintCode) {
        this.info.msg = "波次不能为空!";
        ctx.body = this.info;
        return;
      }
      let query = "";
      var wrapperBarcodeArray = wrapperBarcode.split("\n").filter(o => o);
 
      if (list == null || list.length == 0) {
        this.info.msg = "请先扫描条码!";
        ctx.body = this.info;
        return;
      }
 
      let orderPrintInfo = await this.dbRead.findOne(SaleOrderPrint, {
        orderPrintCode: orderPrintCode,
        userProduct_Id: userInfo.userProduct_Id
      });
      if (orderPrintInfo == null) {
        this.info.msg = "波次不存在!";
        ctx.body = this.info;
        return;
      }
      var printList = await this.dbRead.find(vSaleOrderPrintListGroup, {
        orderPrint_Id: orderPrintInfo.orderPrint_Id
      });
 
      if (printList.length == 0) {
        this.info.msg = "该波次下不存在数据!";
        ctx.body = this.info;
        return;
      }
 
      //验证耗材是否正确
      if (wrapperBarcodeArray.length > 0) {
        where = "'" + wrapperBarcodeArray.Join(",") + "'";
        query = `SELECT TOP 1 v.col FROM  [dbo].[Func_SplitStrToTable](${where}) AS v
            WHERE NOT EXISTS(
                SELECT * FROM dbo.vBase_ProductInfo_SKU WHERE productCode=v.col
            )`;
        let notExistsSku = await this.dbRead.query(query);
        if (notExistsSku && notExistsSku.col) {
          this.info.msg = "包材[" + notExistsSku + "]在物料信息中不存在,请先维护好基础数据!";
          ctx.body = this.info;
          return;
        }
      }
 
      if (newExpressCode) {
        var outerModel = await this.dbRead.findOne(SaleOuter, {
          expressCode: newExpressCode
        });
        if (outerModel) {
          this.info.msg = newExpressCode + "快递单号在[打包校验]中已存在,不允许重复使用!";
          ctx.body = this.info;
          return;
        }
      }
      //判断出库的物料数量是否大于可以出库的数量
      let isExistsSql = "";
      for (var model of list) {
        var orderList_Id = model.orderList_Id;
        var scanCount = model.scanCount;
        if (isExistsSql) {
          isExistsSql += "  UNION  ";
        }
        isExistsSql += `SELECT productCode,( SUM(quantityOrder) - ISNULL(SUM(quantityOuter), 0) ) AS enableQty,
        ${scanCount} AS currentQty FROM dbo.Sale_OrderPrintList WHERE orderPrint_Id=${orderPrintInfo.orderPrint_Id} 
        AND orderList_Id=${orderList_Id}
        AND quantityOrder > 0
        GROUP BY productCode
            HAVING SUM(quantityOrder) - ISNULL(SUM(quantityOuter), 0)<0
        `;
      }
      isExistsSql = "SELECT productCode,enableQty,currentQty FROM ( " + isExistsSql + " ) AS v";
      let table = await this.dbRead.query(isExistsSql);
      if (table != null && table.length > 0) {
        let row = table[0];
        this.info.msg = `物料[${row["productCode"]}]的可出库数量[${row["enableQty"]}]小于当前的出库数量[${row["currentQty"]}]!`;
        ctx.body = this.info;
        return;
      }
      //#endregion
 
      //#region 存在占位数和明细数量不相等的情况
      let orderGroup = list.reduce((all: Array<any>, next) => (all.some(item => item.order_Id == next.order_Id) ? all : [...all, next]), []);
      for (var gOrderInfo of orderGroup) {
        let query = `SELECT  *
              FROM    ( SELECT    ISNULL(SUM(L.QuantityOrderOrign), 0)-SUM(ISNULL(L.QuantityOuter, 0)) AS BatchQuantity ,
                                  ISNULL(( SELECT SUM(H.PlaceholderStorage) AS PlaceholderStorage
                                           FROM   Base_ProductPlaceHolder H
                                           WHERE  className ='销售订单'
                                                  AND H.MainID =32701
                                                  AND H.DetailID = L.orderList_Id
                                         ), 0) AS PlaceholderStorage
                        FROM      dbo.Sale_OrderPrintList AS L
                        WHERE      L.order_Id =${gOrderInfo.order_Id} AND L.OrderPrint_Id=1
                        GROUP BY  L.orderList_Id
                                                HAVING  ISNULL(SUM(L.QuantityOrderOrign), 0)> ISNULL(SUM(L.QuantityOuter), 0)
                      ) a
              WHERE   PlaceholderStorage <> BatchQuantity
              UNION ALL
              SELECT  *
              FROM    ( SELECT    ISNULL(SUM(L.PlaceholderStorage), 0) PlaceholderStorage ,
                                                    ISNULL(( SELECT    SUM(ISNULL(QuantityOrderOrign, 0) - ISNULL(QuantityOuter, 0)) AS BatchQuantity
                              FROM   dbo.Sale_OrderPrintList
                              WHERE  orderList_Id = L.DetailID AND isFullContainerLoad=${isFullContainerLoad}
                                AND order_Id =${gOrderInfo.order_Id}
                                                                AND ISNULL(QuantityOrderOrign, 0)> ISNULL(QuantityOuter, 0)
                          ), 0) AS BatchQuantity
                        FROM      Base_ProductPlaceHolder AS L
                        WHERE     className = '销售订单'
                                  AND  L.MainID =${gOrderInfo.order_Id}  AND L.isFullContainerLoad=${isFullContainerLoad}
                        GROUP BY  L.DetailID
                      ) a
              WHERE   PlaceholderStorage <> BatchQuantity;`;
        let holderDataList = await this.dbRead.query(query);
        if (holderDataList.length > 0) {
          this.info.msg = "分拣占位数和明细数量不相等的情况,不允许打包出库!";
          this.info.result = false;
          ctx.body = this.info;
          return;
        }
      }
      //#endregion
 
      //#region 保存
      let orderInfo = await this.dbRead.findOne(SaleOrder, list[0].order_Id);
      let saleOuter = new SaleOuter();
      saleOuter.consignor_Id = orderInfo.consignor_Id;
      saleOuter.consignorCode = orderInfo.consignorCode;
      saleOuter.consignorName = orderInfo.consignorName;
      saleOuter.expressCorp_Id = orderInfo.expressCorp_Id;
      saleOuter.expressCorpName = orderInfo.expressCorpName;
      saleOuter.expressCode = newExpressCode; //使用新的快递单号
      saleOuter.client_Id = orderInfo.client_Id || 0;
      saleOuter.clientCode = orderInfo.clientCode;
      saleOuter.clientShortName = orderInfo.clientShortName;
 
      saleOuter.orderType = "波次打包";
      saleOuter.order_Id = orderPrintInfo.orderPrint_Id;
      saleOuter.orderCode = orderPrintInfo.orderPrintCode; //对应波次单号
      saleOuter.storeOrderCode = orderInfo.storeOrderCode;
      saleOuter.shippingName = orderInfo.shippingName;
      saleOuter.shippingAddress = orderInfo.shippingAddress;
      saleOuter.mobile = orderInfo.mobile;
 
      saleOuter.storage_Id = orderInfo.storage_Id || 0;
      saleOuter.storageName = orderInfo.storageName;
      saleOuter.user_Id = userInfo.user_Id;
      saleOuter.userTrueName = userInfo.userTrueName;
      saleOuter.dept_Id = userInfo.dept_Id;
      saleOuter.deptName = userInfo.deptName;
      saleOuter.applyDate = new Date();
      saleOuter.createID = userInfo.user_Id;
      saleOuter.creator = userInfo.userTrueName;
 
      saleOuter.orderPrint_Id = orderPrintInfo.orderPrint_Id;
      saleOuter.orderPrintCode = orderPrintInfo.orderPrintCode;
 
      saleOuter.createDate = new Date();
      let outerCode = await ctx.service.common.getCodeRegular(268);
      saleOuter.outerCode = outerCode;
      saleOuter.weight = weight;
 
      saleOuter.platCorpName = userInfo.platCorpName;
      saleOuter.platUserCode = userInfo.platUserCode;
      saleOuter.platUserName = userInfo.platUserName;
      saleOuter.platUser_Id = userInfo.platUser_Id;
      saleOuter.userProductAlias = userInfo.userProductAlias;
      saleOuter.userProductCode = userInfo.userProductCode;
      saleOuter.userProduct_Id = userInfo.userProduct_Id;
 
      await this.dbWrite.save(saleOuter);
      //遍历扫描的明细物料,插入到 打包出库表
      for (var model of list) {
        var orderList_Id = model.orderList_Id;
        var scanCount = model.scanCount;
        //插入明细
        let orderDetail = await this.dbRead.findOne(SaleOrderList, model.orderList_Id);
        let outerDetail = new SaleOuterList();
        outerDetail.batchNumber = orderDetail.batchNumber;
        outerDetail.createDate = new Date();
        outerDetail.createID = userInfo.user_Id;
        outerDetail.creator = userInfo.userTrueName;
 
        outerDetail.order_Id = orderDetail.order_Id;
        outerDetail.orderCode = model.orderCode;
        outerDetail.orderList_Id = orderDetail.orderList_Id;
        outerDetail.outer_Id = saleOuter.outer_Id;
        outerDetail.product_Id = orderDetail.product_Id;
        outerDetail.productCode = orderDetail.productCode;
        outerDetail.productModel = orderDetail.productModel;
        outerDetail.productName = orderDetail.productName;
        outerDetail.productSpec = orderDetail.productSpec;
        outerDetail.quantityOrder = model.scanCount;
 
        outerDetail.salePrice = orderDetail.salePrice;
        outerDetail.subTotal = orderDetail.subTotal;
        outerDetail.caseNumber = model.caseNumber;
        outerDetail.smallUnit = orderDetail.smallUnit;
        outerDetail.bigUnit = orderDetail.bigUnit;
 
        outerDetail.extendField01 = orderDetail.extendField01;
        outerDetail.extendField02 = orderDetail.extendField02;
        outerDetail.extendField03 = orderDetail.extendField03;
        outerDetail.extendField04 = orderDetail.extendField04;
        outerDetail.extendField05 = orderDetail.extendField05;
        outerDetail.extendField06 = orderDetail.extendField06;
        outerDetail.extendField07 = orderDetail.extendField07;
        outerDetail.extendField08 = orderDetail.extendField08;
        outerDetail.extendField09 = orderDetail.extendField09;
        outerDetail.extendField10 = orderDetail.extendField10;
        outerDetail.weight = model.weight;
        outerDetail.totalWeight = model.totalWeight;
        await this.dbRead.save(outerDetail);
      }
      query = "";
      if (wrapperBarcodeArray.length > 0) {
        where = "'" + wrapperBarcodeArray.Join(",") + "'";
        //插入耗材
        query += `INSERT INTO dbo.Sale_OuterWrapper
        ( outer_Id ,
          order_Id ,
          product_Id ,
          productCode ,
          productName ,
          productModel ,
          productSpec ,
          quantity ,
          purchasePrice ,
          subTotal ,
          createID ,
          creator ,
          createDate,
          extendField01, extendField02, extendField03, extendField04, extendField05,
          extendField06, extendField07, extendField08, extendField09, extendField10
        )
                SELECT ${saleOuter.outer_Id},${list[0].order_Id},s.product_Id,s.productCode,s.productName,
                    s.productModel,s.productSpec,1,s.PurchasePrice,s.PurchasePrice,0,'',GETDATE(),
          extendField01, extendField02, extendField03, extendField04, extendField05,
          extendField06, extendField07, extendField08, extendField09, extendField10
                FROM  [dbo].[Func_SplitStrToTable](${where}) AS v
                INNER JOIN dbo.vBase_ProductInfo_SKU s ON v.col=s.productModel;`;
      }
      query += `UPDATE dbo.Sale_Outer SET subTotal=(SELECT SUM(ISNULL(subTotal,0)) FROM dbo.Sale_OuterList WHERE outer_Id=Sale_Outer.outer_Id),
                TotalQuantityOrder=(SELECT SUM(ISNULL(quantityOrder,0)) FROM dbo.Sale_OuterList WHERE outer_Id=Sale_Outer.outer_Id),
        totalWeight=(SELECT SUM(ISNULL(totalWeight,0)) FROM dbo.Sale_OuterList WHERE outer_Id=Sale_Outer.outer_Id)
                WHERE dbo.Sale_Outer.outer_Id=${saleOuter.outer_Id}`;
 
      await this.dbWrite.query(query);
      //#endregion
 
      //#region 审核
      //记录操作前的状态
      let ids = [];
      for (var gInfo of orderGroup) {
        ids.push(gInfo.order_Id);
      }
      let beforeOrderList = await this.dbRead.find(SaleOrder, {
        order_Id: In(ids)
      });
 
      const connection: any = await this.dbWrite.connection;
      let request = new sql.Request(connection.driver.master);
      request.input("outer_Id", saleOuter.outer_Id);
      request.input("user_Id", userInfo.user_Id);
      request.input("menu_Id", 268);
      await request.execute("sp_Sale_OuterBatchPartial_Check");
 
      for (var gInfo of orderGroup) {
        let _orderInfo = beforeOrderList.filter(f => f.order_Id == gInfo.order_Id)[0];
        let fromStatusId = _orderInfo.statusID || 0;
        //有可能是打包完成 ,有可能是部分打包,所以要从新查询出状态
        orderInfo = await this.dbRead.findOne(SaleOrder, _orderInfo.order_Id);
        let toStatusId = orderInfo.statusID;
        await ctx.service.outbound.orderHelper.setStatusHistory(orderInfo.order_Id, fromStatusId, toStatusId, "订单状态", "订单打包");
 
        //更新订单快递单号
        await this.dbWrite.update(SaleOrder, orderInfo.order_Id, {
          expressCode: newExpressCode
        });
      }
      //#endregion
 
      this.info.result = true;
      var data = {
        orderPrint_Id: orderPrintInfo.orderPrint_Id,
        order_Id: orderInfo.order_Id,
        outer_Id: saleOuter.outer_Id
      };
      this.info.data = data;
      this.info.msg = "扫描成功!";
    } catch (error) {
      this.info.result = false;
      this.info.msg = "错误:" + error.message;
    }
    ctx.body = this.info;
  }
  //#endregion
}