This commit is contained in:
18942506660
2024-11-07 09:46:58 +08:00
56 changed files with 3239 additions and 74 deletions

View File

@@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text;
using WMS.Web.Core;
using WMS.Web.Domain.Values;
namespace WMS.Web.Domain.Entitys
{
/// <summary>
/// 成品仓即时库存
/// </summary>
[Serializable]
[Table("t_wms_product_inventory")]
public class ProductInventory : EntityBase
{
public ProductInventory() { }
/// <summary>
/// 主键 订单编号
/// </summary>
[Column("Id")]
public override int Id { get; set; }
/// <summary>
/// 物料编码
/// </summary>
[Column("MaterialNumber")]
public string MaterialNumber { get; set; }
/// <summary>
/// 单据类型
/// </summary>
[Column("Type")]
public ProductInventoryType Type { get; set; } = ProductInventoryType.JinDie;
/// <summary>
/// 组织编码
///</summary>
[Column("OrgCode")]
public string OrgCode { get; set; }
/// <summary>
/// 仓库
///</summary>
[Column("StockCode")]
public string StockCode { get; set; }
/// <summary>
/// 客户/店铺
///</summary>
[Column("Customer")]
public string Customer { get; set; }
/// <summary>
/// 批号
///</summary>
[Column("Batch")]
public string Batch { get; set; }
/// <summary>
/// 可用量
///</summary>
[Column("Qty")]
public decimal Qty { get; set; } = 0;
/// <summary>
/// 库存量
///</summary>
[Column("BeforeQty")]
public decimal BeforeQty { get; set; } = 0;
}
}

View File

@@ -0,0 +1,18 @@

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using WMS.Web.Core.Internal.Results;
namespace WMS.Web.Domain.IService
{
public interface IProductInventoryService
{
Task<Result> LingXing();
Task<Result> Erp();
Task<Result> JuShuiTan();
Task<Result> Refresh();
}
}

View File

