Commit 2356540b7e02620174bb90d3739bf664aeff718c

Authored by “wangming”
1 parent 79503e87

对成本进行了全逻辑的修改和添加

Antis.Erp.Plat/SERVICES_CONFIG.md
... ... @@ -88,7 +88,7 @@ python3 -m http.server 8888
88 88 "http://localhost:3021",
89 89 "http://localhost:3014",
90 90 "http://localhost:3015",
91   - "http://localhost:2015",
  91 + "http://localhost:2011",
92 92 "http://localhost:3009",
93 93 "http://localhost:2016",
94 94 "http://localhost:3000",
... ...
Antis.Erp.Plat/antis-ncc-admin/.env.development
1 1 # 开发
2 2  
3 3 VUE_CLI_BABEL_TRANSPILE_MODULES = true
4   -VUE_APP_BASE_API = 'http://localhost:2015'
  4 +VUE_APP_BASE_API = 'http://localhost:2011'
5 5 VUE_APP_BASE_WSS = 'ws://localhost:2011/websocket'
... ...
Antis.Erp.Plat/antis-ncc-admin/src/views/wtCgthd/Form.vue
... ... @@ -99,6 +99,11 @@
99 99 <el-input v-model="scope.row.dj" placeholder="选择入库编号自动填入" readonly :style="{ background: '#f5f7fa' }"></el-input>
100 100 </template>
101 101 </el-table-column>
  102 + <el-table-column prop="thdj" label="退货单价">
  103 + <template slot-scope="scope">
  104 + <el-input v-model="scope.row.thdj" placeholder="请输入退货单价" clearable @input="handleRefundPriceChange(scope.row)"></el-input>
  105 + </template>
  106 + </el-table-column>
102 107 <el-table-column prop="je" label="金额">
103 108 <template slot-scope="scope">
104 109 <el-input v-model="scope.row.je" placeholder="请输入" clearable @input="handleAmountFieldChange(scope.row)"></el-input>
... ... @@ -364,9 +369,13 @@
364 369 if (!item.hasOwnProperty('dyddbh')) {
365 370 this.$set(item, 'dyddbh', item.dyddbh || undefined);
366 371 }
  372 + if (!item.hasOwnProperty('thdj')) {
  373 + this.$set(item, 'thdj', item.thdj || item.dj || undefined);
  374 + }
367 375 });
368 376 this.syncDetailWarehouses();
369 377 this.updateTotalAmount();
  378 + this.reloadInboundOrdersForExistingRows();
370 379 })
371 380 } else {
372 381 this.dataForm.wtXsckdMxList = [];
... ... @@ -510,6 +519,7 @@
510 519 dw:undefined,
511 520 sl:undefined,
512 521 dj:undefined,
  522 + thdj: undefined,
513 523 je:undefined,
514 524 dyddbh: undefined,
515 525 description: undefined,
... ... @@ -527,6 +537,8 @@
527 537 },
528 538 handleDelWtXsckdMxEntityList(index) {
529 539 this.dataForm.wtXsckdMxList.splice(index, 1);
  540 + // 删除行后,重建下拉缓存索引,避免错位
  541 + this.rebuildInboundOrdersMap();
530 542 // 删除后更新总金额
531 543 this.updateTotalAmount();
532 544 },
... ... @@ -537,6 +549,7 @@
537 549  
538 550 this.$set(row, 'dyddbh', undefined);
539 551 this.$set(row, 'dj', '');
  552 + this.$set(row, 'thdj', '');
