From cf3050083e157819b94781d0445547ffc73e21f2 Mon Sep 17 00:00:00 2001
From: pan <antony1029@163.com>
Date: 星期五, 28 十一月 2025 21:17:28 +0800
Subject: [PATCH] 提交
---
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Jobs/InventoryLockJob.cs | 22 +
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_OutboundBatch.cs | 68 +++
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/OutStockLockInfoService.cs | 7
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Inbound/InboundOrderController.cs | 12
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_Outbound.cs | 195 +++++++++
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Program.cs | 9
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Common/StockEnum/OutLockStockStatusEnum.cs | 11
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs | 2
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_TaskInfoService/WIDESEA_TaskInfoService.csproj | 1
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_OutboundOrderDetail.cs | 4
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs | 2
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_IBasicService/IMaterialUnitService.cs | 2
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_OutboundLockInfo.cs | 2
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundOrderDetailService.cs | 183 +++++++++
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_BasicService/MaterialUnitService.cs | 12
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundBatchPickingService.cs | 571 ++++++++++++++++++++++++++++
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_InboundService/InboundOrderService.cs | 37
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_IOutboundService/IOutStockLockInfoService.cs | 2
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundOrderService.cs | 18
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_IOutboundService/IOutboundOrderDetailService.cs | 2
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs | 2
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/WIDESEA_OutboundService.csproj | 1
22 files changed, 1,128 insertions(+), 37 deletions(-)
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs"
index dc62c83..edb4c46 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs"
@@ -217,7 +217,7 @@
{
return Repository.QueryData(x => locationCodes.Contains(x.LocationCode));
}
-
+
public List<LocationTypeDto> GetLocationTypes()
{
return _locationTypeRepository.Db.Queryable<Dt_LocationType>().Select(x =>
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_BasicService/MaterialUnitService.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_BasicService/MaterialUnitService.cs"
index e0c46ef..7c48c96 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_BasicService/MaterialUnitService.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_BasicService/MaterialUnitService.cs"
@@ -156,6 +156,18 @@
return ConvertAsync(materialData, quantity, materialData.PurchaseUnit, materialData.StockUnit);
}
+ public async Task<MaterialWithUnitConversionResult> ConvertFromToStockAsync(string materialCode,string fromUom, decimal quantity)
+ {
+ var materialData = await GetMaterialWithUnitsAsync(materialCode);
+
+ // 濡傛灉棰嗘枡鍗曚綅鍜屽簱瀛樺崟浣嶇浉鍚岋紝鐩存帴杩斿洖
+ if (fromUom.Equals(materialData.StockUnit, StringComparison.OrdinalIgnoreCase))
+ return new MaterialWithUnitConversionResult(quantity, materialData.StockUnit, false);
+
+ return ConvertAsync(materialData, quantity, fromUom, materialData.StockUnit);
+ }
+
+
/// <summary>
/// 棰嗘枡鍗曚綅杞簱瀛樺崟浣�
/// </summary>
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_Common/StockEnum/OutLockStockStatusEnum.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_Common/StockEnum/OutLockStockStatusEnum.cs"
index 2cc1115..32471a8 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_Common/StockEnum/OutLockStockStatusEnum.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_Common/StockEnum/OutLockStockStatusEnum.cs"
@@ -16,6 +16,17 @@
// 宸插嚭搴� = 4,
// 宸插洖搴� = 5
//}
+
+ // 鏋氫妇瀹氫箟
+ public enum BatchStatusEnum
+ {
+ 鍒嗛厤涓� = 0,
+ 鎵ц涓� = 1,
+ 宸插畬鎴� = 2,
+ 宸插洖搴� = 3,
+ 宸插彇娑� = 4
+ }
+
public enum SplitPackageStatusEnum
{
宸叉媶鍖� = 1,
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_IBasicService/IMaterialUnitService.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_IBasicService/IMaterialUnitService.cs"
index 9e544d6..d06b50e 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_IBasicService/IMaterialUnitService.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_IBasicService/IMaterialUnitService.cs"
@@ -20,6 +20,8 @@
Task<Dictionary<string, MaterialWithUnitConversionResult>> BatchConvertPurchaseToStockAsync(List<BatchConversionRequest> requests);
Task<MaterialWithUnitConversionResult> ConvertAsync(string materialCode, decimal quantity, string fromUnit, string toUnit);
Task<MaterialWithUnitConversionResult> ConvertIssueToStockAsync(string materialCode, decimal quantity);
+
+ Task<MaterialWithUnitConversionResult> ConvertFromToStockAsync(string materialCode, string fromUom, decimal quantity);
Task<MaterialWithUnitConversionResult> ConvertPurchaseToStockAsync(string materialCode, decimal quantity);
Task<decimal?> GetConversionRatioAsync(string materialCode, string fromUnit, string toUnit);
Task<string> GetIssueUnitAsync(string materialCode);
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_IOutboundService/IOutStockLockInfoService.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_IOutboundService/IOutStockLockInfoService.cs"
index a97e67f..d4e589f 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_IOutboundService/IOutStockLockInfoService.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_IOutboundService/IOutStockLockInfoService.cs"
@@ -26,7 +26,7 @@
Task<List<Dt_OutStockLockInfo>> GetByPalletCode(string palletCode, int? status = null);
Task<LockInfoDetailDto> GetLockInfoDetail(int lockInfoId);
- Dt_OutStockLockInfo GetOutStockLockInfo(Dt_OutboundOrder outboundOrder,Dt_OutboundOrderDetail outboundOrderDetail,Dt_StockInfo outStock, decimal assignQuantity, string barcode = null);
+ Dt_OutStockLockInfo GetOutStockLockInfo(Dt_OutboundOrder outboundOrder,Dt_OutboundOrderDetail outboundOrderDetail,Dt_StockInfo outStock, decimal assignQuantity, string barcode = null, string outboundBatchNo = "");
List<Dt_OutStockLockInfo> GetOutStockLockInfos(Dt_OutboundOrder outboundOrder, Dt_OutboundOrderDetail outboundOrderDetail, List<Dt_StockInfo> outStocks, int? taskNum = null);
Task<List<Dt_OutStockLockInfo>> GetPalletLockInfos(string palletCode);
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_IOutboundService/IOutboundOrderDetailService.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_IOutboundService/IOutboundOrderDetailService.cs"
index 3525497..3cb776c 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_IOutboundService/IOutboundOrderDetailService.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_IOutboundService/IOutboundOrderDetailService.cs"
@@ -23,6 +23,6 @@
WebResponseContent LockOutboundStockDataUpdate(List<Dt_StockInfo> stockInfos, List<Dt_OutboundOrderDetail> outboundOrderDetails, List<Dt_OutStockLockInfo> outStockLockInfos, List<Dt_LocationInfo> locationInfos, LocationStatusEnum locationStatus = LocationStatusEnum.Lock, List<Dt_Task>? tasks = null);
(List<Dt_StockInfo>, Dt_OutboundOrderDetail, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) AssignStockOutbound(Dt_OutboundOrderDetail outboundOrderDetail, List<StockSelectViewDTO> stockSelectViews);
//List<Dt_OutboundOrderDetail> GetOutboundStockDataById(int id);
-
+ Task<(List<Dt_StockInfo>, List<Dt_OutboundOrderDetail>, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>)> AssignStockForBatch(Dt_OutboundOrderDetail orderDetail, decimal batchQuantity, string batchNo);
}
}
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_InboundService/InboundOrderService.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_InboundService/InboundOrderService.cs"
index 15294a8..729b4e1 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_InboundService/InboundOrderService.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_InboundService/InboundOrderService.cs"
@@ -96,11 +96,11 @@
item.Unit = purchaseToStockResult.Unit;
item.OrderQuantity = purchaseToStockResult.Quantity;
}
- if (model .OrderType != InOrderTypeEnum.Allocat.ObjToInt())
+ if (model.OrderType != InOrderTypeEnum.Allocat.ObjToInt())
{
model.InboundOrderNo = CreateCodeByRule(nameof(RuleCodeEnum.InboundOrderRule));
}
-
+
Db.InsertNav(model).Include(x => x.Details).ExecuteCommand();
}
return WebResponseContent.Instance.OK();
@@ -341,12 +341,12 @@
if (!result2.Item1) return content = WebResponseContent.Instance.Error(result2.Item2);
// materielGroupDTO.WarehouseCode
- var code = _warehouseAreaRepository.Db.Queryable<Dt_WarehouseArea>().Where(x => x.Code == materielGroupDTO.WarehouseType).Select(x=>x.Code).First();
- if(string.IsNullOrEmpty(code))
+ var code = _warehouseAreaRepository.Db.Queryable<Dt_WarehouseArea>().Where(x => x.Code == materielGroupDTO.WarehouseType).Select(x => x.Code).First();
+ if (string.IsNullOrEmpty(code))
{
return content = WebResponseContent.Instance.Error($"浠撳簱涓病鏈夎{materielGroupDTO.WarehouseType}缂栧彿銆�");
}
-
+
Dt_InboundOrder inboundOrder = GetInboundOrder(materielGroupDTO.OrderNo);
@@ -368,10 +368,10 @@
if (stockInfo == null)
{
- stockInfo = new Dt_StockInfo() { PalletType = (int)PalletTypeEnum.None,LocationType=materielGroupDTO.locationType.ObjToInt() };
+ stockInfo = new Dt_StockInfo() { PalletType = (int)PalletTypeEnum.None, LocationType = materielGroupDTO.locationType.ObjToInt() };
stockInfo.Details = new List<Dt_StockInfoDetail>();
}
-
+
foreach (var item in dbinboundOrderDetails)
{
stockInfo.Details.Add(new Dt_StockInfoDetail
@@ -385,15 +385,15 @@
SupplyCode = item.SupplyCode,
WarehouseCode = materielGroupDTO.WarehouseType,
StockQuantity = item.OrderQuantity,
- BarcodeQty=item.BarcodeQty,
- BarcodeUnit=item.BarcodeUnit,
- FactoryArea= inboundOrder.FactoryArea,
- Status = 0,
+ BarcodeQty = item.BarcodeQty,
+ BarcodeUnit = item.BarcodeUnit,
+ FactoryArea = inboundOrder.FactoryArea,
+ Status = 0,
OrderNo = inboundOrder.InboundOrderNo,
BusinessType = inboundOrder.BusinessType,
-
+
});
-
+
item.ReceiptQuantity = item.BarcodeQty;
item.OrderDetailStatus = OrderDetailStatusEnum.Over.ObjToInt();
item.WarehouseCode = materielGroupDTO.WarehouseType;
@@ -440,7 +440,7 @@
WebResponseContent content = new WebResponseContent();
try
- {
+ {
(bool, string, object?) result2 = ModelValidate.ValidateModelData(materielGroupDTO);
if (!result2.Item1) return content = WebResponseContent.Instance.Error(result2.Item2);
@@ -450,7 +450,8 @@
return content = WebResponseContent.Instance.Error($"鍖哄煙涓病鏈夎{materielGroupDTO.WarehouseCode}缂栧彿銆�");
}
- if(_stockRepository.QueryFirst(x=>x.PalletCode == materielGroupDTO.PalletCode)!=null){
+ if (_stockRepository.QueryFirst(x => x.PalletCode == materielGroupDTO.PalletCode) != null)
+ {
return WebResponseContent.Instance.Error("璇ユ墭鐩樺凡缁忕粍杩囩洏");
}
@@ -469,7 +470,7 @@
{
if (stockInfo == null)
{
- stockInfo = new Dt_StockInfo() { PalletType = PalletTypeEnum.Empty.ObjToInt(), StockStatus = StockStatusEmun.缁勭洏鏆傚瓨.ObjToInt(), PalletCode = materielGroupDTO.PalletCode,LocationType= materielGroupDTO.WarehouseCode.ObjToInt() };
+ stockInfo = new Dt_StockInfo() { PalletType = PalletTypeEnum.Empty.ObjToInt(), StockStatus = StockStatusEmun.缁勭洏鏆傚瓨.ObjToInt(), PalletCode = materielGroupDTO.PalletCode, LocationType = materielGroupDTO.WarehouseCode.ObjToInt() };
stockInfo.Details = new List<Dt_StockInfoDetail>();
}
else
@@ -650,13 +651,13 @@
{
return WebResponseContent.Instance.Error("鎵樼洏鍙蜂笉鑳戒负绌�");
}
- var stock= _stockRepository.Db.Queryable<Dt_StockInfo>().Includes(o=>o.Details).First(x => x.PalletCode == palletCode && x.StockStatus ==(int)StockStatusEmun.缁勭洏鏆傚瓨);
+ var stock = _stockRepository.Db.Queryable<Dt_StockInfo>().Includes(o => o.Details).First(x => x.PalletCode == palletCode && x.StockStatus == (int)StockStatusEmun.缁勭洏鏆傚瓨);
if (stock == null)
{
return WebResponseContent.Instance.Error($"鏈壘鍒版墭鐩樺彿{palletCode}瀵瑰簲鐨勫簱瀛樿褰�");
}
- if(stock.Details == null || !stock.Details.Any())
+ if (stock.Details == null || !stock.Details.Any())
{
_stockRepository.DeleteData(stock);
return WebResponseContent.Instance.OK();
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_OutboundBatch.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_OutboundBatch.cs"
new file mode 100644
index 0000000..7f75efd
--- /dev/null
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_OutboundBatch.cs"
@@ -0,0 +1,68 @@
+锘縰sing SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WIDESEA_Core.DB.Models;
+
+namespace WIDESEA_Model.Models.Outbound
+{
+
+
+ /// <summary>
+ /// 鍑哄簱鎵规琛�
+ /// </summary>
+ [SugarTable("Dt_OutboundBatch")]
+ public class Dt_OutboundBatch : BaseEntity
+ {
+ /// <summary>
+ /// 涓婚敭ID锛堣嚜澧烇級
+ /// </summary>
+ [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] //
+ public int Id { get; set; }
+
+ /// <summary>
+ /// 鎵规鍙�
+ /// </summary>
+ [SugarColumn(ColumnName = "BatchNo", Length = 50, IsNullable = false)]
+ public string BatchNo { get; set; }
+
+ /// <summary>
+ /// 璁㈠崟鍙�
+ /// </summary>
+ [SugarColumn(ColumnName = "OrderNo", Length = 50, IsNullable = false)]
+ public string OrderNo { get; set; }
+
+ /// <summary>
+ /// 璁㈠崟鏄庣粏ID
+ /// </summary>
+ [SugarColumn(ColumnName = "OrderDetailId", IsNullable = false)]
+ public int OrderDetailId { get; set; }
+
+ /// <summary>
+ /// 鎵规鍒嗛厤鏁伴噺
+ /// </summary>
+ [SugarColumn(ColumnName = "BatchQuantity", IsNullable = false)] // 绮惧害18锛屽皬鏁颁綅2
+ public decimal BatchQuantity { get; set; }
+
+ /// <summary>
+ /// 宸插畬鎴愭暟閲忥紙榛樿0锛�
+ /// </summary>
+ [SugarColumn(ColumnName = "CompletedQuantity", DefaultValue = "0")] // 榛樿鍊�0
+ public decimal CompletedQuantity { get; set; } = 0; // 浠g爜灞傞粯璁ゅ�硷紝涓庢暟鎹簱榛樿鍊间竴鑷�
+
+ /// <summary>
+ /// 鎵规鐘舵�侊紙榛樿0锛�
+ /// </summary>
+ [SugarColumn(ColumnName = "BatchStatus", DefaultValue = "0")]
+ public int BatchStatus { get; set; } = 0;
+
+
+ /// <summary>
+ /// 鎿嶄綔浜�
+ /// </summary>
+ [SugarColumn(ColumnName = "Operator", Length = 50, IsNullable = true)] // 鍙┖
+ public string Operator { get; set; }
+ }
+}
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_OutboundLockInfo.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_OutboundLockInfo.cs"
index 120729c..50a2684 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_OutboundLockInfo.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_OutboundLockInfo.cs"
@@ -136,6 +136,8 @@
public string BarcodeUnit { get; set; }
+ public string OutboundBatchNo { get; set; }
+
[Navigate(NavigateType.OneToOne, nameof(StockInfo))]//涓�瀵逛竴 SchoolId鏄疭tudentA绫婚噷闈㈢殑
public Dt_StockInfo StockInfo { get; set; } //涓嶈兘璧嬪�煎彧鑳芥槸null
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_OutboundOrderDetail.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_OutboundOrderDetail.cs"
index 2fa8b35..95fcf3b 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_OutboundOrderDetail.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_OutboundOrderDetail.cs"
@@ -145,5 +145,9 @@
public decimal PickedQty { get; set; }
public string documentsNO { get; set; }
+
+ public decimal AllocatedQuantity { get; set; }
+
+ public string BatchAllocateStatus { get; set; }
}
}
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutStockLockInfoService.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutStockLockInfoService.cs"
index d4a584d..ef15c2e 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutStockLockInfoService.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutStockLockInfoService.cs"
@@ -43,7 +43,7 @@
Dt_OutboundOrderDetail outboundOrderDetail,
Dt_StockInfo outStock,
decimal assignQuantity,
- string barcode = null)
+ string barcode = null,string outboundBatchNo = "")
{
// 鑾峰彇搴撳瓨鏄庣粏淇℃伅
var stockDetails = outStock.Details
@@ -107,9 +107,12 @@
IsSplitted = 0,
MaterielCode = outboundOrderDetail.MaterielCode,
BatchNo = firstAvailableDetail.BatchNo,
- Unit = firstAvailableDetail.BarcodeUnit,
+ Unit = firstAvailableDetail.Unit,
+ BarcodeQty = firstAvailableDetail.BarcodeQty,
+ BarcodeUnit = firstAvailableDetail.BarcodeUnit,
FactoryArea = firstAvailableDetail.FactoryArea,
lineNo = outboundOrderDetail.lineNo,
+ OutboundBatchNo= outboundBatchNo
};
}
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundBatchPickingService.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundBatchPickingService.cs"
new file mode 100644
index 0000000..445c6e5
--- /dev/null
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundBatchPickingService.cs"
@@ -0,0 +1,571 @@
+锘縰sing Microsoft.Extensions.Logging;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WIDESEA_BasicService;
+using WIDESEA_Common.OrderEnum;
+using WIDESEA_Common.StockEnum;
+using WIDESEA_Core;
+using WIDESEA_Core.BaseRepository;
+using WIDESEA_Core.BaseServices;
+using WIDESEA_IAllocateService;
+using WIDESEA_IBasicService;
+using WIDESEA_IOutboundService;
+using WIDESEA_IStockService;
+using WIDESEA_Model.Models;
+using WIDESEA_Model.Models.Basic;
+using WIDESEA_Model.Models.Outbound;
+
+namespace WIDESEA_OutboundService
+{
+ public class OutboundBatchPickingService : ServiceBase<Dt_PickingRecord, IRepository<Dt_PickingRecord>>
+ {
+
+
+ private readonly IUnitOfWorkManage _unitOfWorkManage;
+ public IRepository<Dt_PickingRecord> Repository => BaseDal;
+
+ private readonly IStockInfoService _stockInfoService;
+ private readonly IStockService _stockService;
+ private readonly IOutStockLockInfoService _outStockLockInfoService;
+ private readonly IStockInfoDetailService _stockInfoDetailService;
+ private readonly ILocationInfoService _locationInfoService;
+ private readonly IOutboundOrderDetailService _outboundOrderDetailService;
+ private readonly IOutboundOrderService _outboundOrderService;
+ private readonly ISplitPackageService _splitPackageService;
+ private readonly IRepository<Dt_Task> _taskRepository;
+ private readonly IESSApiService _eSSApiService;
+ private readonly IInvokeMESService _invokeMESService;
+ private readonly IDailySequenceService _dailySequenceService;
+ private readonly IAllocateService _allocateService;
+ private readonly IRepository<Dt_OutboundBatch> _outboundBatchRepository;
+ private readonly ILogger<OutboundPickingService> _logger;
+
+ private Dictionary<string, string> stations = new Dictionary<string, string>
+ {
+ {"2-1","2-9" },
+ {"3-1","3-9" },
+
+ };
+
+ private Dictionary<string, string> movestations = new Dictionary<string, string>
+ {
+ {"2-1","2-5" },
+ {"3-1","3-5" },
+
+ };
+
+ public OutboundBatchPickingService(IRepository<Dt_PickingRecord> BaseDal, IUnitOfWorkManage unitOfWorkManage, IStockInfoService stockInfoService, IStockService stockService,
+ IOutStockLockInfoService outStockLockInfoService, IStockInfoDetailService stockInfoDetailService, ILocationInfoService locationInfoService,
+ IOutboundOrderDetailService outboundOrderDetailService, ISplitPackageService splitPackageService, IOutboundOrderService outboundOrderService,
+ IRepository<Dt_Task> taskRepository, IESSApiService eSSApiService, ILogger<OutboundPickingService> logger, IInvokeMESService invokeMESService, IDailySequenceService dailySequenceService, IAllocateService allocateService) : base(BaseDal)
+ {
+ _unitOfWorkManage = unitOfWorkManage;
+ _stockInfoService = stockInfoService;
+ _stockService = stockService;
+ _outStockLockInfoService = outStockLockInfoService;
+ _stockInfoDetailService = stockInfoDetailService;
+ _locationInfoService = locationInfoService;
+ _outboundOrderDetailService = outboundOrderDetailService;
+ _splitPackageService = splitPackageService;
+ _outboundOrderService = outboundOrderService;
+ _taskRepository = taskRepository;
+ _eSSApiService = eSSApiService;
+ _logger = logger;
+ _invokeMESService = invokeMESService;
+ _dailySequenceService = dailySequenceService;
+ _allocateService = allocateService;
+ }
+
+
+ #region 鍒嗘壒鍒嗘嫞
+
+ /// <summary>
+ /// 鍒嗘壒鍒嗘嫞纭
+ /// </summary>
+ public async Task<WebResponseContent> ConfirmBatchPicking(string orderNo, string batchNo, string palletCode, string barcode, decimal actualPickedQty)
+ {
+ try
+ {
+ _unitOfWorkManage.BeginTran();
+
+ // 1. 楠岃瘉鍒嗘嫞璇锋眰
+ var validationResult = await ValidateBatchPickingRequest(orderNo, batchNo, palletCode, barcode, actualPickedQty);
+ if (!validationResult.IsValid)
+ return WebResponseContent.Instance.Error(validationResult.ErrorMessage);
+
+ var (lockInfo, orderDetail, stockDetail) = validationResult.Data;
+
+ // 2. 鎵ц鍒嗘嫞閫昏緫
+ var pickingResult = await ExecuteBatchPickingLogic(lockInfo, orderDetail, stockDetail, actualPickedQty);
+
+ // 3. 鏇存柊鎵规瀹屾垚鏁伴噺
+ await UpdateBatchCompletedQuantity(batchNo, actualPickedQty);
+
+ // 4. 鏇存柊璁㈠崟鐩稿叧鏁版嵁
+ await UpdateOrderRelatedData(orderDetail.Id, actualPickedQty, orderNo);
+
+ // 5. 璁板綍鎷i�夊巻鍙�
+ await RecordPickingHistory(pickingResult, orderNo, palletCode, batchNo);
+
+ _unitOfWorkManage.CommitTran();
+
+ return WebResponseContent.Instance.OK("鍒嗘壒鍒嗘嫞鎴愬姛");
+ }
+ catch (Exception ex)
+ {
+ _unitOfWorkManage.RollbackTran();
+ _logger.LogError($"鍒嗘壒鍒嗘嫞澶辫触 - OrderNo: {orderNo}, BatchNo: {batchNo}, Error: {ex.Message}");
+ return WebResponseContent.Instance.Error($"鍒嗘壒鍒嗘嫞澶辫触锛歿ex.Message}");
+ }
+ }
+
+ private async Task<ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail)>> ValidateBatchPickingRequest(
+ string orderNo, string batchNo, string palletCode, string barcode, decimal actualPickedQty)
+ {
+ // 鏌ユ壘鎵规閿佸畾淇℃伅
+ var lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+ .Where(x => x.OrderNo == orderNo &&
+ x.BatchNo == batchNo &&
+ x.PalletCode == palletCode &&
+ x.CurrentBarcode == barcode &&
+ x.Status == (int)OutLockStockStatusEnum.鍑哄簱涓�)
+ .FirstAsync();
+
+ if (lockInfo == null)
+ return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail)>.Error("鏈壘鍒版湁鏁堢殑鎵规閿佸畾淇℃伅");
+
+ if (actualPickedQty <= 0 || actualPickedQty > lockInfo.AssignQuantity - lockInfo.PickedQty)
+ return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail)>.Error("鍒嗘嫞鏁伴噺鏃犳晥");
+
+ // 鑾峰彇璁㈠崟鏄庣粏鍜屽簱瀛樻槑缁�
+ var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+ .FirstAsync(x => x.Id == lockInfo.OrderDetailId);
+
+ var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+ .FirstAsync(x => x.Barcode == barcode && x.StockId == lockInfo.StockId);
+
+ return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail)>.Success((lockInfo, orderDetail, stockDetail));
+ }
+
+ private async Task<PickingResult> ExecuteBatchPickingLogic(
+ Dt_OutStockLockInfo lockInfo, Dt_OutboundOrderDetail orderDetail,
+ Dt_StockInfoDetail stockDetail, decimal actualPickedQty)
+ {
+ // 鏇存柊閿佸畾淇℃伅
+ lockInfo.PickedQty += actualPickedQty;
+ if (lockInfo.PickedQty >= lockInfo.AssignQuantity)
+ {
+ lockInfo.Status = (int)OutLockStockStatusEnum.鎷i�夊畬鎴�;
+ }
+ await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
+
+ // 鏇存柊搴撳瓨
+ stockDetail.StockQuantity -= actualPickedQty;
+ stockDetail.OutboundQuantity += actualPickedQty;
+
+ if (stockDetail.StockQuantity <= 0)
+ {
+ stockDetail.Status = (int)StockStatusEmun.鍑哄簱瀹屾垚;
+ }
+ await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
+
+ return new PickingResult
+ {
+ FinalLockInfo = lockInfo,
+ ActualPickedQty = actualPickedQty
+ };
+ }
+
+ private async Task UpdateBatchCompletedQuantity(string batchNo, decimal pickedQty)
+ {
+ await _outboundBatchRepository.Db.Updateable<Dt_OutboundBatch>()
+ .SetColumns(x => x.CompletedQuantity == x.CompletedQuantity + pickedQty)
+ .Where(x => x.BatchNo == batchNo)
+ .ExecuteCommandAsync();
+
+ // 妫�鏌ユ壒娆℃槸鍚﹀畬鎴�
+ var batch = await _outboundBatchRepository.Db.Queryable<Dt_OutboundBatch>()
+ .FirstAsync(x => x.BatchNo == batchNo);
+
+ if (batch.CompletedQuantity >= batch.BatchQuantity)
+ {
+ batch.BatchStatus = (int)BatchStatusEnum.宸插畬鎴�;
+ await _outboundBatchRepository.Db.Updateable(batch).ExecuteCommandAsync();
+ }
+ }
+
+ #endregion
+
+ #region 鎵嬪姩鎷嗗寘
+
+ /// <summary>
+ /// 鎵嬪姩鎷嗗寘
+ /// </summary>
+ public async Task<WebResponseContent> ManualSplitPackage(string orderNo, string batchNo, string originalBarcode, decimal splitQuantity)
+ {
+ try
+ {
+ _unitOfWorkManage.BeginTran();
+
+ // 1. 楠岃瘉鎷嗗寘璇锋眰
+ var validationResult = await ValidateManualSplitRequest(orderNo, batchNo, originalBarcode, splitQuantity);
+ if (!validationResult.IsValid)
+ return WebResponseContent.Instance.Error(validationResult.ErrorMessage);
+
+ var (lockInfo, stockDetail) = validationResult.Data;
+
+ // 2. 鎵ц鎷嗗寘閫昏緫
+ var splitResult = await ExecuteManualSplit(lockInfo, stockDetail, splitQuantity, batchNo);
+
+ _unitOfWorkManage.CommitTran();
+
+ return WebResponseContent.Instance.OK("鎵嬪姩鎷嗗寘鎴愬姛", new { NewBarcode = splitResult.NewBarcode });
+ }
+ catch (Exception ex)
+ {
+ _unitOfWorkManage.RollbackTran();
+ _logger.LogError($"鎵嬪姩鎷嗗寘澶辫触 - OrderNo: {orderNo}, BatchNo: {batchNo}, Barcode: {originalBarcode}, Error: {ex.Message}");
+ return WebResponseContent.Instance.Error($"鎵嬪姩鎷嗗寘澶辫触锛歿ex.Message}");
+ }
+ }
+
+ private async Task<ValidationResult<(Dt_OutStockLockInfo, Dt_StockInfoDetail)>> ValidateManualSplitRequest(
+ string orderNo, string batchNo, string originalBarcode, decimal splitQuantity)
+ {
+ var lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+ .Where(x => x.OrderNo == orderNo &&
+ x.BatchNo == batchNo &&
+ x.CurrentBarcode == originalBarcode &&
+ x.Status == (int)OutLockStockStatusEnum.鍑哄簱涓�)
+ .FirstAsync();
+
+ if (lockInfo == null)
+ return ValidationResult<(Dt_OutStockLockInfo, Dt_StockInfoDetail)>.Error("鏈壘鍒版湁鏁堢殑閿佸畾淇℃伅");
+
+ var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+ .FirstAsync(x => x.Barcode == originalBarcode && x.StockId == lockInfo.StockId);
+
+ if (stockDetail.StockQuantity < splitQuantity)
+ return ValidationResult<(Dt_OutStockLockInfo, Dt_StockInfoDetail)>.Error("鎷嗗寘鏁伴噺涓嶈兘澶т簬搴撳瓨鏁伴噺");
+
+ if (lockInfo.AssignQuantity - lockInfo.PickedQty < splitQuantity)
+ return ValidationResult<(Dt_OutStockLockInfo, Dt_StockInfoDetail)>.Error("鎷嗗寘鏁伴噺涓嶈兘澶т簬鏈嫞閫夋暟閲�");
+
+ return ValidationResult<(Dt_OutStockLockInfo, Dt_StockInfoDetail)>.Success((lockInfo, stockDetail));
+ }
+
+ private async Task<SplitResultDto> ExecuteManualSplit(Dt_OutStockLockInfo lockInfo, Dt_StockInfoDetail stockDetail,
+ decimal splitQuantity, string batchNo)
+ {
+ // 鐢熸垚鏂版潯鐮�
+ string newBarcode = await GenerateNewBarcode();
+
+ // 鍒涘缓鏂板簱瀛樻槑缁�
+ var newStockDetail = new Dt_StockInfoDetail
+ {
+ StockId = stockDetail.StockId,
+ MaterielCode = stockDetail.MaterielCode,
+ OrderNo = stockDetail.OrderNo,
+ BatchNo = stockDetail.BatchNo,
+ StockQuantity = splitQuantity,
+ OutboundQuantity = 0,
+ Barcode = newBarcode,
+ Status = (int)StockStatusEmun.鍑哄簱閿佸畾,
+ SupplyCode = stockDetail.SupplyCode,
+ Unit = stockDetail.Unit
+ };
+ await _stockInfoDetailService.Db.Insertable(newStockDetail).ExecuteCommandAsync();
+
+ // 鏇存柊鍘熷簱瀛樻槑缁�
+ stockDetail.StockQuantity -= splitQuantity;
+ await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
+
+ // 鍒涘缓鏂伴攣瀹氫俊鎭�
+ var newLockInfo = new Dt_OutStockLockInfo
+ {
+ OrderNo = lockInfo.OrderNo,
+ OrderDetailId = lockInfo.OrderDetailId,
+ BatchNo = batchNo,
+ MaterielCode = lockInfo.MaterielCode,
+ StockId = lockInfo.StockId,
+ OrderQuantity = splitQuantity,
+ AssignQuantity = splitQuantity,
+ PickedQty = 0,
+ LocationCode = lockInfo.LocationCode,
+ PalletCode = lockInfo.PalletCode,
+ Status = (int)OutLockStockStatusEnum.鍑哄簱涓�,
+ CurrentBarcode = newBarcode,
+ Operator = App.User.UserName,
+ };
+ await _outStockLockInfoService.Db.Insertable(newLockInfo).ExecuteCommandAsync();
+
+ // 鏇存柊鍘熼攣瀹氫俊鎭�
+ lockInfo.AssignQuantity -= splitQuantity;
+ await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
+
+ // 璁板綍鎷嗗寘鍘嗗彶
+ await RecordSplitHistory(lockInfo, stockDetail, splitQuantity, newBarcode);
+
+ return new SplitResultDto { NewBarcode = newBarcode };
+ }
+
+ #endregion
+
+ #region 鍙栨秷鎷嗗寘
+
+ /// <summary>
+ /// 鍙栨秷鎷嗗寘
+ /// </summary>
+ public async Task<WebResponseContent> CancelSplitPackage(string orderNo, string batchNo, string newBarcode)
+ {
+ try
+ {
+ _unitOfWorkManage.BeginTran();
+
+ // 鏌ユ壘鎷嗗寘璁板綍鍜屾柊閿佸畾淇℃伅
+ var splitRecord = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>()
+ .Where(x => x.NewBarcode == newBarcode && x.OrderNo == orderNo && !x.IsReverted)
+ .FirstAsync();
+
+ if (splitRecord == null)
+ return WebResponseContent.Instance.Error("鏈壘鍒版媶鍖呰褰�");
+
+ var newLockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+ .Where(x => x.CurrentBarcode == newBarcode && x.BatchNo == batchNo)
+ .FirstAsync();
+
+ if (newLockInfo == null)
+ return WebResponseContent.Instance.Error("鏈壘鍒版柊閿佸畾淇℃伅");
+
+ // 鎭㈠鍘熷簱瀛�
+ var originalStock = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+ .FirstAsync(x => x.Barcode == splitRecord.OriginalBarcode && x.StockId == splitRecord.StockId);
+
+ originalStock.StockQuantity += splitRecord.SplitQty;
+ await _stockInfoDetailService.Db.Updateable(originalStock).ExecuteCommandAsync();
+
+ // 鎭㈠鍘熼攣瀹氫俊鎭�
+ var originalLockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+ .FirstAsync(x => x.Id == splitRecord.OutStockLockInfoId);
+
+ originalLockInfo.AssignQuantity += splitRecord.SplitQty;
+ await _outStockLockInfoService.Db.Updateable(originalLockInfo).ExecuteCommandAsync();
+
+ // 鍒犻櫎鏂板簱瀛樻槑缁�
+ await _stockInfoDetailService.Db.Deleteable<Dt_StockInfoDetail>()
+ .Where(x => x.Barcode == newBarcode)
+ .ExecuteCommandAsync();
+
+ // 鍒犻櫎鏂伴攣瀹氫俊鎭�
+ await _outStockLockInfoService.Db.Deleteable<Dt_OutStockLockInfo>()
+ .Where(x => x.Id == newLockInfo.Id)
+ .ExecuteCommandAsync();
+
+ // 鏍囪鎷嗗寘璁板綍涓哄凡鎾ら攢
+ splitRecord.IsReverted = true;
+ splitRecord.RevertTime = DateTime.Now;
+ splitRecord.Operator = App.User.UserName;
+ await _splitPackageService.Db.Updateable(splitRecord).ExecuteCommandAsync();
+
+ _unitOfWorkManage.CommitTran();
+
+ return WebResponseContent.Instance.OK("鍙栨秷鎷嗗寘鎴愬姛");
+ }
+ catch (Exception ex)
+ {
+ _unitOfWorkManage.RollbackTran();
+ _logger.LogError($"鍙栨秷鎷嗗寘澶辫触 - OrderNo: {orderNo}, BatchNo: {batchNo}, Barcode: {newBarcode}, Error: {ex.Message}");
+ return WebResponseContent.Instance.Error($"鍙栨秷鎷嗗寘澶辫触锛歿ex.Message}");
+ }
+ }
+
+ #endregion
+
+ #region 鍒嗘壒鍥炲簱
+
+ /// <summary>
+ /// 鍒嗘壒鍥炲簱 - 閲婃斁鏈嫞閫夌殑搴撳瓨
+ /// </summary>
+ public async Task<WebResponseContent> BatchReturnStock(string orderNo, string batchNo)
+ {
+ try
+ {
+ _unitOfWorkManage.BeginTran();
+
+ // 1. 鏌ユ壘鎵规鏈畬鎴愮殑閿佸畾璁板綍
+ var unfinishedLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+ .Where(x => x.OrderNo == orderNo &&
+ x.BatchNo == batchNo &&
+ x.Status == (int)OutLockStockStatusEnum.鍑哄簱涓�)
+ .ToListAsync();
+
+ if (!unfinishedLocks.Any())
+ return WebResponseContent.Instance.Error("璇ユ壒娆℃病鏈夋湭瀹屾垚鐨勯攣瀹氳褰�");
+
+ // 2. 閲婃斁搴撳瓨鍜岄攣瀹氳褰�
+ foreach (var lockInfo in unfinishedLocks)
+ {
+ await ReleaseLockAndStock(lockInfo);
+ }
+
+ // 3. 鏇存柊鎵规鐘舵��
+ await UpdateBatchStatusForReturn(batchNo);
+
+ // 4. 鏇存柊璁㈠崟鏄庣粏鐨勫凡鍒嗛厤鏁伴噺
+ await UpdateOrderDetailAfterReturn(unfinishedLocks);
+
+ _unitOfWorkManage.CommitTran();
+
+ return WebResponseContent.Instance.OK("鍒嗘壒鍥炲簱鎴愬姛");
+ }
+ catch (Exception ex)
+ {
+ _unitOfWorkManage.RollbackTran();
+ _logger.LogError($"鍒嗘壒鍥炲簱澶辫触 - OrderNo: {orderNo}, BatchNo: {batchNo}, Error: {ex.Message}");
+ return WebResponseContent.Instance.Error($"鍒嗘壒鍥炲簱澶辫触锛歿ex.Message}");
+ }
+ }
+
+ private async Task ReleaseLockAndStock(Dt_OutStockLockInfo lockInfo)
+ {
+ // 鎭㈠搴撳瓨鐘舵��
+ var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+ .FirstAsync(x => x.Barcode == lockInfo.CurrentBarcode && x.StockId == lockInfo.StockId);
+
+ if (stockDetail != null)
+ {
+ stockDetail.Status = (int)StockStatusEmun.鍏ュ簱瀹屾垚;
+ await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
+ }
+
+ // 鏇存柊閿佸畾璁板綍鐘舵�佷负鍥炲簱
+ lockInfo.Status = (int)OutLockStockStatusEnum.鍥炲簱涓�;
+ await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
+ }
+
+ private async Task UpdateBatchStatusForReturn(string batchNo)
+ {
+ await _outboundBatchRepository.Db.Updateable<Dt_OutboundBatch>()
+ .SetColumns(x => new Dt_OutboundBatch
+ {
+ BatchStatus = (int)BatchStatusEnum.宸插洖搴�,
+ Operator = App.User.UserName
+ })
+ .Where(x => x.BatchNo == batchNo)
+ .ExecuteCommandAsync();
+ }
+
+ private async Task UpdateOrderDetailAfterReturn(List<Dt_OutStockLockInfo> returnedLocks)
+ {
+ var orderDetailGroups = returnedLocks.GroupBy(x => x.OrderDetailId);
+
+ foreach (var group in orderDetailGroups)
+ {
+ var orderDetailId = group.Key;
+ var returnedQty = group.Sum(x => x.AssignQuantity - x.PickedQty);
+
+ await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
+ .SetColumns(x => x.AllocatedQuantity == x.AllocatedQuantity - returnedQty)
+ .Where(x => x.Id == orderDetailId)
+ .ExecuteCommandAsync();
+ }
+ }
+
+ #endregion
+
+ #region 杈呭姪鏂规硶
+
+ private async Task<string> GenerateNewBarcode()
+ {
+ var seq = await _dailySequenceService.GetNextSequenceAsync();
+ return "WSLOT" + DateTime.Now.ToString("yyyyMMdd") + seq.ToString()?.PadLeft(5, '0');
+ }
+
+ private async Task RecordSplitHistory(Dt_OutStockLockInfo lockInfo, Dt_StockInfoDetail stockDetail,decimal splitQty, string newBarcode)
+ {
+ var splitHistory = new Dt_SplitPackageRecord
+ {
+ OrderNo = lockInfo.OrderNo,
+ OutStockLockInfoId = lockInfo.Id,
+ StockId = stockDetail.StockId,
+ Operator = App.User.UserName,
+ OriginalBarcode = stockDetail.Barcode,
+ NewBarcode = newBarcode,
+ SplitQty = splitQty,
+ SplitTime = DateTime.Now,
+ Status = (int)SplitPackageStatusEnum.宸叉媶鍖�
+ };
+
+ await _splitPackageService.Db.Insertable(splitHistory).ExecuteCommandAsync();
+ }
+
+ private async Task RecordPickingHistory(PickingResult result, string orderNo, string palletCode, string batchNo)
+ {
+ var pickingRecord = new Dt_PickingRecord
+ {
+ OrderNo = orderNo,
+ // BatchNo = batchNo,
+ OrderDetailId = result.FinalLockInfo.OrderDetailId,
+ PalletCode = palletCode,
+ Barcode = result.FinalLockInfo.CurrentBarcode,
+ MaterielCode = result.FinalLockInfo.MaterielCode,
+ PickQuantity = result.ActualPickedQty,
+ PickTime = DateTime.Now,
+ Operator = App.User.UserName,
+ OutStockLockId = result.FinalLockInfo.Id
+ };
+
+ await Db.Insertable(pickingRecord).ExecuteCommandAsync();
+ }
+
+ private async Task UpdateOrderRelatedData(int orderDetailId, decimal pickedQty, string orderNo)
+ {
+ // 鏇存柊璁㈠崟鏄庣粏鐨勫凡鍑哄簱鏁伴噺
+ await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
+ .SetColumns(x => new Dt_OutboundOrderDetail
+ {
+ OverOutQuantity = x.OverOutQuantity + pickedQty,
+ AllocatedQuantity = x.AllocatedQuantity - pickedQty
+ })
+ .Where(x => x.Id == orderDetailId)
+ .ExecuteCommandAsync();
+
+ // 妫�鏌ヨ鍗曠姸鎬�
+ await CheckAndUpdateOrderStatus(orderNo);
+ }
+
+ private async Task CheckAndUpdateOrderStatus(string orderNo)
+ {
+ var orderDetails = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+ .LeftJoin<Dt_OutboundOrder>((o, item) => o.OrderId == item.Id)
+ .Where((o, item) => item.OrderNo == orderNo)
+ .Select((o, item) => o)
+ .ToListAsync();
+
+
+
+ bool allCompleted = orderDetails.All(x => x.OverOutQuantity >= x.NeedOutQuantity);
+
+ if (allCompleted)
+ {
+ await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
+ .SetColumns(x => new Dt_OutboundOrder { OrderStatus = (int)OutOrderStatusEnum.鍑哄簱瀹屾垚 })
+ .Where(x => x.OrderNo == orderNo)
+ .ExecuteCommandAsync();
+ }
+ }
+
+ #endregion
+ }
+
+
+ // 鏀寔绫�
+ public class SplitResultDto
+ {
+ public string NewBarcode { get; set; }
+ }
+}
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundOrderDetailService.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundOrderDetailService.cs"
index 121a74e..450ce11 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundOrderDetailService.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundOrderDetailService.cs"
@@ -227,6 +227,189 @@
return (true, "鍒嗛厤鎴愬姛");
}
+
+ /// <summary>
+ /// 涓哄垎鎵瑰垎閰嶅簱瀛�
+ /// </summary>
+ public async Task<(List<Dt_StockInfo>, List<Dt_OutboundOrderDetail>, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>)>
+ AssignStockForBatch(Dt_OutboundOrderDetail orderDetail, decimal batchQuantity, string batchNo)
+ {
+ if (orderDetail == null)
+ {
+ throw new Exception("鏈壘鍒板嚭搴撳崟鏄庣粏淇℃伅");
+ }
+
+ var outboundOrder = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>()
+ .FirstAsync(x => x.Id == orderDetail.OrderId);
+
+ List<Dt_StockInfo> outStocks = new List<Dt_StockInfo>();
+ List<Dt_OutStockLockInfo> outStockLockInfos = new List<Dt_OutStockLockInfo>();
+ List<Dt_LocationInfo> locationInfos = new List<Dt_LocationInfo>();
+
+ // 鎸夌墿鏂欏拰鎵规鍒嗙粍澶勭悊锛堣繖閲屽彧鏈変竴涓槑缁嗭級
+ var groupDetails = new List<Dt_OutboundOrderDetail> { orderDetail }
+ .GroupBy(x => new { x.MaterielCode, x.BatchNo, x.SupplyCode })
+ .Select(x => new
+ {
+ MaterielCode = x.Key.MaterielCode,
+ BatchNo = x.Key.BatchNo,
+ SupplyCode = x.Key.SupplyCode,
+ Details = x.ToList(),
+ TotalNeedQuantity = batchQuantity // 浣跨敤鍒嗘壒鏁伴噺
+ })
+ .Where(x => x.TotalNeedQuantity > 0)
+ .ToList();
+
+ foreach (var item in groupDetails)
+ {
+ var needQuantity = item.TotalNeedQuantity;
+
+ // 鑾峰彇鍙敤搴撳瓨锛堟寜鍏堣繘鍏堝嚭鎺掑簭锛�
+ List<Dt_StockInfo> stockInfos = _stockService.StockInfoService.GetUseableStocks(item.MaterielCode, item.BatchNo, item.SupplyCode);
+ if (!stockInfos.Any())
+ {
+ throw new Exception($"鐗╂枡[{item.MaterielCode}]鎵规[{item.BatchNo}]鏈壘鍒板彲鍒嗛厤搴撳瓨");
+ }
+
+ // 鍒嗛厤搴撳瓨锛堟寜鍏堣繘鍏堝嚭锛�
+ var (autoAssignStocks, stockAllocations) = _stockService.StockInfoService.GetOutboundStocks (stockInfos, item.MaterielCode, needQuantity, out decimal residueQuantity);
+
+ // 妫�鏌ュ垎閰嶇粨鏋�
+ decimal allocatedQuantity = needQuantity - residueQuantity;
+ if (allocatedQuantity <= 0)
+ {
+ throw new Exception($"鐗╂枡[{item.MaterielCode}]鎵规[{item.BatchNo}]搴撳瓨涓嶈冻锛岄渶瑕亄needQuantity}锛屼絾鏃犳硶鍒嗛厤浠讳綍搴撳瓨");
+ }
+
+ outStocks.AddRange(autoAssignStocks);
+
+ // 鎸夊厛杩涘厛鍑哄師鍒欏垎閰嶉攣瀹氭暟閲忓埌鍚勪釜鏄庣粏
+ var distributionResult = DistributeLockQuantityByFIFO(item.Details, autoAssignStocks, stockAllocations, outStockLockInfos, outboundOrder, batchNo);
+
+ if (!distributionResult.success)
+ {
+ throw new Exception(distributionResult.message);
+ }
+
+ // 鏇存柊鍑哄簱鍗曟槑缁嗙姸鎬�
+ UpdateOrderDetailStatus(item.Details, allocatedQuantity, needQuantity);
+ }
+
+ if (outStocks.Any())
+ {
+ locationInfos.AddRange(_locationInfoService.GetLocationInfos(
+ outStocks.Select(x => x.LocationCode).Distinct().ToList()));
+
+
+ }
+
+ return (outStocks, groupDetails.SelectMany(x => x.Details).ToList(), outStockLockInfos, locationInfos);
+ }
+
+ /// <summary>
+ /// 鎸夊厛杩涘厛鍑哄師鍒欏垎閰嶉攣瀹氭暟閲�
+ /// </summary>
+ private (bool success, string message) DistributeLockQuantityByFIFO(
+ List<Dt_OutboundOrderDetail> details,
+ List<Dt_StockInfo> assignStocks,
+ Dictionary<int, decimal> stockAllocations,
+ List<Dt_OutStockLockInfo> outStockLockInfos,
+ Dt_OutboundOrder outboundOrder,
+ string batchNo)
+ {
+ var sortedDetails = details
+ .Where(d => d.OrderQuantity - d.OverOutQuantity - d.AllocatedQuantity > 0)
+ .OrderBy(x => x.Id)
+ .ToList();
+
+ if (!sortedDetails.Any())
+ return (true, "鏃犻渶鍒嗛厤");
+
+ // 鑾峰彇鎵�鏈夊垎閰嶄簡搴撳瓨鐨勬槑缁嗭紝鎸夊厛杩涘厛鍑烘帓搴�
+ var allocatedStockDetails = assignStocks
+ .SelectMany(x => x.Details)
+ .Where(x => stockAllocations.ContainsKey(x.Id) && stockAllocations[x.Id] > 0)
+ .OrderBy(x => x.CreateDate)
+ .ThenBy(x => x.StockId)
+ .ToList();
+
+ if (!allocatedStockDetails.Any())
+ {
+ return (false, "娌℃湁鍙垎閰嶇殑搴撳瓨鏄庣粏");
+ }
+
+ decimal totalNeedQuantity = sortedDetails.Sum(d =>
+ d.OrderQuantity - d.OverOutQuantity - d.AllocatedQuantity);
+ decimal allocatedQuantity = 0;
+
+ // 涓烘瘡涓簱瀛樻槑缁嗗垱寤哄垎閰嶈褰�
+ foreach (var stockDetail in allocatedStockDetails)
+ {
+ if (!stockAllocations.TryGetValue(stockDetail.Id, out decimal allocatedQuantityForStock))
+ continue;
+
+ if (allocatedQuantityForStock <= 0) continue;
+
+ var stockInfo = assignStocks.First(x => x.Id == stockDetail.StockId);
+ decimal remainingAllocate = allocatedQuantityForStock;
+
+ // 鎸夐『搴忓垎閰嶇粰鍚勪釜鍑哄簱鍗曟槑缁�
+ foreach (var detail in sortedDetails)
+ {
+ if (remainingAllocate <= 0) break;
+
+ // 璁$畻杩欎釜鏄庣粏杩橀渶瑕佸垎閰嶇殑鏁伴噺
+ var detailNeed = detail.OrderQuantity - detail.OverOutQuantity - detail.AllocatedQuantity;
+ if (detailNeed <= 0) continue;
+
+ // 鍒嗛厤鏁伴噺
+ var assignQuantity = Math.Min(remainingAllocate, detailNeed);
+
+ // 楠岃瘉鏉$爜鏄惁瀛樺湪
+ if (string.IsNullOrEmpty(stockDetail.Barcode))
+ {
+ return (false, $"搴撳瓨鏄庣粏ID[{stockDetail.Id}]鐨勬潯鐮佷负绌�");
+ }
+
+
+ // 鍒涘缓鍑哄簱閿佸畾淇℃伅
+ var lockInfo = _outStockLockInfoService.GetOutStockLockInfo(
+ outboundOrder, detail, stockInfo, assignQuantity, stockDetail.Barcode,batchNo);
+ outStockLockInfos.Add(lockInfo);
+
+ // 鏇存柊鏄庣粏鐨勫凡鍒嗛厤鏁伴噺
+ detail.AllocatedQuantity += assignQuantity;
+ remainingAllocate -= assignQuantity;
+ allocatedQuantity += assignQuantity;
+ }
+
+ // 濡傛灉杩樻湁鍓╀綑鍒嗛厤鏁伴噺锛岃褰曡鍛�
+ if (remainingAllocate > 0)
+ {
+ _logger.LogWarning($"搴撳瓨鍒嗛厤鍚庝粛鏈夊墿浣欐暟閲忔湭鍒嗛厤: {remainingAllocate}, 鏉$爜: {stockDetail.Barcode}");
+ }
+ }
+
+ // 楠岃瘉鏄惁鑷冲皯鍒嗛厤浜嗕竴閮ㄥ垎
+ if (allocatedQuantity <= 0)
+ {
+ return (false, "搴撳瓨鍒嗛厤澶辫触锛屾棤娉曞垎閰嶄换浣曟暟閲�");
+ }
+
+ // 璁板綍鍒嗛厤缁撴灉
+ if (allocatedQuantity < totalNeedQuantity)
+ {
+ _logger.LogWarning($"搴撳瓨閮ㄥ垎鍒嗛厤锛岄渶瑕亄totalNeedQuantity}锛屽疄闄呭垎閰峽allocatedQuantity}");
+ }
+ else
+ {
+ _logger.LogInformation($"搴撳瓨瀹屽叏鍒嗛厤锛屽垎閰嶆暟閲弡allocatedQuantity}");
+ }
+
+ return (true, "鍒嗛厤鎴愬姛");
+ }
+
+
private void UpdateOrderDetailStatus(List<Dt_OutboundOrderDetail> details,
decimal allocatedQuantity, decimal needQuantity)
{
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundOrderService.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundOrderService.cs"
index 15ba41a..ab67148 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundOrderService.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundOrderService.cs"
@@ -65,15 +65,17 @@
}
foreach (var item in model.Details)
{
- var issueoStockResult = await _materialUnitService.ConvertIssueToStockAsync(item.MaterielCode, item.BarcodeQty);
+ var issueoStockResult = await _materialUnitService.ConvertFromToStockAsync(item.MaterielCode,item.BarcodeUnit, item.BarcodeQty);
item.Unit = issueoStockResult.Unit;
item.OrderQuantity = issueoStockResult.Quantity;
- var moveissueoStockResult = await _materialUnitService.ConvertIssueToStockAsync(item.MaterielCode, item.BarcodeMoveQty);
+ var moveissueoStockResult = await _materialUnitService.ConvertFromToStockAsync(item.MaterielCode, item.BarcodeUnit, item.BarcodeMoveQty);
item.MoveQty = moveissueoStockResult.Quantity;
}
-
- model.OrderNo = CreateCodeByRule(nameof(RuleCodeEnum.OutboundOrderRule));
+ if (model.OrderType != InOrderTypeEnum.Allocat.ObjToInt() || model.OrderType != InOrderTypeEnum.InternalAllocat.ObjToInt())
+ {
+ model.OrderNo = CreateCodeByRule(nameof(RuleCodeEnum.OutboundOrderRule));
+ }
Db.InsertNav(model).Include(x => x.Details).ExecuteCommand();
return WebResponseContent.Instance.OK();
@@ -125,10 +127,10 @@
BarcodeQty = item.OrderQuantity,
BarcodeUnit = item.Unit,
};
- var issueoStockResult = await _materialUnitService.ConvertIssueToStockAsync(item.MaterielCode, item.BarcodeQty);
+ var issueoStockResult = await _materialUnitService.ConvertFromToStockAsync(item.MaterielCode,item.BarcodeUnit, item.BarcodeQty);
item.Unit = issueoStockResult.Unit;
item.OrderQuantity = issueoStockResult.Quantity;
- var moveissueoStockResult = await _materialUnitService.ConvertIssueToStockAsync(item.MaterielCode, item.BarcodeMoveQty);
+ var moveissueoStockResult = await _materialUnitService.ConvertFromToStockAsync(item.MaterielCode, item.BarcodeUnit, item.BarcodeMoveQty);
item.MoveQty = moveissueoStockResult.Quantity;
outboundOrderDetails.Add(outboundOrderDetail);
@@ -146,10 +148,10 @@
outboundOrderDetail.BarcodeMoveQty = item.MoveQty;
outboundOrderDetail.BarcodeQty = item.OrderQuantity;
outboundOrderDetail.BarcodeUnit = item.Unit;
- var issueoStockResult = await _materialUnitService.ConvertIssueToStockAsync(item.MaterielCode, item.BarcodeQty);
+ var issueoStockResult = await _materialUnitService.ConvertFromToStockAsync(item.MaterielCode, item.BarcodeUnit, item.BarcodeQty);
outboundOrderDetail.Unit = issueoStockResult.Unit;
outboundOrderDetail.OrderQuantity = issueoStockResult.Quantity;
- var moveissueoStockResult = await _materialUnitService.ConvertIssueToStockAsync(item.MaterielCode, item.BarcodeMoveQty);
+ var moveissueoStockResult = await _materialUnitService.ConvertFromToStockAsync(item.MaterielCode, item.BarcodeUnit, item.BarcodeMoveQty);
outboundOrderDetail.MoveQty = moveissueoStockResult.Quantity;
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs"
index f289724..a0497ba 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs"
@@ -2168,6 +2168,8 @@
FactoryArea = originalLock.FactoryArea,
lineNo = originalLock.lineNo,
WarehouseCode = originalLock.WarehouseCode,
+ BarcodeQty=originalLock.BarcodeQty,
+ BarcodeUnit=originalLock.BarcodeUnit,
};
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/WIDESEA_OutboundService.csproj" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/WIDESEA_OutboundService.csproj"
index ebf59e5..a9892c1 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/WIDESEA_OutboundService.csproj"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/WIDESEA_OutboundService.csproj"
@@ -7,6 +7,7 @@
</PropertyGroup>
<ItemGroup>
+ <ProjectReference Include="..\WIDESEA_BasicService\WIDESEA_BasicService.csproj" />
<ProjectReference Include="..\WIDESEA_IAllocateService\WIDESEA_IAllocateService.csproj" />
<ProjectReference Include="..\WIDESEA_IBasicService\WIDESEA_IBasicService.csproj" />
<ProjectReference Include="..\WIDESEA_IOutboundService\WIDESEA_IOutboundService.csproj" />
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs"
index 3021a88..d8690fd 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs"
@@ -51,6 +51,7 @@
using WIDESEA_IStockService;
using WIDESEA_ITaskInfoService;
using WIDESEA_Model.Models;
+using WIDESEA_Model.Models.Outbound;
namespace WIDESEA_TaskInfoService
{
@@ -65,6 +66,7 @@
private readonly IInboundOrderService _inboundOrderService;
private readonly IInboundOrderDetailService _inboundOrderDetailService;
+ private readonly IRepository<Dt_OutboundBatch> _OutboundBatchRepository;
private readonly IOutboundOrderService _outboundOrderService;
private readonly IOutboundOrderDetailService _outboundOrderDetailService;
private readonly IOutStockLockInfoService _outStockLockInfoService;
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_Outbound.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_Outbound.cs"
index d479cef..6cbf577 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_Outbound.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_Outbound.cs"
@@ -6,6 +6,7 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using WIDESEA_BasicService;
using WIDESEA_Common.CommonEnum;
using WIDESEA_Common.LocationEnum;
using WIDESEA_Common.OrderEnum;
@@ -17,6 +18,8 @@
using WIDESEA_DTO.Basic;
using WIDESEA_DTO.Stock;
using WIDESEA_Model.Models;
+using WIDESEA_Model.Models.Basic;
+using WIDESEA_Model.Models.Outbound;
namespace WIDESEA_TaskInfoService
{
@@ -596,5 +599,197 @@
}
+
+ #region 鍒嗘壒鍒嗛厤搴撳瓨
+
+ /// <summary>
+ /// 鍒嗘壒鍒嗛厤搴撳瓨
+ /// </summary>
+ public async Task<WebResponseContent> BatchAllocateStock(string orderNo, int orderDetailId, decimal batchQuantity, string outStation)
+ {
+ try
+ {
+ List<Dt_Task> tasks = new List<Dt_Task>();
+ List<Dt_StockInfo> stockInfos = new List<Dt_StockInfo>();
+ List<Dt_OutboundOrderDetail> outboundOrderDetails = new List<Dt_OutboundOrderDetail>();
+ List<Dt_OutStockLockInfo> outStockLockInfos = new List<Dt_OutStockLockInfo>();
+ List<Dt_LocationInfo> locationInfos = new List<Dt_LocationInfo>();
+
+ (List<Dt_Task>, List<Dt_StockInfo>?, List<Dt_OutboundOrderDetail>?, List<Dt_OutStockLockInfo>?, List<Dt_LocationInfo>?) result = await BatchAllocateStockDataHandle(orderNo, orderDetailId, batchQuantity, outStation);
+
+ if (result.Item2 != null && result.Item2.Count > 0)
+ {
+ stockInfos.AddRange(result.Item2);
+ }
+ if (result.Item3 != null && result.Item3.Count > 0)
+ {
+ outboundOrderDetails.AddRange(result.Item3);
+ }
+ if (result.Item4 != null && result.Item4.Count > 0)
+ {
+ outStockLockInfos.AddRange(result.Item4);
+ }
+ if (result.Item5 != null && result.Item5.Count > 0)
+ {
+ locationInfos.AddRange(result.Item5);
+ }
+ if (result.Item1 != null && result.Item1.Count > 0)
+ {
+ tasks.AddRange(result.Item1);
+ }
+
+ WebResponseContent content = await GenerateOutboundTaskDataUpdateAsync(tasks, stockInfos, outboundOrderDetails, outStockLockInfos, locationInfos);
+ return content;
+ }
+ catch (Exception ex)
+ {
+ _unitOfWorkManage.RollbackTran();
+ _logger.LogError($"鍒嗘壒鍒嗛厤搴撳瓨澶辫触 - OrderNo: {orderNo}, OrderDetailId: {orderDetailId}, Quantity: {batchQuantity}, Error: {ex.Message}");
+ return WebResponseContent.Instance.Error($"鍒嗘壒鍒嗛厤澶辫触锛歿ex.Message}");
+ }
+ }
+
+ /// <summary>
+ /// 鍒嗘壒鍒嗛厤搴撳瓨鏁版嵁澶勭悊
+ /// </summary>
+ public async Task<(List<Dt_Task>, List<Dt_StockInfo>?, List<Dt_OutboundOrderDetail>?, List<Dt_OutStockLockInfo>?, List<Dt_LocationInfo>?)>
+ BatchAllocateStockDataHandle(string orderNo, int orderDetailId, decimal batchQuantity, string outStation)
+ {
+ List<Dt_Task> tasks = new List<Dt_Task>();
+
+ // 鑾峰彇璁㈠崟鏄庣粏
+ var outboundOrderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+ .FirstAsync(x => x.Id == orderDetailId );
+
+ if (outboundOrderDetail == null)
+ {
+ throw new Exception("鏈壘鍒板嚭搴撳崟鏄庣粏淇℃伅");
+ }
+
+ // 楠岃瘉璁㈠崟鏄庣粏鐘舵��
+ if (outboundOrderDetail.OrderDetailStatus > OrderDetailStatusEnum.New.ObjToInt() &&
+ outboundOrderDetail.OrderDetailStatus != OrderDetailStatusEnum.AssignOverPartial.ObjToInt())
+ {
+ throw new Exception("鎵�閫夊嚭搴撳崟鏄庣粏瀛樺湪鍑哄簱涓垨宸插畬鎴�");
+ }
+
+ // 楠岃瘉鍒嗛厤鏁伴噺
+ decimal allocatedQty = outboundOrderDetail.AllocatedQuantity;
+ decimal overOutQty = outboundOrderDetail.OverOutQuantity;
+ decimal needOutQty = outboundOrderDetail.NeedOutQuantity;
+ decimal availableQty = needOutQty - allocatedQty - overOutQty;
+
+ if (availableQty <= 0)
+ throw new Exception("鏃犲彲鍒嗛厤鏁伴噺");
+
+ if (batchQuantity > availableQty)
+ throw new Exception($"鍒嗛厤鏁伴噺涓嶈兘瓒呰繃鍙垎閰嶆暟閲弡availableQty}");
+
+ List<Dt_StockInfo>? stockInfos = null;
+ List<Dt_OutboundOrderDetail>? orderDetails = null;
+ List<Dt_OutStockLockInfo>? outStockLockInfos = null;
+ List<Dt_LocationInfo>? locationInfos = null;
+
+ // 鐢熸垚鎵规鍙�
+ string batchNo = await GenerateBatchNo();
+
+ // 鍒嗛厤搴撳瓨
+ (List<Dt_StockInfo>, List<Dt_OutboundOrderDetail>, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) allocateResult =
+ await _outboundOrderDetailService.AssignStockForBatch(outboundOrderDetail, batchQuantity, batchNo);
+
+ if (allocateResult.Item1 != null && allocateResult.Item1.Count > 0)
+ {
+ // 鍒涘缓鍒嗘壒璁板綍
+ await CreateBatchRecord(orderNo, orderDetailId, batchQuantity, batchNo);
+
+ Dt_OutboundOrder outboundOrder = await _outboundOrderService.Repository.QueryFirstAsync(x => x.Id == outboundOrderDetail.OrderId);
+ TaskTypeEnum typeEnum = outboundOrder.OrderType switch
+ {
+ (int)OutOrderTypeEnum.Issue => TaskTypeEnum.Outbound,
+ (int)OutOrderTypeEnum.Allocate => TaskTypeEnum.OutAllocate,
+ (int)OutOrderTypeEnum.Quality => TaskTypeEnum.OutQuality,
+ _ => TaskTypeEnum.Outbound
+ };
+
+ tasks = GetTasks(allocateResult.Item1, typeEnum, outStation);
+ tasks.ForEach(x =>
+ {
+ x.OrderNo = outboundOrder.OrderNo;
+ });
+
+ allocateResult.Item2.ForEach(x =>
+ {
+ x.OrderDetailStatus = OrderDetailStatusEnum.Outbound.ObjToInt();
+ });
+
+ allocateResult.Item3.ForEach(x =>
+ {
+ x.Status = OutLockStockStatusEnum.鍑哄簱涓�.ObjToInt();
+ });
+
+ stockInfos = allocateResult.Item1;
+ orderDetails = allocateResult.Item2;
+ outStockLockInfos = allocateResult.Item3;
+ locationInfos = allocateResult.Item4;
+ }
+ else
+ {
+ throw new Exception("鏃犲簱瀛�");
+ }
+
+ return (tasks, stockInfos, orderDetails, outStockLockInfos, locationInfos);
+ }
+
+
+
+
+
+ /// <summary>
+ /// 鏇存柊璁㈠崟鏄庣粏鐘舵��
+ /// </summary>
+ private void UpdateOrderDetailStatus(List<Dt_OutboundOrderDetail> details, decimal allocatedQuantity, decimal needQuantity)
+ {
+ foreach (var detail in details)
+ {
+ // 鏍规嵁鍒嗛厤鎯呭喌鏇存柊鐘舵��
+ if (allocatedQuantity >= needQuantity)
+ {
+ detail.OrderDetailStatus = OrderDetailStatusEnum.Outbound.ObjToInt();
+ }
+ else
+ {
+ detail.OrderDetailStatus = OrderDetailStatusEnum.AssignOverPartial.ObjToInt();
+ }
+ }
+ }
+
+
+
+ private async Task<string> GenerateBatchNo()
+ {
+ var batchNo = UniqueValueGenerator.Generate();
+
+ return $"Out{batchNo} ";
+ }
+
+ private async Task<Dt_OutboundBatch> CreateBatchRecord(string orderNo, int orderDetailId, decimal batchQuantity, string batchNo)
+ {
+ var batchRecord = new Dt_OutboundBatch
+ {
+ BatchNo = batchNo,
+ OrderNo = orderNo,
+ OrderDetailId = orderDetailId,
+ BatchQuantity = batchQuantity,
+ BatchStatus = (int)BatchStatusEnum.鍒嗛厤涓�,
+ Operator = App.User.UserName
+ };
+
+ await _OutboundBatchRepository.Db.Insertable(batchRecord).ExecuteCommandAsync();
+ return batchRecord;
+ }
+
+ #endregion
+
+
}
}
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_TaskInfoService/WIDESEA_TaskInfoService.csproj" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_TaskInfoService/WIDESEA_TaskInfoService.csproj"
index 51b297d..c586408 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_TaskInfoService/WIDESEA_TaskInfoService.csproj"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_TaskInfoService/WIDESEA_TaskInfoService.csproj"
@@ -7,6 +7,7 @@
</PropertyGroup>
<ItemGroup>
+ <ProjectReference Include="..\WIDESEA_BasicService\WIDESEA_BasicService.csproj" />
<ProjectReference Include="..\WIDESEA_IAllocateService\WIDESEA_IAllocateService.csproj" />
<ProjectReference Include="..\WIDESEA_IBasicService\WIDESEA_IBasicService.csproj" />
<ProjectReference Include="..\WIDESEA_IInboundService\WIDESEA_IInboundService.csproj" />
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Inbound/InboundOrderController.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Inbound/InboundOrderController.cs"
index 4b98acf..d17e070 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Inbound/InboundOrderController.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Inbound/InboundOrderController.cs"
@@ -51,14 +51,14 @@
[HttpPost, Route("Test"), AllowAnonymous, MethodParamsValidate]
public async Task<WebResponseContent> Test()
{
-
- Service.Db.Deleteable<Dt_InboundOrder>().Where(x=>x.UpperOrderNo== "12020251100040").ExecuteCommand();
- _inboundService.InboundOrderDetailService.Db.Deleteable<Dt_InboundOrderDetail>()
- .Where(p => SqlFunc.Subqueryable<Dt_InboundOrder>().Where(s => s.Id == p.OrderId && s.UpperOrderNo == "12020251100040").Any()).ExecuteCommand();
- // var purchaseToStockResult = await _materialUnitService.ConvertPurchaseToStockAsync("101001-00002", 10);
+ // Service.Db.Deleteable<Dt_InboundOrder>().Where(x=>x.UpperOrderNo== "12020251100040").ExecuteCommand();
+ //_inboundService.InboundOrderDetailService.Db.Deleteable<Dt_InboundOrderDetail>()
+ // .Where(p => SqlFunc.Subqueryable<Dt_InboundOrder>().Where(s => s.Id == p.OrderId && s.UpperOrderNo == "12020251100040").Any()).ExecuteCommand();
- // var pdddurchaseToStockResult = await _materialUnitService.ConvertPurchaseToStockAsync("100513-00210", 10);
+ var purchaseToStockResult = await _materialUnitService.ConvertPurchaseToStockAsync("100513-00303", 1);
+
+ var pdddurchaseToStockResult = await _materialUnitService.ConvertFromToStockAsync("100513-00303", "W013", 1);
//var sddd = _locationInfoService.AssignLocation();
//var code = sddd.LocationCode;
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Jobs/InventoryLockJob.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Jobs/InventoryLockJob.cs"
new file mode 100644
index 0000000..248f47e
--- /dev/null
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Jobs/InventoryLockJob.cs"
@@ -0,0 +1,22 @@
+锘縰sing Quartz;
+using SqlSugar;
+
+namespace WIDESEA_WMSServer.Jobs
+{
+ [DisallowConcurrentExecution]
+ public class InventoryLockJob : IJob
+ {
+ private readonly ILogger<ErpJob> _logger;
+ private readonly ISqlSugarClient _db;
+ public InventoryLockJob(ILogger<ErpJob> logger, ISqlSugarClient db )
+ {
+ _logger = logger;
+ _db = db;
+
+ }
+ public Task Execute(IJobExecutionContext context)
+ {
+ return Task.CompletedTask;
+ }
+ }
+}
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Program.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Program.cs"
index ef722e9..c284b28 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Program.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Program.cs"
@@ -161,6 +161,15 @@
.ForJob(jobKey)
.WithIdentity("ErpJob-trigger")
.WithCronSchedule("0 0 10,14,20 * * ?"));
+
+ var inventoryLockJobKey = new JobKey("InventoryLockJob");
+ q.AddJob<InventoryLockJob>(opts => opts.WithIdentity(inventoryLockJobKey));
+
+ q.AddTrigger(opts => opts
+ .ForJob(inventoryLockJobKey)
+ .WithIdentity("InventoryLockJob-trigger")
+ .WithCronSchedule("0 0/10 * * * ?")); // 每10分钟执行一次
+
});
--
Gitblit v1.9.3