@@ -5,6 +5,7 @@ using WMS.Web.Core.Dto.Erp;
using WMS.Web.Core.Dto.Erp.Customer;
using WMS.Web.Core.Dto.Erp.Org;
using WMS.Web.Core.Dto.Erp.Supplier;
using WMS.Web.Core.Dto.SingleData;
namespace WMS.Web.Domain.IService.Public
{
@@ -173,5 +174,12 @@ namespace WMS.Web.Domain.IService.Public
/// <param name="code"></param>
/// <returns></returns>
string GetSubStockName(List<Erp_SubStockDto> erpStocks, string code);
/// <summary>
/// 成品即时库存仓库
/// </summary>
/// <param name="list"></param>
/// <param name="code"></param>
/// <returns></returns>
string GetProductInventoryStockName(List<UcStockHeadOfficeResponse> list, string code);
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using WMS.Web.Core.Dto.Erp;
using WMS.Web.Core.Internal.Results;
namespace WMS.Web.Domain.IService.Public
{
public interface IErpInventoryService
{
Task<Result<List<ErpInventoryDto>>> GetInventory(List<string> stockCodes);
}
}

View File

@@ -178,7 +178,7 @@ namespace WMS.Web.Domain.IService.Public
/// 及时库存
/// </summary>
/// <returns></returns>
Task<ResultList<ErpInventoryDto>> BillQueryForInventory(List<(string materialNumber, string orgCode, string stockCode, int subStockId)> request);
Task<ResultList<ErpInventoryDto>> BillQueryForInventory(List<(string orgCode, string stockCode)> request);
//同步数据(保存提交审核)
Task<Result<string>> Save<T>(T dto, string formId);
//提交

View File

@@ -13,6 +13,7 @@ namespace WMS.Web.Domain.IService.Public
Task<T> GetAsync<T>(string url, Dictionary<string, string> dicHeaders, int timeoutSecond = 180);
Task<T> PostAsync<T>(string url, string requestBody, int timeoutSecond = 180);
Task<T> PostAsync<T>(string url, string requestBody, Dictionary<string, string> dicHeaders, int timeoutSecond = 180);
Task<T> PostAsync<T>(string url, HttpContent content, Dictionary<string, string> dicHeaders, int timeoutSecond = 180);
Task<T> ExecuteAsync<T>(string url, HttpMethod method, string requestBody, Dictionary<string, string> dicHeaders, int timeoutSecond = 180);
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using WMS.Web.Core.Dto.JuShuiTan;
using WMS.Web.Core.Internal.Results;
namespace WMS.Web.Domain.IService.Public
{
public interface IJuShuiTanService
{
Task GetTest();
Task<Result<List<JuShuiTanStockResponse>>> GetStock();
Task<Result<List<JuShuiTanInventoryResponse>>> GetInventory(List<int> StockId);
}
}

View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using WMS.Web.Core.Dto.LingXing;
using WMS.Web.Core.Internal.Results;
namespace WMS.Web.Domain.IService.Public
{
/// <summary>
/// 领星服务接口
/// </summary>
public interface ILingXingService
{
/// <summary>
/// 获取领星所有仓库
/// </summary>
/// <returns></returns>
public Task<Result<List<LingXingStockResponse>>> GetStock();
/// <summary>
/// 获取领星所有仓库
/// </summary>
/// <returns></returns>
public Task<Result<List<LingXingSellerResponse>>> GetSeller();
/// <summary>
/// 获取即时库存
/// </summary>
/// <returns></returns>
public Task<Result<List<LingXingInventoryResponse>>> GetInventory(List<int> ids);
}
}

View File

@@ -71,6 +71,11 @@ namespace WMS.Web.Domain.Infrastructure
/// </summary>
/// <returns></returns>
Task<List<UcStockResponse>> GetUcStockAsync(string systemCode,string name, int companyId);
/// <summary>
/// 获取仓库总公司
/// </summary>
/// <returns></returns>
Task<List<UcStockHeadOfficeResponse>> GetUcStockByHeadOfficeAsync(string name, int companyId);
/// <summary>
/// 获取事务 用来处理即时库存

View File

@@ -0,0 +1,42 @@
using AutoMapper;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using WMS.Web.Core.Dto.Inventory;
using WMS.Web.Core.Dto.ProductInventory;
using WMS.Web.Domain.Entitys;
using WMS.Web.Domain.IService.Public;
using WMS.Web.Domain.Values;
namespace WMS.Web.Domain.Infrastructure
{
/// <summary>
/// 成品仓即时库存
/// </summary>
public interface IProductInventoryRepositories
{
/// <summary>
/// 添加
/// </summary>
/// <param name="entitys"></param>
/// <param name="isTransaction"></param>
/// <returns></returns>
Task<bool> AddRange(List<ProductInventory> entitys, bool isTransaction = true);
/// <summary>
/// 删除
/// </summary>
/// <param name="isTransaction"></param>
/// <returns></returns>
Task<bool> Delete(ProductInventoryType type, bool isTransaction = true);
Task<bool> EditEntityList(List<ProductInventory> entitys, bool isTransaction = true);
Task<List<ProductInventory>> GetEntityList(ProductInventoryType type);
/// <summary>
/// 列表-分页
/// </summary>
/// <param name="dto"></param>
/// <param name="companyId"></param>
/// <returns></returns>
Task<(List<ProductInventoryQueryResponse> list, int total, List<decimal> details)> GetListAsync(ProductInventoryQueryRequest dto, int companyId = 0);
}
}

View File

@@ -0,0 +1,17 @@
using AutoMapper;
using System;
using System.Collections.Generic;
using System.Text;
using WMS.Web.Core.Dto.Erp;
using WMS.Web.Domain.Entitys;
namespace WMS.Web.Domain.Mappers
{
public class ProductInventoryMapper : Profile
{
public ProductInventoryMapper()
{
CreateMap<ProductInventory, ProductInventory>().ReverseMap();
}
}
}

View File

@@ -28,6 +28,10 @@ namespace WMS.Web.Domain.Options
/// erp-Id
/// </summary>
public string ErpId { get; set; }
/// <summary>
/// 账号Id
/// </summary>
public string ZhangTaoId { get; set; }
public readonly string cache_materail_all_key = "erp_materials_list_all";
public readonly string cache_materail_key = "erp_materials_list";
public readonly string cache_org_key = "erp_org_list";

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace WMS.Web.Domain.Options
{
public class JuShuiTanOptions
{
public string Url { get; set; }
public string AppKey { get; set; }
public string AppSecret { get; set; }
public string AccessToken { get; set; }
}
}

View File

@@ -103,6 +103,11 @@ namespace WMS.Web.Domain.Options
/// 监测金蝶删单
/// </summary>
public string JobStartErpDelete { get; set; }
/// <summary>
/// 成品仓库即时库存
/// </summary>
public string JobStartProductInventory { get; set; }
/// <summary>
/// 是否启用集群:键
/// </summary>

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace WMS.Web.Domain.Options
{
/// <summary>
/// 领星配置
/// </summary>
public class lingXingOptions
{
public string Url { get; set; }
public string AppId { get; set; }
public string AppSecret { get; set; }
}
}

View File

@@ -0,0 +1,48 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Quartz;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using WMS.Web.Domain.IService;
namespace WMS.Web.Domain.QuartzJob
{
//成品即时库存
public class InventoryQuartzJob : IJob
{
private readonly ILogger<InventoryQuartzJob> _logger;
private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly IProductInventoryService _productInventoryService;
public InventoryQuartzJob(ILogger<InventoryQuartzJob> logger,
IServiceScopeFactory serviceScopeFactory, IProductInventoryService productInventoryService)
{
this._logger = logger;
_serviceScopeFactory = serviceScopeFactory;
_productInventoryService = productInventoryService;
}
/// <summary>
/// 执行方法
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public async Task Execute(IJobExecutionContext context)
{
try
{
if (DateTime.Now.Hour < 8 || DateTime.Now.Hour > 20) return;
_logger.LogInformation($"同步成品即时库存->开始定时任务");
var result = await _productInventoryService.Refresh();
}
catch (Exception ex)
{
_logger.LogInformation($"同步成品即时库存:定时任务执行失败->{ex.Message}");
}
}
}
}

View File

@@ -0,0 +1,342 @@
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using NPOI.POIFS.FileSystem;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using WMS.Web.Core.Dto.Erp;
using WMS.Web.Core.Dto.Login;
using WMS.Web.Core.Internal.Results;
using WMS.Web.Domain.Entitys;
using WMS.Web.Domain.Infrastructure;
using WMS.Web.Domain.IService;
using WMS.Web.Domain.IService.Public;
using WMS.Web.Domain.Values;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
namespace WMS.Web.Domain.Services
{
public class ProductInventoryService : IProductInventoryService
{
private readonly IErpService _erpService;
private readonly ISingleDataService _singleDataService;
private readonly IErpBasicDataExtendService _erpBasicDataExtendService;
private readonly IProductInventoryRepositories _repositories;
private readonly ILingXingService _lingXingService;
private readonly IBasicsRepositories _basicsRepositories;
public readonly IBasicsRepositories _transactionRepositories;
public readonly IJuShuiTanService _juShuiTanService;
public readonly IErpInventoryService _erpInventoryService;
private readonly ILogger<ProductInventoryService> _logger;
public ProductInventoryService(IErpService erpService,
ISingleDataService singleDataService,
IErpBasicDataExtendService erpBasicDataExtendService,
IProductInventoryRepositories repositories,
ILingXingService lingXingService,
IBasicsRepositories basicsRepositories,
IBasicsRepositories transactionRepositories,
IJuShuiTanService juShuiTanService,
IErpInventoryService erpInventoryService,
ILogger<ProductInventoryService> logger)
{
_erpService = erpService;
_singleDataService = singleDataService;
_erpBasicDataExtendService = erpBasicDataExtendService;
_repositories = repositories;
_lingXingService = lingXingService;
_basicsRepositories = basicsRepositories;
_transactionRepositories = transactionRepositories;
_juShuiTanService = juShuiTanService;
_erpInventoryService = erpInventoryService;
_logger = logger;
}
/// <summary>
/// 金蝶
/// </summary>
/// <returns></returns>
public async Task<Result> Erp()
{
//获取单点配置
var r = await _basicsRepositories.GetUcStockByHeadOfficeAsync("", 1);
//r = r.Where(w => w.Code.Equals("CK001")).ToList();
var codes = r.Where(w =>
w.ManagementSystem == 1 || w.ManagementSystem == 4).Select(s => (s.Code, s.ErpOrgCode)).ToList();
if (codes.Count() <= 0) return Result.ReSuccess();
//var str = string.Join(",", codes.Select(s => s.Code).ToList());
var res = await _erpInventoryService.GetInventory(codes.Select(s => s.Code).ToList());
_logger.LogInformation($"拉取金蝶数据结果:{res.IsSuccess} {res.Message}");
if (!res.IsSuccess) return res;
//过滤掉不符合要求的组织和仓库组合
List<ErpInventoryDto> listOld = new List<ErpInventoryDto>();
foreach (var item in codes)
{
var zList = res.Data.Where(w => w.OrgCode == item.ErpOrgCode && w.StockCode == item.Code).ToList();
listOld.AddRange(zList);
}
List<ProductInventory> inventoryList = new List<ProductInventory>();
foreach (var item in listOld)
{
string subStock = "";
if (!string.IsNullOrEmpty(item.Erp_SubStockName))
subStock = item.Erp_SubStockName.Split(':')[1].Replace(";", "");
var entity = new ProductInventory()
{
Type = ProductInventoryType.JinDie,
MaterialNumber = item.MaterialNumber,
Customer = subStock,
OrgCode = item.OrgCode,
StockCode = item.StockCode,
Qty = item.Qty,
Batch = item.Batch,
BeforeQty = item.BeforeQty
};
inventoryList.Add(entity);
}
IDbContextTransaction _transaction = _transactionRepositories.GetTransaction();
Result res_Rollback = Result.ReSuccess();
bool isSuccess = true;
//修改库存
//先删除之前的再添加
if (res_Rollback.IsSuccess)
{
isSuccess = await _repositories.Delete(ProductInventoryType.JinDie, false);
if (isSuccess == false) res_Rollback = Result.ReFailure(ResultCodes.DateWriteError);
}
if (res_Rollback.IsSuccess)
{
isSuccess = await _repositories.AddRange(inventoryList, false);
if (isSuccess == false) res_Rollback = Result.ReFailure(ResultCodes.DateWriteError);
}
//提交事务
isSuccess = _transactionRepositories.CommitTransaction(res_Rollback.IsSuccess ? false : true, _transaction);
if (!res_Rollback.IsSuccess) return res_Rollback;
if (!isSuccess)
return Result.ReFailure(ResultCodes.DateWriteError);
return Result.ReSuccess();
}
/// <summary>
/// 聚水潭
/// </summary>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<Result> JuShuiTan()
{
//获取单点配置
var r = await _basicsRepositories.GetUcStockByHeadOfficeAsync("", 1);
var listNames = r.Where(w =>
w.ManagementSystem == 2 && !string.IsNullOrEmpty(w.WarehouseCodeOfJushuitan))
.Select(s => s.WarehouseCodeOfJushuitan)
.ToList();
if (listNames.Count() <= 0) return Result.ReSuccess();
//获取原数据
var yList = await _repositories.GetEntityList(ProductInventoryType.JushuiTan);
//获取领星仓库
var resStock = await _juShuiTanService.GetStock();
if (!resStock.IsSuccess) return resStock;
var ids = resStock.Data.Where(w => listNames.Contains(w.Name)).Select(s => s.Id).ToList();
//获取领星库存
var resInventory = await _juShuiTanService.GetInventory(ids);
_logger.LogInformation($"拉取聚水潭数据结果:{resInventory.IsSuccess} {resInventory.Message}");
if (!resInventory.IsSuccess) return resStock;
//物料
var materials_result = await _erpService.BillQueryForMaterial();
List<ErpMaterialDto> materials = new List<ErpMaterialDto>();
if (materials_result.IsSuccess)
materials = materials_result.Data.ToList();
List<ProductInventory> inventoryList = new List<ProductInventory>();
List<ProductInventory> update_List = new List<ProductInventory>();
foreach (var item in resInventory.Data)
{
//如果物料不匹配 过滤
var m = materials.FirstOrDefault(f => f.Specifications.Equals(item.sku_id));
if (m == null) continue;
//找仓库
var l_stock = resStock.Data.FirstOrDefault(f => f.Id == item.wms_co_id);
if (l_stock == null) continue;
var stock = r.FirstOrDefault(f => f.WarehouseCodeOfJushuitan.Equals(l_stock.Name));
if (stock == null) continue;
var entity = new ProductInventory()
{
Type = ProductInventoryType.JushuiTan,
MaterialNumber = m.MaterialNumber,
Customer = "",
OrgCode = stock.ErpOrgCode,
StockCode = stock.Code,
Qty = item.ky_qty,
BeforeQty = item.qty ?? 0
};
var old_Entity = yList.FirstOrDefault(f => f.MaterialNumber.Equals(entity.MaterialNumber) &&
f.OrgCode.Equals(entity.OrgCode) && f.StockCode.Equals(entity.StockCode));
if (old_Entity != null)
{
old_Entity.Qty = entity.Qty;
old_Entity.BeforeQty = entity.BeforeQty;
update_List.Add(old_Entity);
}
else
inventoryList.Add(entity);
}
IDbContextTransaction _transaction = _transactionRepositories.GetTransaction();
Result res_Rollback = Result.ReSuccess();
bool isSuccess = true;
//修改库存
//先删除之前的再添加
if (res_Rollback.IsSuccess)
{
isSuccess = await _repositories.EditEntityList(update_List, false);
if (isSuccess == false) res_Rollback = Result.ReFailure(ResultCodes.DateWriteError);
}
if (res_Rollback.IsSuccess)
{
isSuccess = await _repositories.AddRange(inventoryList, false);
if (isSuccess == false) res_Rollback = Result.ReFailure(ResultCodes.DateWriteError);
}
//提交事务
isSuccess = _transactionRepositories.CommitTransaction(res_Rollback.IsSuccess ? false : true, _transaction);
if (!res_Rollback.IsSuccess) return res_Rollback;
if (!isSuccess)
return Result.ReFailure(ResultCodes.DateWriteError);
return Result.ReSuccess();
}
/// <summary>
/// 领星
/// </summary>
/// <returns></returns>
public async Task<Result> LingXing()
{
//获取单点配置
var r = await _basicsRepositories.GetUcStockByHeadOfficeAsync("", 1);
var listNames = r.Where(w =>
w.ManagementSystem == 3 && !string.IsNullOrEmpty(w.WarehouseCodeOfLingxing))
.Select(s => s.WarehouseCodeOfLingxing)
.ToList();
if (listNames.Count() <= 0) return Result.ReSuccess();
//获取领星仓库
var resStock = await _lingXingService.GetStock();
_logger.LogInformation($"拉取领星仓库:{JsonConvert.SerializeObject(resStock)}");
if (!resStock.IsSuccess) return resStock;
var ids = resStock.Data.Where(w => listNames.Contains(w.Name)).Select(s => s.Id).ToList();
string strIds = string.Join(",", ids);
//获取领星库存
var resInventory = await _lingXingService.GetInventory(ids);
_logger.LogInformation($"拉取领星数据结果:{resInventory.IsSuccess} {resInventory.Message}");
if (!resInventory.IsSuccess) return resStock;
foreach (var i in ids)
{
_logger.LogInformation($"拉取领星数据{i} 数据总数:{resInventory.Data.Where(w => w.StockId == i).Count()}");
}
//物料
var materials_result = await _erpService.BillQueryForMaterial();
List<ErpMaterialDto> materials = new List<ErpMaterialDto>();
if (materials_result.IsSuccess)
materials = materials_result.Data.ToList();
//获取店铺
var sellerList = await _lingXingService.GetSeller();
//合并
var group = resInventory.Data.GroupBy(g => (g.StockId, g.SKU, g.SellerId));
//int cc = group.Count();
List<ProductInventory> inventoryList = new List<ProductInventory>();
foreach (var item in group)
{
//如果物料不匹配 过滤
var m = materials.FirstOrDefault(f => f.Specifications.Equals(item.Key.SKU));
if (m == null) continue;
//找仓库
var l_stock = resStock.Data.FirstOrDefault(f => f.Id == item.Key.StockId);
if (l_stock == null) continue;
var stock = r.FirstOrDefault(f => f.WarehouseCodeOfLingxing.Equals(l_stock.Name));
if (stock == null) continue;
//店铺
var seller = sellerList.Data.FirstOrDefault(f => f.Id == item.Key.SellerId);
var pList = resInventory.Data.Where(w => w.SKU == item.Key.SKU
&& w.StockId == item.Key.StockId && w.SellerId == item.Key.SellerId).ToList();
var entity = new ProductInventory()
{
Type = ProductInventoryType.LingXing,
MaterialNumber = m.MaterialNumber,
Customer = seller != null ? seller.Name : "",
OrgCode = stock.ErpOrgCode,
StockCode = stock.Code,
Qty = pList.Sum(s => s.Product_Valid_Num),
BeforeQty = pList.Sum(s => s.Product_Total)
};
inventoryList.Add(entity);
}
IDbContextTransaction _transaction = _transactionRepositories.GetTransaction();
Result res_Rollback = Result.ReSuccess();
bool isSuccess = true;
//修改库存
//先删除之前的再添加
if (res_Rollback.IsSuccess)
{
isSuccess = await _repositories.Delete(ProductInventoryType.LingXing, false);
if (isSuccess == false) res_Rollback = Result.ReFailure(ResultCodes.DateWriteError);
}
if (res_Rollback.IsSuccess)
{
isSuccess = await _repositories.AddRange(inventoryList, false);
if (isSuccess == false) res_Rollback = Result.ReFailure(ResultCodes.DateWriteError);
}
//提交事务
isSuccess = _transactionRepositories.CommitTransaction(res_Rollback.IsSuccess ? false : true, _transaction);
if (!res_Rollback.IsSuccess) return res_Rollback;
if (!isSuccess)
return Result.ReFailure(ResultCodes.DateWriteError);
return Result.ReSuccess();
}
public async Task<Result> Refresh()
{
_logger.LogInformation($"同步成品仓库存->开始 {DateTime.Now}");
try
{
var res = await this.Erp();
_logger.LogInformation($"同步成品仓库存(物料) {res.IsSuccess} {res.Message}");
if (!res.IsSuccess) return res;
res = await this.JuShuiTan();
_logger.LogInformation($"同步成品仓库存(聚水潭) {res.IsSuccess} {res.Message}");
if (!res.IsSuccess) return res;
res = await this.LingXing();
_logger.LogInformation($"同步成品仓库存(领星) {res.IsSuccess} {res.Message}");
if (!res.IsSuccess) return res;
}
catch (Exception ex)
{
_logger.LogError($"同步成品仓库异常:{ex.ToString()}");
}
_logger.LogInformation($"同步成品仓库存->结束 {DateTime.Now}");
return Result.ReSuccess();
}
}
}

View File

@@ -7,6 +7,7 @@ using WMS.Web.Core.Dto.Erp;
using WMS.Web.Core.Dto.Erp.Customer;
using WMS.Web.Core.Dto.Erp.Org;
using WMS.Web.Core.Dto.Erp.Supplier;
using WMS.Web.Core.Dto.SingleData;
using WMS.Web.Domain.Infrastructure;
using WMS.Web.Domain.IService.Public;
@@ -407,6 +408,18 @@ namespace WMS.Web.Domain.Services.Public
var stock = erpStocks.Where(x => x.Code == code).FirstOrDefault();
return stock == null ? "" : stock.Name;
}
/// <summary>
/// 成品即时库存仓库
/// </summary>
/// <param name="list"></param>
/// <param name="code"></param>
/// <returns></returns>
public string GetProductInventoryStockName(List<UcStockHeadOfficeResponse> list, string code)
{
if (list == null || list.Count == 0)
return "";
var stock = list.Where(x => x.Code == code).FirstOrDefault();
return stock == null ? "" : stock.Name;
}
}
}