540 553 this.$set(row, 'je', '');
541 554  
542 555 await this.loadInboundOrders(row);
... ... @@ -558,10 +571,12 @@
558 571 if (!row.spbh || !warehouse) return;
559 572  
560 573 try {
  574 + const requestData = { spbh: row.spbh, ck: warehouse };
  575 + console.log('[loadInboundOrders] GET请求参数:', requestData);
561 576 const res = await request({
562 577 url: '/api/Extend/WtXsckd/GetPurchaseInboundOrders',
563 578 method: 'get',
564   - params: { spbh: row.spbh, ck: warehouse }
  579 + data: requestData
565 580 });
566 581 let rawList = [];
567 582 if (Array.isArray(res)) {
... ... @@ -582,6 +597,29 @@
582 597 console.error('加载入库单列表失败', e);
583 598 }
584 599 },
  600 + rebuildInboundOrdersMap() {
  601 + const oldMap = this.inboundOrdersMap || {};
  602 + const newMap = {};
  603 + (this.dataForm.wtXsckdMxList || []).forEach((row, idx) => {
  604 + const oldIdx = Object.keys(oldMap).find(key => {
  605 + const list = oldMap[key] || [];
  606 + return list.some(item => item.orderid === row.dyddbh);
  607 + });
  608 + if (oldIdx !== undefined) {
  609 + this.$set(newMap, idx, oldMap[oldIdx] || []);
  610 + }
  611 + });
  612 + this.inboundOrdersMap = newMap;
  613 + },
  614 + async reloadInboundOrdersForExistingRows() {
  615 + if (!this.dataForm || !Array.isArray(this.dataForm.wtXsckdMxList)) return;
  616 + const tasks = this.dataForm.wtXsckdMxList
  617 + .filter(row => row && row.spbh)
  618 + .map(row => this.loadInboundOrders(row));
  619 + if (tasks.length > 0) {
  620 + await Promise.all(tasks);
  621 + }
  622 + },