View File

@@ -0,0 +1,320 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MySqlX.XDevAPI.Common;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using WMS.Web.Core.Dto.Erp;
using WMS.Web.Core.Dto.JuShuiTan;
using WMS.Web.Core.Internal.Results;
using WMS.Web.Domain.IService.Public;
using WMS.Web.Domain.Options;
using WMS.Web.Domain.Values;
namespace WMS.Web.Domain.Services.Public
{
public class ErpInventoryService : IErpInventoryService
{
private ErpOptions _erpOptions;
private readonly ILogger<ErpInventoryService> _logger;
public ErpInventoryService(IOptions<ErpOptions> erpOptions, ILogger<ErpInventoryService> logger)
{
_erpOptions = erpOptions?.Value;
_logger = logger;
}
private bool Login(HttpClientEx httpClient)
{
string baseUrl = _erpOptions.EndpointAddress.Replace("/ERPGW.asmx", ""); //"http://192.168.1.1/k3cloud";//服务器地址
httpClient.Url = string.Format("{0}/Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateUser.common.kdsvc", baseUrl);
List<object> Parameters = new List<object>();
Parameters.Add(_erpOptions.ZhangTaoId);//帐套Id
Parameters.Add(_erpOptions.UserName);//用户名
Parameters.Add(_erpOptions.Password);//密码
Parameters.Add(2052);//多语言:中文
httpClient.Content = JsonConvert.SerializeObject(Parameters);
string response = httpClient.AsyncRequest();
var iResult = JObject.Parse(response)["LoginResultType"].Value<int>();
return iResult == 1 ? true : false;
}
public async Task<Result<List<ErpInventoryDto>>> GetInventory(List<string> stockCodes)
{
List<ErpInventoryDto> list = new List<ErpInventoryDto>();
HttpClientEx httpClient = new HttpClientEx();
var isSuccess = Login(httpClient);
string baseUrl = _erpOptions.EndpointAddress.Replace("/ERPGW.asmx", "");
httpClient.Url = string.Format("{0}/Kingdee.K3.SCM.WebApi.ServicesStub.InventoryQueryService.GetInventoryData.common.kdsvc", baseUrl);
int count = stockCodes.Count() / 10;
count = count + 1;
for (int ic = 1; ic <= count; ic++)
{
var codes = stockCodes.Skip((ic-1) * 10).Take(10).ToList();
if (codes.Count() <= 0)
{
return Result<List<ErpInventoryDto>>.ReSuccess(list.Where(w => w.Qty > 0 || w.BeforeQty > 0).ToList());
}
string code = string.Join(",", codes);
//foreach (var code in stockCodes)
//{
List<object> Parameters = new List<object>();
var model = new InventoryParamModel();
model.fstocknumbers = code;
//model.fmaterialnumbers = "G01-11-572474";
model.isshowauxprop = true;
model.isshowstockloc = true;
model.pageindex = 1;
model.pagerows = 5000;
Parameters.Add(model);
httpClient.Content = JsonConvert.SerializeObject(Parameters);
//_logger.LogInformation($"1.开始进行连接 {code}");
string content = httpClient.AsyncRequest();
//_logger.LogInformation($"金蝶返回数据{content}");
JObject resData = JObject.Parse(content);
if (resData["success"].ToString().ToLower() != "true")
return Result<List<ErpInventoryDto>>.ReFailure(ResultCodes.Erp_Inventory_Error);
string json = resData["data"].ToString();
var datas = JsonConvert.DeserializeObject<List<ErpInventoryDto>>(json);
if (datas != null && datas.Count() > 0)
list.AddRange(datas);
int num = Convert.ToInt32(resData["rowcount"]) / 5000;
for (int i = 1; i <= num; i++)
{
model.pageindex++;
httpClient.Content = JsonConvert.SerializeObject(Parameters);
content = httpClient.AsyncRequest();
//_logger.LogInformation($"金蝶返回数据{content}");
resData = JObject.Parse(content);
if (resData["success"].ToString().ToLower() != "true")
return Result<List<ErpInventoryDto>>.ReFailure(ResultCodes.Erp_Inventory_Error);
json = resData["data"].ToString();
datas = JsonConvert.DeserializeObject<List<ErpInventoryDto>>(json);
if (datas != null && datas.Count() > 0)
list.AddRange(datas);
}
}
var blist = list.Where(w => w.Qty > 0 || w.BeforeQty > 0).ToList();
return Result<List<ErpInventoryDto>>.ReSuccess(blist);
}
}
class HttpClientEx
{
/// <summary>
/// Seivice URL
/// </summary>
public string Url { get; set; }
/// <summary>
/// 内容
/// </summary>
public string Content { get; set; }
/// <summary>
/// Cookie保证登录后所有访问持有一个Cookie
/// </summary>
static CookieContainer Cookie = new CookieContainer();
/// <summary>
/// HTTP访问
/// </summary>
public string AsyncRequest()
{
HttpWebRequest httpRequest = HttpWebRequest.Create(Url) as HttpWebRequest;
httpRequest.Method = "POST";
httpRequest.ContentType = "application/json";
httpRequest.CookieContainer = Cookie;
httpRequest.Timeout = 1000 * 60 * 10;//10min
using (Stream reqStream = httpRequest.GetRequestStream())
{
JObject jObj = new JObject();
jObj.Add("format", 1);
jObj.Add("useragent", "ApiClient");
jObj.Add("rid", Guid.NewGuid().ToString().GetHashCode().ToString());
jObj.Add("parameters", Content);
jObj.Add("timestamp", DateTime.Now);
jObj.Add("v", "1.0");
string sContent = jObj.ToString();
var bytes = UnicodeEncoding.UTF8.GetBytes(sContent);
reqStream.Write(bytes, 0, bytes.Length);
reqStream.Flush();
}
using (var repStream = httpRequest.GetResponse().GetResponseStream())
{
using (var reader = new StreamReader(repStream))
{
return ValidateResult(reader.ReadToEnd());
}
}
}
private static string ValidateResult(string responseText)
{
if (responseText.StartsWith("response_error:"))
{
return responseText.TrimStart("response_error:".ToCharArray());
}
return responseText;
}
}
class InventoryParamModel
{
/// <summary>
/// 库存组织编码,多个使用英文逗号【,】分隔
/// </summary>
public string fstockorgnumbers { get; set; }
/// <summary>
/// 物料编码,多个使用英文逗号【,】分隔
/// </summary>
public string fmaterialnumbers { get; set; }
/// <summary>
/// 仓库编码,多个使用英文逗号【,】分隔
/// </summary>
public string fstocknumbers { get; set; }
/// <summary>
/// 批号编码,多个使用英文逗号【,】分隔
/// </summary>
public string flotnumbers { get; set; }
/// <summary>
/// 是否查询仓位
/// </summary>
public bool isshowstockloc { get; set; }
/// <summary>
/// 是否查询辅助属性
/// </summary>
public bool isshowauxprop { get; set; }
/// <summary>
/// 当前页码
/// </summary>
public int pageindex { get; set; }
/// <summary>
/// 每页显示行数
/// </summary>
public int pagerows { get; set; }
}
}

View File

@@ -160,7 +160,7 @@ namespace WMS.Web.Domain.Services.Public
/// <param name="billNo">模糊搜索</param>
/// <param name="sourceBillNos">单据编号集合精确查找</param>
/// <returns></returns>
public async Task<ResultList<ErpInStockResultDto>> BillQueryForPurchaseInStock(List<string> sourceBillNos = null, DateTime? beginTime = null,bool isCheck=true)
public async Task<ResultList<ErpInStockResultDto>> BillQueryForPurchaseInStock(List<string> sourceBillNos = null, DateTime? beginTime = null, bool isCheck = true)
{
string result_json = "";
try
@@ -194,7 +194,7 @@ namespace WMS.Web.Domain.Services.Public
//5.仓库wms系统的仓库值---现在这个没有加,因为还单点没有和金蝶同步
//param.FilterString = " FDocumentStatus='C' and (FBillTypeID='83d822ca3e374b4ab01e5dd46a0062bd' or FBillTypeID='6d01d059713d42a28bb976c90a121142') and FMRPCloseStatus='A'";
param.FilterString = " FMRPCloseStatus='A'";
if(isCheck) param.FilterString += " and FDocumentStatus='C'";
if (isCheck) param.FilterString += " and FDocumentStatus='C'";
for (int i = 0; i < stocks.Count(); i++)
{
if (i == 0)
@@ -2637,7 +2637,7 @@ namespace WMS.Web.Domain.Services.Public
}
}
public async Task<ResultList<ErpInventoryDto>> BillQueryForInventory(List<(string materialNumber, string orgCode, string stockCode, int subStockId)> request)
public async Task<ResultList<ErpInventoryDto>> BillQueryForInventory(List<(string orgCode, string stockCode)> request)
{
try
{
@@ -2650,51 +2650,76 @@ namespace WMS.Web.Domain.Services.Public
//3.获取金蝶采购订单:拼接参数和条件
var query = new ErpBillQueryDto(token_result.Data);
var param = new ErpBillQueryParamDto(FormIdParam.STK_Inventory.ToString());
param.FieldKeys = "FBASEQTY,FMATERIALID.FNumber,FSTOCKORGID.FNumber,FSTOCKID.FNumber,FSTOCKLOCID";
param.Limit = 100;
//param.FilterString = $"FSTOCKORGID.FNumber='{request[0].orgCode}' and FSTOCKID.FNumber='{request[0].stockCode}'";
//param.FilterString = $"";
// ORICO_AD,FF100004 ORICO_GD,FF100005 ORICO_HD,FF100007 ORICO_JD,FF100008
param.FieldKeys = "FMATERIALID.FNumber,FSTOCKORGID.FNumber,FSTOCKID.FNumber,FLot.FNumber,FBASEQTY,FSTOREURNOM,FSTOREURNUM,FSTOCKLOCID.FF100004.FName,FSTOCKLOCID.FF100005.FName,FSTOCKLOCID.FF100007.FName,FSTOCKLOCID.FF100008.FName";
param.Limit = 10000;
//param.FilterString = $" FMATERIALID.FNumber='G01-11-572474' and FSTOCKID.FNumber='AD' and FBASEQTY>0";
//param.FilterString = $" FBASEQTY>0";
for (int i = 0; i < request.Count(); i++)
{
if (i == 0)
{
param.FilterString = $"(FMATERIALID.FNumber='{request[0].materialNumber}' and FSTOCKORGID.FNumber='{request[0].orgCode}' and FSTOCKID.FNumber='{request[0].stockCode}' and FSTOCKLOCID={request[0].subStockId})";
param.FilterString += $" and ((FSTOCKORGID.FNumber='{request[0].orgCode}' and FSTOCKID.FNumber='{request[0].stockCode}' )";
if (request.Count() == 1) param.FilterString += ")";
}
else
{
param.FilterString += $" or (FMATERIALID.FNumber='{request[i].materialNumber}' and FSTOCKORGID.FNumber='{request[i].orgCode}' and FSTOCKID.FNumber='{request[i].stockCode}' and FSTOCKLOCID={request[i].subStockId})";
param.FilterString += $" or (FSTOCKORGID.FNumber='{request[i].orgCode}' and FSTOCKID.FNumber='{request[i].stockCode}' ))";
}
}
query.Data = JsonConvert.SerializeObject(param);
var json = JsonConvert.SerializeObject(query);
//4.请求查询接口
var result_json = await _client.ExecuteBillQueryAsync(json);
var result = JsonConvert.DeserializeObject<List<List<string>>>(result_json);
bool isHave = true;
var erp_list = new List<ErpInventoryDto>();
foreach (var item in result)
int skip = 0;
while (isHave)
{
//4.1.页码页码按照金蝶的要求从0开始
param.StartRow = (Convert.ToInt32(skip) * param.Limit);
var lis = erp_list.FirstOrDefault(f => f.MaterialNumber.Equals(item[1])
&& f.OrgCode.Equals(item[2])
&& f.StockCode.Equals(item[3]));
query.Data = JsonConvert.SerializeObject(param);
var json = JsonConvert.SerializeObject(query);
if (lis == null)
//4.请求查询接口
var result_json = await _client.ExecuteBillQueryAsync(json);
var result = JsonConvert.DeserializeObject<List<List<string>>>(result_json);
//4.4.判断数据是否全部拉取完成:并停止循环的条件
if (result == null || result.Count == 0)
isHave = false;
foreach (var item in result)
{
lis = new ErpInventoryDto();
lis.Qty = Convert.ToDecimal(item[0]);
lis.MaterialNumber = item[1];
lis.OrgCode = item[2];
lis.StockCode = item[3];
lis.Erp_SubStockId = Convert.ToInt32(item[4]);
erp_list.Add(lis);
}
else
lis.Qty = lis.Qty + Convert.ToDecimal(item[0]);
}
string name = GetName(item[7], item[8], item[9], item[10]);
var lis = erp_list.FirstOrDefault(f => f.MaterialNumber.Equals(item[0])
&& f.OrgCode.Equals(item[1])
&& f.StockCode.Equals(item[2]) && f.Erp_SubStockName.Equals(name));
return ResultList<ErpInventoryDto>.ReSuccess(erp_list);
if (lis == null)
{
lis = new ErpInventoryDto();
lis.MaterialNumber = item[0];
lis.OrgCode = item[1];
lis.StockCode = item[2];
lis.Batch = item[3];
//查询库存单位数量FQTYFMaterialid.FSTOREURNOM,FMaterialid.FSTOREURNUM
//查出结果后用(FBASEQTY*FSTOREURNOM/FSTOREURNUM)计算得到库存单位数量。
lis.BeforeQty = Convert.ToDecimal(item[4]) * Convert.ToDecimal(item[5]) / Convert.ToDecimal(item[6]);
//lis.Qty= Convert.ToDecimal(item[10]) * Convert.ToDecimal(item[5]) / Convert.ToDecimal(item[6]);
lis.Erp_SubStockName = name;
erp_list.Add(lis);
}
else
{
lis.BeforeQty = lis.BeforeQty + (Convert.ToDecimal(item[4]) * Convert.ToDecimal(item[5]) / Convert.ToDecimal(item[6]));
//lis.Qty = lis.Qty + Convert.ToDecimal(item[5]);
}
}
//4.6页面的叠加
skip++;
}
var list = erp_list.Where(w => w.BeforeQty > 0 || w.Qty > 0).ToList();
return ResultList<ErpInventoryDto>.ReSuccess(list);
}
catch (Exception ex)
{
@@ -2702,9 +2727,16 @@ namespace WMS.Web.Domain.Services.Public
return ResultList<ErpInventoryDto>.ReFailure(ResultCodes.Erp_Inventory_Error);
}
}
public string GetName(string name1,string name2,string name3,string name4)
{
if (!string.IsNullOrEmpty(name1)) return name1;
if (!string.IsNullOrEmpty(name2)) return name2;
if (!string.IsNullOrEmpty(name3)) return name3;
if (!string.IsNullOrEmpty(name4)) return name4;
return "";
}
#endregion
}