585 623 normalizeInboundOrder(item) {
586 624 const getVal = (obj, keys) => {
587 625 for (const key of keys) {
... ... @@ -604,6 +642,7 @@
604 642 const selected = orders.find(o => o.orderid === row.dyddbh);
605 643 if (selected) {
606 644 this.$set(row, 'dj', selected.dj);
  645 + this.$set(row, 'thdj', selected.dj);
607 646 const sl = parseFloat(row.sl) || 0;
608 647 if (sl > 0) {
609 648 this.$set(row, 'je', (sl * parseFloat(selected.dj)).toFixed(2));
... ... @@ -629,14 +668,17 @@
629 668 },
630 669  
631 670 // 处理主表出库仓库变化,同步更新所有明细行的出库仓库
632   - handleMainWarehouseChange(value) {
  671 + async handleMainWarehouseChange(value) {
633 672 this.syncDetailWarehouses();
634 673 this.inboundOrdersMap = {};
635 674 this.dataForm.wtXsckdMxList.forEach(row => {
636 675 this.$set(row, 'dyddbh', undefined);
637 676 this.$set(row, 'dj', '');
  677 + this.$set(row, 'thdj', '');
638 678 this.$set(row, 'je', '');
639 679 });
  680 + // 关键修复:仓库变化后,自动为已选商品重新加载入库编号
  681 + await this.reloadInboundOrdersForExistingRows();
640 682 this.updateTotalAmount();
641 683 },
642 684  
... ... @@ -688,7 +730,7 @@
688 730 // 处理数量变化
689 731 handleAmountChange(row) {
690 732 const sl = parseFloat(row.sl) || 0;
691   - const dj = parseFloat(row.dj) || 0;
  733 + const dj = parseFloat(row.thdj) || 0;
692 734 row.je = (sl * dj).toFixed(2);
693 735  
694 736 // 自动更新主表退款金额
... ... @@ -722,10 +764,10 @@
722 764 }
723 765 },
724 766  
725   - // 处理单价变化
726   - handlePriceChange(row) {
  767 + // 处理退货单价变化(金额按退货单价计算)
  768 + handleRefundPriceChange(row) {
727 769 const sl = parseFloat(row.sl) || 0;
728   - const dj = parseFloat(row.dj) || 0;
  770 + const dj = parseFloat(row.thdj) || 0;
729 771 row.je = (sl * dj).toFixed(2);
730 772  
731 773 // 自动更新主表退款金额
... ... @@ -764,8 +806,9 @@
764 806 // 自动设置数量为选择的序列号数量
765 807 currentRow.sl = selectedSerialNumbers.length.toString()
766 808 // 自动计算金额
767   - if (currentRow.dj) {
768   - currentRow.je = (parseFloat(currentRow.sl) * parseFloat(currentRow.dj)).toFixed(2)
  809 + if (currentRow.thdj || currentRow.dj) {
  810 + const usePrice = parseFloat(currentRow.thdj || currentRow.dj || 0)
  811 + currentRow.je = (parseFloat(currentRow.sl) * usePrice).toFixed(2)
769 812 }
770 813  
771 814 // 更新总金额
... ...
Antis.Erp.Plat/netcore/src/Application/NCC.API/Properties/launchSettings.json
... ... @@ -19,7 +19,7 @@
19 19 "commandName": "Project",
20 20 "dotnetRunMessages": "true",
21 21 "launchBrowser": false,
22   - "applicationUrl": "http://localhost:2015",
  22 + "applicationUrl": "http://localhost:2011",
23 23 "environmentVariables": {
24 24 "ASPNETCORE_ENVIRONMENT": "Development"
25 25 }
... ...
Antis.Erp.Plat/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/WtXsckdMxCrInput.cs
1   -using System;
  1 +using System;
2 2 using System.Collections.Generic;
3 3  
4 4 namespace NCC.Extend.Entitys.Dto.WtXsckd
... ... @@ -54,6 +54,11 @@ namespace NCC.Extend.Entitys.Dto.WtXsckd
54 54 public decimal dj { get; set; }
55 55  
56 56 /// <summary>
  57 + /// 退货单价(采购退货业务使用)
  58 + /// </summary>
  59 + public decimal? thdj { get; set; }
  60 +
  61 + /// <summary>
57 62 /// 金额
58 63 /// </summary>
59 64 public decimal je { get; set; }
... ... @@ -68,5 +73,10 @@ namespace NCC.Extend.Entitys.Dto.WtXsckd
68 73 /// </summary>
69 74 public string mdxx { get; set; }
70 75  
  76 + /// <summary>
  77 + /// 已选择的序列号列表
  78 + /// </summary>
  79 + public List<string> selectedSerialNumbers { get; set; }
  80 +
71 81 }
72 82 }
... ...
Antis.Erp.Plat/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/WtXsckdMxInfoOutput.cs
1   -using System;
  1 +using System;
2 2 using System.Collections.Generic;
3 3  
4 4 namespace NCC.Extend.Entitys.Dto.WtXsckd
... ... @@ -59,6 +59,11 @@ namespace NCC.Extend.Entitys.Dto.WtXsckd
59 59 public decimal dj { get; set; }
60 60  
61 61 /// <summary>
  62 + /// 退货单价(采购退货业务使用)
  63 + /// </summary>
  64 + public decimal? thdj { get; set; }
  65 +
  66 + /// <summary>
62 67 /// 金额
63 68 /// </summary>
64 69 public decimal je { get; set; }
... ...
Antis.Erp.Plat/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/WtXsckdMxEntity.cs
... ... @@ -72,6 +72,12 @@ namespace NCC.Extend.Entitys
72 72 public decimal Dj { get; set; }
73 73  
74 74 /// <summary>
  75 + /// 退货单价(采购退货业务使用)
  76 + /// </summary>
  77 + [SugarColumn(ColumnName = "thdj")]
  78 + public decimal? Thdj { get; set; }
  79 +
  80 + /// <summary>
75 81 /// 金额
76 82 /// </summary>
77 83 [SugarColumn(ColumnName = "je")]
... ...
Antis.Erp.Plat/netcore/src/Modularity/Extend/NCC.Extend/WtXsckdService.cs
... ... @@ -574,6 +574,94 @@ namespace NCC.Extend.WtXsckd
574 574 }
575 575 }
576 576 }
  577 + // ✅ 处理采购退货单:扣减在库序列号(Status 0 -> 1)
  578 + else if (input.djlx == "采购退货单")
  579 + {
  580 + Console.WriteLine($"Create方法 - 准备处理采购退货单序列号出库");
  581 + Console.WriteLine($" - 单据ID: {newEntity.Id}");
  582 + Console.WriteLine($" - 单据类型: {input.djlx}");
  583 + Console.WriteLine($" - 出库仓库: {entity.Cjck}");
  584 +
  585 + if (wtXsckdMxEntityList != null && wtXsckdMxEntityList.Any())
  586 + {
  587 + for (int i = 0; i < wtXsckdMxEntityList.Count; i++)
  588 + {
  589 + var detail = wtXsckdMxEntityList[i];
  590 + var inputDetail = (input.wtXsckdMxList != null && input.wtXsckdMxList.Count > i)
  591 + ? input.wtXsckdMxList[i]
  592 + : null;
  593 +
  594 + if (!string.IsNullOrEmpty(detail.Spbh) && int.TryParse(detail.Sl, out int slValue) && slValue > 0)
  595 + {
  596 + var outStoreId = !string.IsNullOrEmpty(detail.Ckck) ? detail.Ckck : entity.Cjck;
  597 + if (string.IsNullOrEmpty(outStoreId))
  598 + {
  599 + throw new Exception($"商品 {detail.Spmc} 未指定出库仓库,无法处理采购退货序列号");
  600 + }
  601 +
  602 + var warehouseIds = await _db.Queryable<WtCkEntity>()
  603 + .Where(c => c.Ssmd == outStoreId || c.Id == outStoreId)
  604 + .Select(c => c.Id)
  605 + .ToListAsync();
  606 + if (warehouseIds == null || warehouseIds.Count == 0)
  607 + {
  608 + warehouseIds = new List<string> { outStoreId };
  609 + }
  610 +
  611 + var selectedSerials = inputDetail?.selectedSerialNumbers?
  612 + .Where(s => !string.IsNullOrWhiteSpace(s))
  613 + .Select(s => s.Trim())
  614 + .Distinct()
  615 + .ToList() ?? new List<string>();
  616 +
  617 + List<string> serialsToOut;
  618 + if (selectedSerials.Count > 0)
  619 + {
  620 + serialsToOut = await _db.Queryable<WtSerialNumberEntity>()
  621 + .Where(s => s.Spbh == detail.Spbh
  622 + && s.Status == 0
  623 + && warehouseIds.Contains(s.InWarehouse)
  624 + && selectedSerials.Contains(s.SerialNumber))
  625 + .Select(s => s.SerialNumber)
  626 + .ToListAsync();
  627 +
  628 + if (serialsToOut.Count != slValue)
  629 + {
  630 + throw new Exception($"商品 {detail.Spmc} 选择的序列号数量与明细数量不一致,或包含非在库序列号");
  631 + }
  632 + }
  633 + else
  634 + {
  635 + serialsToOut = await _db.Queryable<WtSerialNumberEntity>()
  636 + .Where(s => s.Spbh == detail.Spbh
  637 + && s.Status == 0
  638 + && warehouseIds.Contains(s.InWarehouse))
  639 + .OrderBy(s => s.InTime)
  640 + .Take(slValue)
  641 + .Select(s => s.SerialNumber)
  642 + .ToListAsync();
  643 + if (serialsToOut.Count < slValue)
  644 + {
  645 + throw new Exception($"商品 {detail.Spmc} 在仓库可用序列号不足,需{slValue}个,实得{serialsToOut.Count}个");
  646 + }
  647 + }
  648 +
  649 + await _db.Updateable<WtSerialNumberEntity>()
  650 + .SetColumns(it => new WtSerialNumberEntity
  651 + {
  652 + Status = 1,
  653 + OutDjbh = newEntity.Id,
  654 + OutDjlx = input.djlx,
  655 + OutWarehouse = outStoreId,
  656 + OutTime = DateTime.Now,
  657 + OutOperator = userId ?? ""
  658 + })
  659 + .Where(it => serialsToOut.Contains(it.SerialNumber))
  660 + .ExecuteCommandAsync();
  661 + }
  662 + }
  663 + }
  664 + }
577 665  
578 666 // 自动生成导购提成记录
579 667 if (input.djlx == "销售出库单")
... ... @@ -2882,7 +2970,7 @@ ORDER BY t.`商品编号`;&quot;;
2882 2970 if (string.IsNullOrEmpty(detail.Spbh)) continue;
2883 2971 if (!int.TryParse(detail.Sl, out int qty) || qty <= 0) continue;
2884 2972  
2885   - decimal returnPrice = detail.Dj;
  2973 + decimal returnPrice = detail.Thdj.HasValue && detail.Thdj.Value > 0 ? detail.Thdj.Value : detail.Dj;
2886 2974  
2887 2975 foreach (var whId in warehouseIds)
2888 2976 {
... ... @@ -2910,6 +2998,14 @@ ORDER BY t.`商品编号`;&quot;;
2910 2998 "UPDATE wt_sp_cost SET cbj = @cbj, sl = @sl, update_time = NOW() WHERE spbh = @spbh AND ck = @ck",
2911 2999 new { cbj = newCbj, sl = newSl, spbh = detail.Spbh, ck = whId });
2912 3000  
  3001 + // 库存口径统一:以序列号在库数量为准
  3002 + var actualCount = await _db.Ado.GetIntAsync(
  3003 + "SELECT COUNT(*) FROM wt_serial_number WHERE spbh = @spbh AND in_warehouse = @ck AND status = 0",
  3004 + new SugarParameter[] { new SugarParameter("@spbh", detail.Spbh), new SugarParameter("@ck", whId) });
  3005 + await _db.Ado.ExecuteCommandAsync(
  3006 + "UPDATE wt_sp_cost SET sl = @sl, update_time = NOW() WHERE spbh = @spbh AND ck = @ck",
  3007 + new { sl = actualCount, spbh = detail.Spbh, ck = whId });
  3008 +
2913 3009 await _db.Ado.ExecuteCommandAsync(
2914 3010 "UPDATE wt_xsckd_mx SET cbdj = @cbdj, cbje = @cbje WHERE F_Id = @id",
2915 3011 new { cbdj = returnPrice, cbje = Math.Round(returnPrice * qty, 2), id = detail.Id });
... ... @@ -3067,7 +3163,28 @@ ORDER BY t.`商品编号`;&quot;;
3067 3163 if (string.IsNullOrEmpty(detail.Spbh)) continue;
3068 3164 if (!int.TryParse(detail.Sl, out int qty) || qty <= 0) continue;
3069 3165  
3070   - decimal returnPrice = detail.Dj;
  3166 + decimal returnPrice = detail.Thdj.HasValue && detail.Thdj.Value > 0 ? detail.Thdj.Value : detail.Dj;
  3167 +
  3168 + // 先回退序列号状态(采购退货出库的序列号恢复为在库)
  3169 + var serials = await _db.Queryable<WtSerialNumberEntity>()
  3170 + .Where(s => s.OutDjbh == id && s.Spbh == detail.Spbh)
  3171 + .Select(s => s.SerialNumber)
  3172 + .ToListAsync();
  3173 + if (serials.Any())
  3174 + {
  3175 + await _db.Updateable<WtSerialNumberEntity>()
  3176 + .SetColumns(it => new WtSerialNumberEntity
  3177 + {
  3178 + Status = 0,
  3179 + OutDjbh = "",
  3180 + OutDjlx = "",
  3181 + OutWarehouse = "",
  3182 + OutTime = null,
  3183 + OutOperator = ""
  3184 + })
  3185 + .Where(it => serials.Contains(it.SerialNumber))
  3186 + .ExecuteCommandAsync();
  3187 + }
3071 3188  
3072 3189 foreach (var whId in warehouseIds)
3073 3190 {
... ...