View File

@@ -1,4 +1,5 @@
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
@@ -48,8 +49,9 @@ namespace WMS.Web.Domain.Services.Public
var responseContent = await response.Content.ReadAsStringAsync(); //2.当前使用这里是为了迎合错误信息观看
if (response.IsSuccessStatusCode)
{
var t = JsonSerializer.Deserialize<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
//var t = JsonSerializer.Deserialize<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
//var t = await JsonSerializer.DeserializeAsync<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });//3.配合1的ReadAsStream使用
var t = JsonConvert.DeserializeObject<T>(responseContent);
return t;
}
@@ -80,8 +82,9 @@ namespace WMS.Web.Domain.Services.Public
var responseContent = await response.Content.ReadAsStringAsync(); //2.当前使用这里是为了迎合错误信息观看
if (response.IsSuccessStatusCode)
{
var t = JsonSerializer.Deserialize<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
//var t = JsonSerializer.Deserialize<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
//var t = await JsonSerializer.DeserializeAsync<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });//3.配合1的ReadAsStream使用
var t = JsonConvert.DeserializeObject<T>(responseContent);
return t;
}
@@ -111,7 +114,8 @@ namespace WMS.Web.Domain.Services.Public
var responseContent = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
var t = JsonSerializer.Deserialize<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
//var t = JsonSerializer.Deserialize<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
var t = JsonConvert.DeserializeObject<T>(responseContent);
return t;
}
@@ -135,7 +139,8 @@ namespace WMS.Web.Domain.Services.Public
var responseContent = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
var t = JsonSerializer.Deserialize<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
//var t = JsonSerializer.Deserialize<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
var t = JsonConvert.DeserializeObject<T>(responseContent);
if (t == null)
_logger.LogInformation($"获取单点数据为空---{responseContent}");
return t;
@@ -163,8 +168,8 @@ namespace WMS.Web.Domain.Services.Public
var responseContent = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
var t = JsonSerializer.Deserialize<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
//var t = JsonSerializer.Deserialize<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
var t = JsonConvert.DeserializeObject<T>(responseContent);
return t;
}
@@ -226,5 +231,20 @@ namespace WMS.Web.Domain.Services.Public
if (timeoutSecond != null) httpClient.Timeout = TimeSpan.FromSeconds(timeoutSecond.Value);
return httpClient;
}
public async Task<T> PostAsync<T>(string url, HttpContent content, Dictionary<string, string> dicHeaders, int timeoutSecond = 180)
{
var client = BuildHttpClient(dicHeaders, timeoutSecond);
var response = await client.PostAsync(url, content);
var responseContent = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
var t = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(responseContent);
return t;
}
_logger.LogError($"HttpGet:{url} Error:{responseContent}");
throw new WebHttpException(response.StatusCode.ToString(), responseContent);
}
}
}

View File

@@ -0,0 +1,245 @@
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WMS.Web.Core.Dto.Erp;
using WMS.Web.Core.Dto.JuShuiTan;
using WMS.Web.Core.Help;
using WMS.Web.Core.Internal.Results;
using WMS.Web.Domain.IService.Public;
using WMS.Web.Domain.Options;
using WMS.Web.Domain.Values;
namespace WMS.Web.Domain.Services.Public
{
public class JuShuiTanService : IJuShuiTanService
{
private readonly IHttpClientService _httpClientService;
private readonly ILogger<JuShuiTanService> _logger;
private readonly IMemoryCache _memoryCache;
private int hours = 10;//过期时间 默认10小时
private readonly JuShuiTanOptions _option;
public JuShuiTanService(IHttpClientService httpClientService, ILogger<JuShuiTanService> logger,
IMemoryCache memoryCache, IOptions<JuShuiTanOptions> option)
{
this._memoryCache = memoryCache;
this._httpClientService = httpClientService;
this._logger = logger;
_option = option?.Value;
}
public async Task GetTest()
{
//await GetStock();
var list = new List<int>();
list.Add(10923342);
await GetInventory(list);
}
public async Task<Result<List<JuShuiTanStockResponse>>> GetStock()
{
var stock_list = _memoryCache.Get<List<JuShuiTanStockResponse>>("jushuitan_stock");
if (stock_list != null && stock_list.Count > 0)
return Result<List<JuShuiTanStockResponse>>.ReSuccess(stock_list);
List<JuShuiTanStockResponse> list = new List<JuShuiTanStockResponse>();
JuShuiTanStockRequst request = new JuShuiTanStockRequst();
var resContent = PostUrl("/open/wms/partner/query", JsonConvert.SerializeObject(request));
JObject resData = JObject.Parse(resContent);
if (Convert.ToInt32(resData["code"]) != 0)
{
_logger.LogInformation($"聚水潭获取仓库失败:{resData["msg"].ToString()}");
return Result<List<JuShuiTanStockResponse>>.ReFailure(ResultCodes.JuShuiTanDataError);
}
string json = resData["data"]["datas"].ToString();
var datas = JsonConvert.DeserializeObject<List<JuShuiTanStockResponse>>(json);
list.AddRange(datas);
int count = Convert.ToInt32(resData["data"]["page_count"]);
for (int i = 1; i < count; i++)
{
request.page_index++;
resContent = PostUrl("/open/wms/partner/query", JsonConvert.SerializeObject(request));
resData = JObject.Parse(resContent);
if (Convert.ToInt32(resData["code"]) != 0)
{
_logger.LogInformation($"聚水潭获取仓库失败:{resData["msg"].ToString()}");
return Result<List<JuShuiTanStockResponse>>.ReFailure(ResultCodes.JuShuiTanDataError);
}
json = resData["data"]["datas"].ToString();
datas = JsonConvert.DeserializeObject<List<JuShuiTanStockResponse>>(json);
list.AddRange(datas);
}
//设置缓存
_memoryCache.Set("jushuitan_stock", list, new MemoryCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromMinutes(DateTimeUtil.GetTotalMinutesTimeSpan())));
return Result<List<JuShuiTanStockResponse>>.ReSuccess(list);
}
public async Task<Result<List<JuShuiTanInventoryResponse>>> GetInventory(List<int> StockId)
{
List<JuShuiTanInventoryResponse> list = new List<JuShuiTanInventoryResponse>();
foreach (var id in StockId)
{
Thread.Sleep(1000);//不能太频繁请求
JuShuiTanInventoryRequst request = new JuShuiTanInventoryRequst();
request.wms_co_id = id;//10923342;
request.page_size = 100;
request.modified_begin = DateTime.Now.AddDays(-6).AddHours(-23).ToString("yyyy-MM-dd HH:mm:ss");
request.modified_end = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
var resContent = PostUrl("/open/inventory/query", JsonConvert.SerializeObject(request));
JObject resData = JObject.Parse(resContent);
if (Convert.ToInt32(resData["code"]) != 0)
{
_logger.LogInformation($"聚水潭获取即时库存失败:{resData["msg"].ToString()}");
return Result<List<JuShuiTanInventoryResponse>>.ReFailure(ResultCodes.JuShuiTanDataError);
}
string json = resData["data"]["inventorys"].ToString();
var datas = JsonConvert.DeserializeObject<List<JuShuiTanInventoryResponse>>(json);
datas.ForEach(f => f.wms_co_id = id);
list.AddRange(datas);
int count = Convert.ToInt32(resData["data"]["page_count"]);
for (int i = 1; i < count; i++)
{
Thread.Sleep(1000);//不能太频繁请求
request.page_index++;
resContent = PostUrl("/open/inventory/query", JsonConvert.SerializeObject(request));
resData = JObject.Parse(resContent);
if (Convert.ToInt32(resData["code"]) != 0)
{
_logger.LogInformation($"聚水潭获取即时库存失败:{resData["msg"].ToString()}");
return Result<List<JuShuiTanInventoryResponse>>.ReFailure(ResultCodes.JuShuiTanDataError);
}
json = resData["data"]["inventorys"].ToString();
datas = JsonConvert.DeserializeObject<List<JuShuiTanInventoryResponse>>(json);
datas.ForEach(f => f.wms_co_id = id);
list.AddRange(datas);
}
}
//主仓实际库存-订单占有数+虚拟库存+采购在途(业务设置)+进货仓(业务设置)+销退仓库存(业务设置)
foreach (var item in list)
{
item.qty = item.qty == null ? 0 : item.qty;
item.ky_qty = (item.qty ?? 0) - (item.order_lock ?? 0) + (item.virtual_qty ?? 0)
+ (item.purchase_qty ?? 0) + (item.in_qty ?? 0) + (item.return_qty ?? 0);
}
//这里不能过滤掉都是0的 因为要修改
//var resList = list.Where(w => w.qty > 0 || w.ky_qty > 0).ToList();
return Result<List<JuShuiTanInventoryResponse>>.ReSuccess(list);
}
/// <summary>
/// 调用接口
/// </summary>
private string PostUrl(string urlStr, string biz)
{
Hashtable ht = new Hashtable();
System.DateTime starttime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));
string time = Math.Floor((System.DateTime.Now - starttime).TotalSeconds).ToString();
string app_key = _option.AppKey;// "17231841286c45f99eb9acf445404349";
string app_secret = _option.AppSecret;// "5ce9641ae6db4abb8b96eea7df6a81e9";
string access_token = _option.AccessToken;// "4605358c37374780a8a4395e6cdb1c3f";
//string biz = "{\"modified_begin\":\"2022-06-10 00:00:00\",\"modified_end\":\"2022-06-12 00:00:00\",\"page_index\":1,\"page_size\":30}";
ht.Add("access_token", access_token);
ht.Add("app_key", app_key);
ht.Add("biz", biz);
ht.Add("charset", "utf-8");
ht.Add("timestamp", time);
ht.Add("version", "2");
string sign = getSign(app_secret, ht);
ht.Add("sign", sign);
string posturl = _option.Url + urlStr;
Encoding datacode = Encoding.UTF8;
string paramData = GetParamData(ht);
return PostWebRequest(posturl, paramData, datacode);
}
string getSign(string signKey, Hashtable param)
{
ArrayList keys = new ArrayList(param.Keys);
keys.Sort(); //按字母顺序进行排序
string resultStr = "";
foreach (string key in keys)
{
if (key != null && key != "" && key != "sign")
{
resultStr = resultStr + key + param[key];
}
}
resultStr = signKey + resultStr;
MD5 md5 = MD5.Create();
byte[] rstRes = md5.ComputeHash(Encoding.UTF8.GetBytes(resultStr));
string hex = BitConverter.ToString(rstRes, 0).Replace("-", string.Empty).ToLower();
return hex;
}
private string PostWebRequest(string postUrl, string paramData, Encoding dataEncode)
{
string ret = string.Empty;
try
{
byte[] byteArray = dataEncode.GetBytes(paramData);
//转化
HttpWebRequest webReq = (HttpWebRequest)WebRequest.Create(new Uri(postUrl));
webReq.Method = "POST";
webReq.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";
webReq.ContentLength = byteArray.Length;
Stream newStream = webReq.GetRequestStream();
newStream.Write(byteArray, 0, byteArray.Length);
//写入参数
newStream.Close();
HttpWebResponse response = (HttpWebResponse)webReq.GetResponse();
StreamReader sr = new StreamReader(response.GetResponseStream(), dataEncode);
ret = sr.ReadToEnd();
sr.Close();
response.Close();
newStream.Close();
}
catch (Exception ex)
{
}
return ret;
}
private string GetParamData(Hashtable ht)
{
string str = "";
foreach (DictionaryEntry items in ht)
{
str += items.Key.ToString() + "=" + System.Web.HttpUtility.UrlEncode(items.Value.ToString(), System.Text.Encoding.UTF8) + "&";
}
return str.Substring(0, str.Length - 1);
}
}
}

View File

@@ -0,0 +1,392 @@
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using WMS.Web.Core.Dto;
using WMS.Web.Domain.IService.Public;
using WMS.Web.Domain.Options;
using WMS.Web.Core.Internal.Results;
using WMS.Web.Core.Dto.LingXing;
using System.Json;
using System.Net.Http;
using NPOI.POIFS.Crypt.Dsig;
using NPOI.SS.Formula.Functions;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
using System.Reflection;
using WMS.Web.Core.Help;
using static System.Net.WebRequestMethods;
using WMS.Web.Domain.Values;
using WMS.Web.Core.Dto.JuShuiTan;
using System.Threading;
namespace WMS.Web.Domain.Services.Public
{
/// <summary>
/// 领星服务接口
/// </summary>
public class LingXingService : ILingXingService
{
private readonly IHttpClientService _httpClientService;
private readonly ILogger<LingXingService> _logger;
private readonly IMemoryCache _memoryCache;
private int hours = 10;//过期时间 默认10小时
private readonly lingXingOptions _option;
public LingXingService(IHttpClientService httpClientService, ILogger<LingXingService> logger,
IMemoryCache memoryCache, IOptions<lingXingOptions> option)
{
this._memoryCache = memoryCache;
this._httpClientService = httpClientService;
this._logger = logger;
_option = option?.Value;
}
public async Task<Result<string>> Login()
{
string endStr = "/api/auth-server/oauth/access-token";
var formData = new MultipartFormDataContent();
formData.Add(new StringContent(_option.AppId), "appId");
formData.Add(new StringContent(_option.AppSecret), "appSecret");
var res = await _httpClientService.PostAsync<dynamic>(_option.Url + endStr, formData, null);
if (res.code != "200")
{
_logger.LogInformation($"领星获取授权失败:{res.msg}");
return Result<string>.ReFailure(ResultCodes.LingXingTokenError);
}
string token = res.data.access_token;
return Result<string>.ReSuccess(token);
}
/// <summary>
/// 获取所有仓库
/// </summary>
/// <returns></returns>
public async Task<Result<List<LingXingStockResponse>>> GetStock()
{
var stock_list = _memoryCache.Get<List<LingXingStockResponse>>("lingxing_stock");
if (stock_list != null && stock_list.Count > 0)
return Result<List<LingXingStockResponse>>.ReSuccess(stock_list);
List<LingXingStockResponse> list = new List<LingXingStockResponse>();
//默认获取本地仓库 如果需要海外仓 另外需传参数type
var request = new LingXingRequest();
var resUrl = await GetStr<LingXingRequest>("/erp/sc/data/local_inventory/warehouse", request);
if (!resUrl.IsSuccess) return Result<List<LingXingStockResponse>>.ReFailure(ResultCodes.LingXingUrlError);
var res = await _httpClientService.PostAsync<LingXingResponse>(resUrl.Data, JsonConvert.SerializeObject(request), null);
if (res.Code != 0) return Result<List<LingXingStockResponse>>.ReFailure(ResultCodes.LingXingDataError);
list.AddRange(JsonConvert.DeserializeObject<List<LingXingStockResponse>>(res.Data.ToString()));
//海外仓
request = new LingXingRequest();
request.type = 3;
resUrl = await GetStr<LingXingRequest>("/erp/sc/data/local_inventory/warehouse", request);
if (!resUrl.IsSuccess) return Result<List<LingXingStockResponse>>.ReFailure(ResultCodes.LingXingUrlError);
res = await _httpClientService.PostAsync<LingXingResponse>(resUrl.Data, JsonConvert.SerializeObject(request), null);
if (res.Code != 0) return Result<List<LingXingStockResponse>>.ReFailure(ResultCodes.LingXingDataError);
list.AddRange(JsonConvert.DeserializeObject<List<LingXingStockResponse>>(res.Data.ToString()));
//设置缓存
_memoryCache.Set("lingxing_stock", list, new MemoryCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromMinutes(DateTimeUtil.GetTotalMinutesTimeSpan())));
return Result<List<LingXingStockResponse>>.ReSuccess(list);
}
/// <summary>
/// 获取所有店铺
/// </summary>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<Result<List<LingXingSellerResponse>>> GetSeller()
{
var seller_list = _memoryCache.Get<List<LingXingSellerResponse>>("lingxing_seller");
if (seller_list != null && seller_list.Count > 0)
return Result<List<LingXingSellerResponse>>.ReSuccess(seller_list);
var request = new LingXingKongRequest();
var resUrl = await GetStr<LingXingKongRequest>("/erp/sc/data/seller/lists", request);
if (!resUrl.IsSuccess) return Result<List<LingXingSellerResponse>>.ReFailure(ResultCodes.LingXingUrlError);
var res = await _httpClientService.GetAsync<LingXingResponse>(resUrl.Data);
if (res.Code != 0)
{
_logger.LogInformation($"领星获取数据失败{res.Message}");
return Result<List<LingXingSellerResponse>>.ReFailure(ResultCodes.LingXingDataError);
}
var list = JsonConvert.DeserializeObject<List<LingXingSellerResponse>>(res.Data.ToString());
//设置缓存
_memoryCache.Set("lingxing_seller", list, new MemoryCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromMinutes(DateTimeUtil.GetTotalMinutesTimeSpan())));
return Result<List<LingXingSellerResponse>>.ReSuccess(list);
}
/// <summary>
/// 获取即使库存
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<Result<List<LingXingInventoryResponse>>> GetInventory(List<int> ids)
{
List<LingXingInventoryResponse> list = new List<LingXingInventoryResponse>();
foreach (var id in ids)
{
LingXingInventoryRequest dto = new LingXingInventoryRequest();
dto.wid = id.ToString();
//dto.length = 50;
//dto.sku = "NTONPOWER-OSP-3A2U-US-BK-4.6M";
var resUrl = await GetStr<LingXingInventoryRequest>("/erp/sc/routing/data/local_inventory/inventoryDetails", dto);
if (!resUrl.IsSuccess) return Result<List<LingXingInventoryResponse>>.ReFailure(ResultCodes.LingXingUrlError);
var res = await _httpClientService.PostAsync<LingXingResponse>(resUrl.Data, JsonConvert.SerializeObject(dto), null);
if (res.Code != 0)
{
_logger.LogInformation($"领星获取数据失败{res.Message}");
return Result<List<LingXingInventoryResponse>>.ReFailure(ResultCodes.LingXingDataError);
}
list.AddRange(JsonConvert.DeserializeObject<List<LingXingInventoryResponse>>(res.Data.ToString()));
//var b = list.Where(w => w.SKU.Equals("NTONPOWER-OSP-3A2U-US-BK-4.6M")).ToList();
int num = res.Total / 800;
for (int i = 1; i <= num; i++)
{
Thread.Sleep(1000);//怕拉取过于频繁接口限制
dto.offset = i * 800;
if (i == num) dto.length = res.Total - (num * 800);
var resUrl_f = await GetStr<LingXingInventoryRequest>("/erp/sc/routing/data/local_inventory/inventoryDetails", dto);
if (!resUrl_f.IsSuccess) return Result<List<LingXingInventoryResponse>>.ReFailure(ResultCodes.LingXingUrlError);
var res_f = await _httpClientService.PostAsync<LingXingResponse>(resUrl_f.Data, JsonConvert.SerializeObject(dto), null);
if (res_f.Code != 0)
{
_logger.LogInformation($"领星获取数据失败{res.Message}");
return Result<List<LingXingInventoryResponse>>.ReFailure(ResultCodes.LingXingDataError);
}
var d = JsonConvert.DeserializeObject<List<LingXingInventoryResponse>>(res_f.Data.ToString());
//var bc = d.Where(w => w.SKU.Equals("NTONPOWER-OSP-3A2U-US-BK-4.6M")).Any();
//_logger.LogInformation($"次数:{i} 是否存在{bc}");
list.AddRange(d);
}
}
//var bcd = list.Where(w => w.SKU.Equals("NTONPOWER-OSP-3A2U-US-BK-4.6M")).ToList();
return Result<List<LingXingInventoryResponse>>.ReSuccess(list.Where(w => w.Product_Total > 0 && w.Product_Valid_Num > 0).ToList());
}
#region
public async Task<Result<string>> GetStr<T>(string urlStr, T data)
{
var res = await Login();
if (!res.IsSuccess) return res;
LxSignInfo lxSign = new LxSignInfo();
lxSign.access_token = res.Data;
lxSign.app_key = _option.AppId;
lxSign.timestamp = DateTime.Now.DateTimeToTimeStamp().ToString();
#region ASCII排序
Dictionary<string, object> testParamDics = new Dictionary<string, object>();
var ssi = GetEntityPropertyToDic(testParamDics, lxSign.GetType().GetProperties(), lxSign);//把签名参数实体转化为键值对
var ssdata = GetEntityPropertyToDic(testParamDics, data.GetType().GetProperties(), data);//把参数实体转化为键值对
// List<KeyValueInfo<string, string>> list = new List<KeyValueInfo<string, string>>();
Dictionary<string, string> list = new Dictionary<string, string>();
//string[] arrays = new string[data];
foreach (var item in typeof(LxSignInfo).GetProperties())
{
//KeyValueInfo<string, string> keys = new KeyValueInfo<string, string>();
//keys.Key = item.Name;
//keys.Value = ssi[$"{item.Name}"].ToString();
//list.Add(keys);
list.Add(item.Name, ssi[$"{item.Name}"].ToString());
}
foreach (var item in typeof(T).GetProperties())
{
//KeyValueInfo<string, string> keys = new KeyValueInfo<string, string>();
//keys.Key = item.Name;
//keys.Value = JsonConvert.SerializeObject(ssdata[$"{item.Name}"]);
//if (ssdata[$"{item.Name}"] == null) { list.Add(keys); continue; }
//if (string.IsNullOrEmpty(ssdata[$"{item.Name}"].ToString()))
//{
// continue;//跳过值为NULL的
//}
if (ssdata[$"{item.Name}"] == null) { list.Add(item.Name, JsonConvert.SerializeObject(ssdata[$"{item.Name}"])); continue; }
if (string.IsNullOrEmpty(ssdata[$"{item.Name}"].ToString()))
{
continue;//跳过值为NULL的
}
list.Add(item.Name, JsonConvert.SerializeObject(ssdata[$"{item.Name}"]));
}
string[] arrays = new string[list.Count];
int i = 0;
foreach (var item in list)
{
arrays[i] = item.Key;
i++;
}
Array.Sort(arrays, string.CompareOrdinal); //ASCII排序
string sig = null;
int j = 0;
foreach (var item in arrays)
{
string key = list.Where(a => a.Key == item).ToList()[0].Key.ToString();
string value = list.Where(a => a.Key == item).ToList()[0].Value.ToString();
#region
if (value.IndexOf("{", StringComparison.OrdinalIgnoreCase) > -1) { }
else
{
value = Regex.Replace(value, @"[\""]+", "");//去掉双引号
}
#endregion
if (j == i - 1)
{
sig += $"{key}={value}";
}
else
{
sig += $"{key}={value}&";
}
j++;
}
#endregion
#region MD5加密转大写+AES/ECB/PKCS5PADDING加密
//sig = Regex.Replace(sig, @"[\""]+", "");//去掉双引号
var md5 = MD5Encrypt(sig, false);
var signs = Encrypt(md5, lxSign.app_key);
#endregion
#region
signs = WebUtility.UrlEncode(signs);
#endregion
#region
var url = _option.Url + urlStr;
var ret = $"{url}?app_key={lxSign.app_key}&access_token={lxSign.access_token}&timestamp={lxSign.timestamp}&sign={signs}";
return Result<string>.ReSuccess(ret);
#endregion
}
/// <summary>
/// 32位MD5加密
/// </summary>
/// <param name="strText">要加密字符串</param>
/// <param name="IsLower">是否以小写方式返回</param>
/// <returns></returns>
public static string MD5Encrypt(string strText, bool IsLower = true)
{
MD5 md5 = new MD5CryptoServiceProvider();
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(strText);
bytes = md5.ComputeHash(bytes);
md5.Clear();
string ret = "";
for (int i = 0; i < bytes.Length; i++)
{
ret += Convert.ToString(bytes[i], 16).PadLeft(2, '0');
}
if (IsLower == false) { return ret.PadLeft(32, '0').ToUpper(); }
return ret.PadLeft(32, '0');
}
/// <summary>
/// AES加密
/// </summary>
/// <param name="str">需要加密的字符串</param>
/// <param name="key">32位密钥</param>
///<param name="lv">向量(默认偏移量)</param>
/// <returns>加密后的字符串</returns>
public static string Encrypt(string str, string key)
{
try
{
Byte[] keyArray = System.Text.Encoding.UTF8.GetBytes(key);
Byte[] toEncryptArray = System.Text.Encoding.UTF8.GetBytes(str);
var rijndael = new System.Security.Cryptography.RijndaelManaged();
rijndael.Key = keyArray;
rijndael.Mode = System.Security.Cryptography.CipherMode.ECB;
rijndael.Padding = System.Security.Cryptography.PaddingMode.PKCS7;
rijndael.IV = System.Text.Encoding.UTF8.GetBytes(key);
System.Security.Cryptography.ICryptoTransform cTransform = rijndael.CreateEncryptor();
Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
catch (Exception ex)
{
//YellowJLog("调用AES加密方法异常异常原因" + ex.Message, "加密异常");
return "";
}
}
/// <summary>
/// 类实体的属性与值转化成键值对形式
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="inParam"></param>
/// <param name="infos"></param>
/// <param name="Entity"></param>
public static Dictionary<string, object> GetEntityPropertyToDic<T>(Dictionary<string, object> inParam, PropertyInfo[] infos, T Entity)
{
foreach (var info in infos)
{
var itemTpe = info.PropertyType;
//实体中有嵌套类的处理
if (itemTpe.IsClass && !itemTpe.Name.Equals("String", StringComparison.OrdinalIgnoreCase))
{
//if (info.GetValue(Entity) == null) continue;
//GetEntityPropertyToDic(inParam, itemTpe.GetProperties(), info.GetValue(Entity));
//inParam.Add(info.Name, info.GetValue(JsonConvert.SerializeObject(Entity), null));
inParam.Add(info.Name, info.GetValue(Entity, null));
}
else
{
inParam.Add(info.Name, info.GetValue(Entity, null));
//sig = Regex.Replace(sig, @"[\""]+", "");//去掉双引号
}
}
return inParam;
}
#endregion
}
public class LxSignInfo
{
public string access_token { get; set; }
public string app_key { get; set; }
public string timestamp { get; set; }
}
}

View File

@@ -262,14 +262,14 @@ namespace WMS.Web.Domain.Services
int subStockId = subs.Data.FirstOrDefault(w => w.OrgCode.Equals(d.OrgCode) && w.StockCode.Equals(d.Erp_SubStockCode))?.Id ?? 0;
requestInventory.Add((d.MaterialNumber, d.OrgCode, d.StockCode, subStockId));
};
var res_s = await sc_erpService.BillQueryForInventory(requestInventory);
if (!res_s.IsSuccess)
{
entity.Sync(false, res_s.Message, SyncStatus.Fail, "");
await sc_takeStockRepositories.Edit(entity, true);
_logger.LogInformation($"及时库存获取异常->错误:{res_s.Message} 数据: {JsonConvert.SerializeObject(entity)}");
return Result<ErpTakeStockSaveDto>.ReFailure(res_s.Message, res_s.Status);
}
//var res_s = await sc_erpService.BillQueryForInventory(requestInventory);
//if (!res_s.IsSuccess)
//{
// entity.Sync(false, res_s.Message, SyncStatus.Fail, "");
// await sc_takeStockRepositories.Edit(entity, true);
// _logger.LogInformation($"及时库存获取异常->错误:{res_s.Message} 数据: {JsonConvert.SerializeObject(entity)}");
// return Result<ErpTakeStockSaveDto>.ReFailure(res_s.Message, res_s.Status);
//}
//组装dto
#region dto
//子仓库 ORICO_JD1000008 GD1000005 HD1000007 AD1000004
@@ -278,9 +278,10 @@ namespace WMS.Web.Domain.Services
{
int subStockId = subs.Data.FirstOrDefault(w => w.OrgCode.Equals(d.OrgCode) && w.StockCode.Equals(d.Erp_SubStockCode))?.Id ?? 0;
var number = d.MaterialNumber;
var erpInventory = res_s.Data.FirstOrDefault(f => f.MaterialNumber == number && f.StockCode == d.StockCode
&& f.OrgCode == d.OrgCode && f.Erp_SubStockId == subStockId);
decimal qty = erpInventory?.Qty ?? 0;
//var erpInventory = res_s.Data.FirstOrDefault(f => f.MaterialNumber == number && f.StockCode == d.StockCode
//&& f.OrgCode == d.OrgCode && f.Erp_SubStockId == subStockId);
//decimal qty = erpInventory?.Qty ?? 0;
decimal qty = 0;
var unitNumber = _erpBasicDataExtendService.GetMaterialUnitNumber(materials, d.MaterialNumber);
detils.Add(new ErpTakeStockDetailsSaveDto()
{

View File

@@ -70,5 +70,11 @@ namespace WMS.Web.Domain.Values
/// </summary>
[EnumRemark("出库信息")]
OutStockTaskInfo = 12,
/// <summary>
/// 成品即时库存
/// </summary>
[EnumRemark("成品即时库存")]
ProductInventory = 13,
}
}

View File

@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Text;
using WMS.Web.Core;
namespace WMS.Web.Domain.Values
{
/// <summary>
/// 成品即时库存类型
/// </summary>
public enum ProductInventoryType
{
/// <summary>
/// 金蝶
/// </summary>
[EnumRemark("金蝶")]
JinDie = 0,
/// <summary>
/// 领星
/// </summary>
[EnumRemark("领星")]
LingXing = 1,
/// <summary>
/// 聚水潭
/// </summary>
[EnumRemark("聚水潭")]
JushuiTan = 2,
}
}

View File

@@ -97,6 +97,11 @@ namespace WMS.Web.Domain.Values
public static ValueTuple<int, string> SubscribeNotificationNoData = (700001, "订阅通知信息不存在");
public static ValueTuple<int, string> GetBarCodeSerialNumberError = (800001, "获取序列码异常");
public static ValueTuple<int, string> LingXingTokenError = (810001, "获取领星授权失败");
public static ValueTuple<int, string> LingXingUrlError = (810002, "拼接领星请求参数失败");
public static ValueTuple<int, string> LingXingDataError = (810003, "请求领星数据失败");
public static ValueTuple<int, string> JuShuiTanDataError = (810004, "请求聚水潭数据失败");
public static ValueTuple<int, string> SyncSuccessError = (800002, "单据已经同步成功");
}
}

View File

@@ -211,5 +211,9 @@ namespace WMS.Web.Domain.Values.Single
/// 获取仓位详情根据仓位Codes集合和公司ID
/// </summary>
GetWmsSubWarehouseByCodesAndCompany = 48,
/// <summary>
/// 获取仓库::根据总公司标记获取仓库
/// </summary>
GetWmsWarehouseByHeadOfficeAndNameAndCompany = 49,
}
}