From ea44abf6af6169a74500a2901868a2f647212010 Mon Sep 17 00:00:00 2001 From: "yang.lee" Date: Tue, 7 Nov 2023 18:01:59 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=87=E8=B4=AD=E6=94=B6=E8=B4=A7=EF=BC=8C?= =?UTF-8?q?=E9=94=80=E5=94=AE=E5=8F=91=E8=B4=A7=E4=B8=9A=E5=8A=A1=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Consts/ModuleConsts.cs | 9 +- .../Dto/Inputs/PurchaseAndReceiveUpInput.cs | 133 +++++++++++++++ .../Constraints/IPurchaseAndSaleEntity.cs | 34 ++++ .../IPurchaseAndSaleQueryEntity.cs | 15 ++ .../Entity/WmsInstockH.cs | 5 +- .../Entity/WmsPurchaseD.cs | 102 ++++++++++++ .../Entity/WmsPurchaseD.part.cs | 20 +++ .../Entity/WmsPurchaseH.cs | 147 +++++++++++++++++ .../Entity/WmsSaleD.cs | 88 ++++++++++ .../Entity/WmsSaleD.part.cs | 33 ++++ .../Entity/WmsSaleH.cs | 147 +++++++++++++++++ .../Mapper/Mapper.cs | 6 +- .../IWmsInStockService.cs | 5 +- .../IWmsOutStockService.cs | 9 +- .../IWmsPDAScanInStockService.cs | 14 ++ .../Tnb.WarehouseMgr/WmsOutStockService.cs | 2 +- .../Tnb.WarehouseMgr/WmsPDAInStockService.cs | 35 ++-- .../WmsPDAScanInStockService.cs | 156 +++++++++++------- .../WmsPurchaseAndSaleCommonService.cs | 134 +++++++++++++++ .../Tnb.WarehouseMgr/WmsPurchaseService.cs | 105 ++++++++++++ .../Tnb.WarehouseMgr/WmsSaleService.cs | 39 +++++ common/Tnb.Common/Utils/PocoToDictionary.cs | 46 ++++++ 22 files changed, 1201 insertions(+), 83 deletions(-) create mode 100644 WarehouseMgr/Tnb.WarehouseMgr.Entities/Dto/Inputs/PurchaseAndReceiveUpInput.cs create mode 100644 WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/Constraints/IPurchaseAndSaleEntity.cs create mode 100644 WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/Constraints/IPurchaseAndSaleQueryEntity.cs create mode 100644 WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsPurchaseD.cs create mode 100644 WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsPurchaseD.part.cs create mode 100644 WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsPurchaseH.cs create mode 100644 WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsSaleD.cs create mode 100644 WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsSaleD.part.cs create mode 100644 WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsSaleH.cs create mode 100644 WarehouseMgr/Tnb.WarehouseMgr.Interfaces/IWmsPDAScanInStockService.cs create mode 100644 WarehouseMgr/Tnb.WarehouseMgr/WmsPurchaseAndSaleCommonService.cs create mode 100644 WarehouseMgr/Tnb.WarehouseMgr/WmsPurchaseService.cs create mode 100644 WarehouseMgr/Tnb.WarehouseMgr/WmsSaleService.cs create mode 100644 common/Tnb.Common/Utils/PocoToDictionary.cs diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Entities/Consts/ModuleConsts.cs b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Consts/ModuleConsts.cs index 4b209e25..77cdcdf4 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr.Entities/Consts/ModuleConsts.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Consts/ModuleConsts.cs @@ -1,4 +1,6 @@ -namespace Tnb.WarehouseMgr; +using System.CodeDom; + +namespace Tnb.WarehouseMgr; public class ModuleConsts { @@ -185,5 +187,8 @@ public class ModuleConsts /// 模块标识-PDA寄存出库 /// public const string MODULE_WMSSCANCODEINSTOCKPDA_ID = "28576495374869"; - + /// + /// 模块标识-采购收货 + /// + public const string MODULE_WMSPURCHASE_ID = "29975280336405"; } \ No newline at end of file diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Entities/Dto/Inputs/PurchaseAndReceiveUpInput.cs b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Dto/Inputs/PurchaseAndReceiveUpInput.cs new file mode 100644 index 00000000..b7e7442c --- /dev/null +++ b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Dto/Inputs/PurchaseAndReceiveUpInput.cs @@ -0,0 +1,133 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tnb.WarehouseMgr.Entities.Dto +{ + /// + /// 采购收货编辑输入参数 + /// + public class PurchaseAndReceiveUpInput + { + public string bill_code { get; set; } = string.Empty; + + /// + /// 单据类型 + /// + public string bill_type { get; set; } = string.Empty; + + /// + /// 单据状态 + /// + public string status { get; set; } = string.Empty; + + /// + /// 业务类型 + /// + public string biz_type { get; set; } = string.Empty; + + /// + /// 入库仓库ID + /// + public string? warehouse_id { get; set; } + + /// + /// 供应商ID + /// + public string? supplier_id { get; set; } + + /// + /// 供应商代码 + /// + public string? supplier_code { get; set; } + + /// + /// 供应商名称 + /// + public string? supplier_name { get; set; } + + /// + /// 生成类型 + /// + public string generate_type { get; set; } = string.Empty; + + /// + /// 备注 + /// + public string? remark { get; set; } + + /// + /// 扩展字段 + /// + public string? extras { get; set; } + + /// + /// 时间戳 + /// + public DateTime? time_stamp { get; set; } + + /// + /// 创建用户 + /// + public string create_id { get; set; } = string.Empty; + + /// + /// 创建时间 + /// + public DateTime create_time { get; set; } = DateTime.Now; + + /// + /// 修改用户 + /// + public string? modify_id { get; set; } + + /// + /// 修改时间 + /// + public DateTime? modify_time { get; set; } + + /// + /// 来源单据ID + /// + public string? source_id { get; set; } + + /// + /// 来源单据代码 + /// + public string? source_code { get; set; } + + /// + /// 流程任务Id + /// + public string? f_flowtaskid { get; set; } + + /// + /// 流程引擎Id + /// + public string? f_flowid { get; set; } + + /// + /// 供货日期 + /// + public DateTime delivery_date { get; set; } = DateTime.Now; + + /// + /// 审核员 + /// + public string? auditor_id { get; set; } + + /// + /// 运输方式 + /// + public string? shipping_method { get; set; } + + /// + /// 审核状态 + /// + public int? audit_status { get; set; } + + public List details { get; set; } = new(); + } +} diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/Constraints/IPurchaseAndSaleEntity.cs b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/Constraints/IPurchaseAndSaleEntity.cs new file mode 100644 index 00000000..0b519c09 --- /dev/null +++ b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/Constraints/IPurchaseAndSaleEntity.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tnb.WarehouseMgr.Entities.Entity.Constraints +{ + /// + /// 采购收货、销售发货 接口约束 + /// + public interface IPurchaseAndSaleEntity + { + public string material_id { get; set; } + /// + /// 已到货数量 + /// + public decimal purchase_prqty { get; set; } + /// + /// 采购数量 + /// + public decimal purchase_qty { get; set; } + /// + /// 本次到货数量 + /// + public decimal purchase_arriveqty { get; set; } + /// + /// 执行状态 + /// + public string line_status { get; set; } + public string modify_id { get; set; } + public DateTime? modify_time { get; set; } + } +} diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/Constraints/IPurchaseAndSaleQueryEntity.cs b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/Constraints/IPurchaseAndSaleQueryEntity.cs new file mode 100644 index 00000000..b189de0c --- /dev/null +++ b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/Constraints/IPurchaseAndSaleQueryEntity.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tnb.WarehouseMgr.Entities.Entity.Constraints +{ + public interface IPurchaseAndSaleQueryEntity + { + public string bill_id { get; set; } + public string material_name { get; set; } + public string material_id { get; set; } + } +} diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsInstockH.cs b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsInstockH.cs index 8562ce01..97516e77 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsInstockH.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsInstockH.cs @@ -208,5 +208,8 @@ public partial class WmsInstockH : BaseEntity /// 流程引擎Id /// public string? f_flowid { get; set; } - + /// + /// 采购单号 + /// + public string purchase_code { get; set; } } diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsPurchaseD.cs b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsPurchaseD.cs new file mode 100644 index 00000000..17082d0a --- /dev/null +++ b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsPurchaseD.cs @@ -0,0 +1,102 @@ +using JNPF.Common.Contracts; +using JNPF.Common.Security; +using SqlSugar; + +namespace Tnb.WarehouseMgr.Entities; + +/// +/// 采购收货明细表 +/// +[SugarTable("wms_purchase_d")] +public partial class WmsPurchaseD : BaseEntity +{ + public WmsPurchaseD() + { + id = SnowflakeIdHelper.NextId(); + } + /// + /// 采购收货单ID + /// + public string bill_id { get; set; } = string.Empty; + + /// + /// 执行状态 + /// + public string line_status { get; set; } = string.Empty; + + /// + /// 物品ID + /// + public string material_id { get; set; } = string.Empty; + + /// + /// 物品代码 + /// + public string material_code { get; set; } = string.Empty; + + /// + /// 单位ID + /// + public string unit_id { get; set; } = string.Empty; + + /// + /// 采购数量 + /// + public decimal purchase_qty { get; set; } + + /// + /// 已到货数量 + /// + public decimal purchase_prqty { get; set; } + + /// + /// 扩展字段 + /// + public string? extras { get; set; } + + /// + /// 时间戳 + /// + public DateTime? time_stamp { get; set; } + + /// + /// 创建用户 + /// + public string? create_id { get; set; } + + /// + /// 创建时间 + /// + public DateTime? create_time { get; set; } + + /// + /// 修改用户 + /// + public string? modify_id { get; set; } + + /// + /// 修改时间 + /// + public DateTime? modify_time { get; set; } + + /// + /// 批次 + /// + public string? code_batch { get; set; } + + /// + /// 流程任务Id + /// + public string? f_flowtaskid { get; set; } + + /// + /// 流程引擎Id + /// + public string? f_flowid { get; set; } + + /// + /// 本次到货数量 + /// + public decimal purchase_arriveqty { get; set; } + +} diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsPurchaseD.part.cs b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsPurchaseD.part.cs new file mode 100644 index 00000000..7cfb38b3 --- /dev/null +++ b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsPurchaseD.part.cs @@ -0,0 +1,20 @@ +using JNPF.Common.Contracts; +using JNPF.Common.Security; +using SqlSugar; +using Tnb.WarehouseMgr.Entities.Entity.Constraints; + +namespace Tnb.WarehouseMgr.Entities; + +/// +/// 采购收货明细表 +/// +public partial class WmsPurchaseD : IPurchaseAndSaleEntity, IPurchaseAndSaleQueryEntity +{ + /// + /// 物料名称 + /// + [SugarColumn(IsIgnore = true)] + public string material_name { get; set; } +} + + diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsPurchaseH.cs b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsPurchaseH.cs new file mode 100644 index 00000000..78b24706 --- /dev/null +++ b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsPurchaseH.cs @@ -0,0 +1,147 @@ +using JNPF.Common.Contracts; +using JNPF.Common.Security; +using SqlSugar; + +namespace Tnb.WarehouseMgr.Entities; + +/// +/// 采购收货主表 +/// +[SugarTable("wms_purchase_h")] +public partial class WmsPurchaseH : BaseEntity +{ + public WmsPurchaseH() + { + id = SnowflakeIdHelper.NextId(); + } + /// + /// 租户ID + /// + public string? tenant_id { get; set; } + + /// + /// 所属组织ID + /// + public string? org_id { get; set; } + + /// + /// 采购收货单号 + /// + public string bill_code { get; set; } = string.Empty; + + /// + /// 单据类型 + /// + public string bill_type { get; set; } = string.Empty; + + /// + /// 单据状态 + /// + public string status { get; set; } = string.Empty; + + /// + /// 业务类型 + /// + public string biz_type { get; set; } = string.Empty; + + /// + /// 入库仓库ID + /// + public string? warehouse_id { get; set; } + + /// + /// 供应商ID + /// + public string? supplier_id { get; set; } + + /// + /// 供应商代码 + /// + public string? supplier_code { get; set; } + + /// + /// 供应商名称 + /// + public string? supplier_name { get; set; } + + /// + /// 生成类型 + /// + public string generate_type { get; set; } = string.Empty; + + /// + /// 备注 + /// + public string? remark { get; set; } + + /// + /// 扩展字段 + /// + public string? extras { get; set; } + + /// + /// 时间戳 + /// + public DateTime? time_stamp { get; set; } + + /// + /// 创建用户 + /// + public string create_id { get; set; } = string.Empty; + + /// + /// 创建时间 + /// + public DateTime create_time { get; set; } = DateTime.Now; + + /// + /// 修改用户 + /// + public string? modify_id { get; set; } + + /// + /// 修改时间 + /// + public DateTime? modify_time { get; set; } + + /// + /// 来源单据ID + /// + public string? source_id { get; set; } + + /// + /// 来源单据代码 + /// + public string? source_code { get; set; } + + /// + /// 流程任务Id + /// + public string? f_flowtaskid { get; set; } + + /// + /// 流程引擎Id + /// + public string? f_flowid { get; set; } + + /// + /// 供货日期 + /// + public DateTime delivery_date { get; set; } = DateTime.Now; + + /// + /// 审核员 + /// + public string? auditor_id { get; set; } + + /// + /// 运输方式 + /// + public string? shipping_method { get; set; } + + /// + /// 审核状态 + /// + public int? audit_status { get; set; } + +} diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsSaleD.cs b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsSaleD.cs new file mode 100644 index 00000000..850e0e4c --- /dev/null +++ b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsSaleD.cs @@ -0,0 +1,88 @@ +using JNPF.Common.Contracts; +using JNPF.Common.Security; +using SqlSugar; + +namespace Tnb.WarehouseMgr.Entities; + +/// +/// 销售发货明细表 +/// +[SugarTable("wms_sale_d")] +public partial class WmsSaleD : BaseEntity +{ + public WmsSaleD() + { + id = SnowflakeIdHelper.NextId(); + } + /// + /// 销售发货单ID + /// + public string bill_id { get; set; } = string.Empty; + + /// + /// 执行状态 + /// + public string line_status { get; set; } = string.Empty; + + /// + /// 物品ID + /// + public string material_id { get; set; } = string.Empty; + + /// + /// 物品代码 + /// + public string material_code { get; set; } = string.Empty; + + /// + /// 单位ID + /// + public string unit_id { get; set; } = string.Empty; + + /// + /// 扩展字段 + /// + public string? extras { get; set; } + + /// + /// 时间戳 + /// + public DateTime? time_stamp { get; set; } + + /// + /// 创建用户 + /// + public string? create_id { get; set; } + + /// + /// 创建时间 + /// + public DateTime? create_time { get; set; } + + /// + /// 修改用户 + /// + public string? modify_id { get; set; } + + /// + /// 修改时间 + /// + public DateTime? modify_time { get; set; } + + /// + /// 批次 + /// + public string? code_batch { get; set; } + + /// + /// 流程任务Id + /// + public string? f_flowtaskid { get; set; } + + /// + /// 流程引擎Id + /// + public string? f_flowid { get; set; } + + +} diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsSaleD.part.cs b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsSaleD.part.cs new file mode 100644 index 00000000..90f7c0a4 --- /dev/null +++ b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsSaleD.part.cs @@ -0,0 +1,33 @@ +using JNPF.Common.Contracts; +using JNPF.Common.Security; +using SqlSugar; +using Tnb.WarehouseMgr.Entities.Entity.Constraints; + +namespace Tnb.WarehouseMgr.Entities; + +/// +/// 销售发货明细表 +/// +public partial class WmsSaleD : IPurchaseAndSaleEntity, IPurchaseAndSaleQueryEntity +{ + /// + /// 物料名称 + /// + [SugarColumn(IsIgnore = true)] + public string material_name { get; set; } + /// + /// 本次发货数量 + /// + [SugarColumn(ColumnName = "sale_sendqty")] + public decimal purchase_arriveqty { get; set; } + /// + ///已 发货数量 + /// + [SugarColumn(ColumnName = "sale_prqty")] + public decimal purchase_prqty { get; set; } + /// + /// 发货数量 + /// + [SugarColumn(ColumnName = "sale_qty")] + public decimal purchase_qty { get; set; } +} diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsSaleH.cs b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsSaleH.cs new file mode 100644 index 00000000..269fb93c --- /dev/null +++ b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsSaleH.cs @@ -0,0 +1,147 @@ +using JNPF.Common.Contracts; +using JNPF.Common.Security; +using SqlSugar; + +namespace Tnb.WarehouseMgr.Entities; + +/// +/// 销售发货主表 +/// +[SugarTable("wms_sale_h")] +public partial class WmsSaleH : BaseEntity +{ + public WmsSaleH() + { + id = SnowflakeIdHelper.NextId(); + } + /// + /// 租户ID + /// + public string? tenant_id { get; set; } + + /// + /// 所属组织ID + /// + public string? org_id { get; set; } + + /// + /// 销售发货单号 + /// + public string bill_code { get; set; } = string.Empty; + + /// + /// 单据类型 + /// + public string bill_type { get; set; } = string.Empty; + + /// + /// 单据状态 + /// + public string status { get; set; } = string.Empty; + + /// + /// 业务类型 + /// + public string biz_type { get; set; } = string.Empty; + + /// + /// 出库仓库ID + /// + public string? warehouse_id { get; set; } + + /// + /// 客户ID + /// + public string? customer_id { get; set; } + + /// + /// 客户代码 + /// + public string? customer_code { get; set; } + + /// + /// 客户名称 + /// + public string? customer_name { get; set; } + + /// + /// 生成类型 + /// + public string generate_type { get; set; } = string.Empty; + + /// + /// 备注 + /// + public string? remark { get; set; } + + /// + /// 扩展字段 + /// + public string? extras { get; set; } + + /// + /// 时间戳 + /// + public DateTime? time_stamp { get; set; } + + /// + /// 创建用户 + /// + public string create_id { get; set; } = string.Empty; + + /// + /// 创建时间 + /// + public DateTime create_time { get; set; } = DateTime.Now; + + /// + /// 修改用户 + /// + public string? modify_id { get; set; } + + /// + /// 修改时间 + /// + public DateTime? modify_time { get; set; } + + /// + /// 来源单据ID + /// + public string? source_id { get; set; } + + /// + /// 来源单据代码 + /// + public string? source_code { get; set; } + + /// + /// 流程任务Id + /// + public string? f_flowtaskid { get; set; } + + /// + /// 流程引擎Id + /// + public string? f_flowid { get; set; } + + /// + /// 供货日期 + /// + public DateTime ship_date { get; set; } = DateTime.Now; + + /// + /// 审核员 + /// + public string? auditor_id { get; set; } + + /// + /// 运输方式 + /// + public string? shipping_method { get; set; } + + /// + /// 审核状态 + /// + public int? audit_status { get; set; } + +} diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Entities/Mapper/Mapper.cs b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Mapper/Mapper.cs index ece5b726..ea946732 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr.Entities/Mapper/Mapper.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Mapper/Mapper.cs @@ -1,4 +1,5 @@ -using Mapster; +using JNPF.Common.Security; +using Mapster; using Tnb.WarehouseMgr.Entities.Consts; using Tnb.WarehouseMgr.Entities.Dto.Inputs; using Tnb.WarehouseMgr.Entities.Dto.Outputs; @@ -21,6 +22,9 @@ namespace Tnb.WarehouseMgr.Entities.Mapper .Map(dest => dest.qc_status, src => src.is_check == 0 ? "不合格" : "合格"); config.ForType() .Map(dest => dest.check_conclusion, src => GenericEnumDicionary.GetEnumDesc(src.check_conclusion)); + config.ForType() + .Map(dest => dest.id, src => SnowflakeIdHelper.NextId()) + .Map(dest => dest.pr_qty, src => src.purchase_arriveqty); } } } \ No newline at end of file diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Interfaces/IWmsInStockService.cs b/WarehouseMgr/Tnb.WarehouseMgr.Interfaces/IWmsInStockService.cs index 1c28a801..9ee39468 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr.Interfaces/IWmsInStockService.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr.Interfaces/IWmsInStockService.cs @@ -1,9 +1,12 @@ -namespace Tnb.WarehouseMgr.Interfaces +using Tnb.WarehouseMgr.Entities.Dto.Inputs; + +namespace Tnb.WarehouseMgr.Interfaces { /// /// 入库申请服务接口 /// public interface IWmsInStockService { + Task MESCreateInstock(MESCreateInstockInput input); } } diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Interfaces/IWmsOutStockService.cs b/WarehouseMgr/Tnb.WarehouseMgr.Interfaces/IWmsOutStockService.cs index 1b18a8e6..5d246e58 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr.Interfaces/IWmsOutStockService.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr.Interfaces/IWmsOutStockService.cs @@ -1,4 +1,5 @@ -using Tnb.WarehouseMgr.Entities.Dto.Inputs; +using JNPF.Common.Dtos.VisualDev; +using Tnb.WarehouseMgr.Entities.Dto.Inputs; namespace Tnb.WarehouseMgr.Interfaces { @@ -13,5 +14,11 @@ namespace Tnb.WarehouseMgr.Interfaces /// /// Task MESCreateOutstock(MESCreateOutstockInput input); + /// + /// 出库申请 + /// + /// + /// + Task OutStockApplyFor(VisualDevModelDataCrInput input); } } diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Interfaces/IWmsPDAScanInStockService.cs b/WarehouseMgr/Tnb.WarehouseMgr.Interfaces/IWmsPDAScanInStockService.cs new file mode 100644 index 00000000..008bb0ba --- /dev/null +++ b/WarehouseMgr/Tnb.WarehouseMgr.Interfaces/IWmsPDAScanInStockService.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using JNPF.Common.Dtos.VisualDev; + +namespace Tnb.WarehouseMgr.Interfaces +{ + public interface IWmsPDAScanInStockService + { + Task ScanInStock(VisualDevModelDataCrInput input); + } +} diff --git a/WarehouseMgr/Tnb.WarehouseMgr/WmsOutStockService.cs b/WarehouseMgr/Tnb.WarehouseMgr/WmsOutStockService.cs index 97a69412..355db6b3 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr/WmsOutStockService.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr/WmsOutStockService.cs @@ -72,7 +72,7 @@ namespace Tnb.WarehouseMgr OverideFuncs.CreateAsync = OutStockApplyFor; } - private async Task OutStockApplyFor(VisualDevModelDataCrInput input) + public async Task OutStockApplyFor(VisualDevModelDataCrInput input) { try { diff --git a/WarehouseMgr/Tnb.WarehouseMgr/WmsPDAInStockService.cs b/WarehouseMgr/Tnb.WarehouseMgr/WmsPDAInStockService.cs index b3071f86..72119a86 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr/WmsPDAInStockService.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr/WmsPDAInStockService.cs @@ -235,30 +235,33 @@ namespace Tnb.WarehouseMgr List items = instockDetails.Adapt>(); //items.ForEach(it => it.org_id = _userManager.User.OrganizeId); List instockCOdes = new(); - jArr = JArray.Parse(input.data["tablefield115"].ToString()!); - if (jArr?.Children().Count() > 0) + if (input.data.ContainsKey("tablefield115")) { - foreach (JToken jo in jArr.Children()) + jArr = JArray.Parse(input.data["tablefield115"].ToString()!); + if (jArr?.Children().Count() > 0) { - string? materialCode = jo.Value(nameof(WmsInstockCode.material_code)); - string? codeBatch = jo.Value(nameof(WmsInstockCode.code_batch)); - WmsInstockCode? b = items.Find(x => x.material_code == materialCode && x.code_batch == codeBatch); - if (b != null) + foreach (JToken jo in jArr.Children()) { - WmsInstockCode c = DeepCopyHelper.DeepCopy(b); - c.id = SnowflakeIdHelper.NextId(); - c.bill_d_id = b.id; - c.barcode = jo.Value(nameof(WmsInstockCode.barcode))!; - c.codeqty = jo.Value(nameof(WmsInstockCode.codeqty)); - instockCOdes.Add(c); + string? materialCode = jo.Value(nameof(WmsInstockCode.material_code)); + string? codeBatch = jo.Value(nameof(WmsInstockCode.code_batch)); + WmsInstockCode? b = items.Find(x => x.material_code == materialCode && x.code_batch == codeBatch); + if (b != null) + { + WmsInstockCode c = DeepCopyHelper.DeepCopy(b); + c.id = SnowflakeIdHelper.NextId(); + c.bill_d_id = b.id; + c.barcode = jo.Value(nameof(WmsInstockCode.barcode))!; + c.codeqty = jo.Value(nameof(WmsInstockCode.codeqty)); + instockCOdes.Add(c); + } } } + string orgId = _userManager.User.OrganizeId; + _ = await _db.Insertable(instockCOdes).CallEntityMethod(it => it.Create(orgId)).ExecuteCommandAsync(); + _ = await _db.Updateable().SetColumns(it => new WmsTempCode { is_end = 1 }).Where(it => instockCOdes.Select(x => x.barcode).Contains(it.barcode)).ExecuteCommandAsync(); } - string orgId = _userManager.User.OrganizeId; _ = await _db.Insertable(carryCodes).ExecuteCommandAsync(); - _ = await _db.Insertable(instockCOdes).CallEntityMethod(it => it.Create(orgId)).ExecuteCommandAsync(); // 更新临时条码表 状态is_end - _ = await _db.Updateable().SetColumns(it => new WmsTempCode { is_end = 1 }).Where(it => instockCOdes.Select(x => x.barcode).Contains(it.barcode)).ExecuteCommandAsync(); await _wareHouseService.GenInStockTaskHandleAfter(preTaskUpInput, it => new WmsCarryH { carry_code = input.data[nameof(WmsCarryH.carry_code)].ToString()!, is_lock = 1, carry_status = ((int)EnumCarryStatus.占用).ToString(), location_id = preTaskUpInput.CarryStartLocationId, location_code = preTaskUpInput.CarryStartLocationCode, source_id = input.data[nameof(WmsOutstockH.source_id)].ToString(), source_code = input.data[nameof(WmsOutstockH.source_code)].ToString() }, it => new BasLocation { is_lock = 1, is_use = ((int)EnumCarryStatus.占用).ToString() }); diff --git a/WarehouseMgr/Tnb.WarehouseMgr/WmsPDAScanInStockService.cs b/WarehouseMgr/Tnb.WarehouseMgr/WmsPDAScanInStockService.cs index 62966689..89bc2bce 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr/WmsPDAScanInStockService.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr/WmsPDAScanInStockService.cs @@ -24,7 +24,7 @@ namespace Tnb.WarehouseMgr /// [OverideVisualDev(ModuleConsts.MODULE_WMSSCANCODEINSTOCKPDA_ID)] [ServiceModule(BizTypeId)] - public class WmsPDAScanInStockService : BaseWareHouseService, IPdaStroage + public class WmsPDAScanInStockService : BaseWareHouseService, IWmsPDAScanInStockService, IPdaStroage { private const string BizTypeId = "26191496816421"; private readonly ISqlSugarClient _db; @@ -57,90 +57,126 @@ namespace Tnb.WarehouseMgr try { await _db.Ado.BeginTranAsync(); - WmsInstockCode item = input.data.Adapt(); - if (item.codeqty == 0) + WmsInstockCode? item = null; + BasMaterial? mat = null; + WmsCarryH? carry = null; + BasLocation? loc = null; + string? carryCode = null; + + if (input.data.ContainsKey(nameof(WmsInstockCode.barcode))) { - throw new AppFriendlyException("请输入入库数量", 500); + item = input.data.Adapt(); + if (item.codeqty == 0) + { + throw new AppFriendlyException("请输入入库数量", 500); + } + + carryCode = item.barcode; + carry = await _db.Queryable().FirstAsync(it => it.carry_code == carryCode); + if (carry == null) + { + throw new AppFriendlyException("载具有误", 500); + } + + mat = await _db.Queryable().FirstAsync(it => it.code == item.material_code); + if (mat == null) + { + throw new AppFriendlyException("物料有误", 500); + } + + loc = await _db.Queryable().FirstAsync(it => it.location_code == item.extras); + if (loc == null) + { + throw new AppFriendlyException("库位有误", 500); + } } - string carryCode = item.barcode; - WmsCarryH carry = await _db.Queryable().FirstAsync(it => it.carry_code == carryCode); - if (carry == null) - { - throw new AppFriendlyException("载具有误", 500); - } - - BasMaterial mat = await _db.Queryable().FirstAsync(it => it.code == item.material_code); - if (mat == null) - { - throw new AppFriendlyException("物料有误", 500); - } - - BasLocation loc = await _db.Queryable().FirstAsync(it => it.location_code == item.extras); - if (loc == null) - { - throw new AppFriendlyException("库位有误", 500); - } + var whId = input.data.ContainsKey(nameof(WmsPurchaseH.warehouse_id)) ? input.data[nameof(WmsPurchaseH.warehouse_id)] : null; + var billCode = input.data.ContainsKey(nameof(WmsPurchaseH.bill_code)) ? input.data[nameof(WmsPurchaseH.warehouse_id)] : null; WmsInstockH instock = new() { id = SnowflakeIdHelper.NextId(), org_id = _userManager.UserId, carry_code = carryCode, - carry_id = carry.id, - location_id = loc.id, + carry_id = carry?.id ?? string.Empty, + location_id = loc?.id ?? string.Empty, bill_code = _billRullService.GetBillNumber(WmsWareHouseConst.WMS_INSTOCK_ENCODE).GetAwaiter().GetResult(), bill_type = WmsWareHouseConst.BILLTYPE_MATERIALINSTOCK_ID, biz_type = WmsWareHouseConst.BIZTYPE_WMSINSTOCK_ID, bill_date = DateTime.Today, - warehouse_id = "26103372441637", + warehouse_id = whId?.ToString() ?? "26103372441637", status = WmsWareHouseConst.BILLSTATUS_ADD_ID, generate_type = "0", sync_status = WmsWareHouseConst.SYNC_STATUS_NONEEDSYNC, print_status = WmsWareHouseConst.PRINT_STATUS_PRINTCOMPLETE, is_check = 1, + purchase_code = billCode?.ToString() ?? string.Empty, create_id = _userManager.UserId, create_time = DateTime.Now, }; - WmsInstockD instockD = new() + var instockDs = new List(); + WmsInstockD? instockD = null; + if (mat != null) { - id = SnowflakeIdHelper.NextId(), - bill_id = instock.id, - line_status = WmsWareHouseConst.BILLSTATUS_ADD_ID, - material_id = mat.id, - material_code = mat.code, - unit_id = mat.unit_id, - pr_qty = item.codeqty, - qty = 0, - code_batch = item.code_batch, - warehouse_id = "26103372441637", - print_qty = item.codeqty, - scan_qty = item.codeqty, - print_id = "", - create_id = _userManager.UserId, - create_time = DateTime.Now, - }; - WmsInstockCode instockCode = new() + instockD = new() + { + id = SnowflakeIdHelper.NextId(), + bill_id = instock.id, + line_status = WmsWareHouseConst.BILLSTATUS_ADD_ID, + material_id = mat.id, + material_code = mat.code, + unit_id = mat.unit_id, + pr_qty = item.codeqty, + qty = 0, + code_batch = item.code_batch, + warehouse_id = "26103372441637", + print_qty = item.codeqty, + scan_qty = item.codeqty, + print_id = "", + create_id = _userManager.UserId, + create_time = DateTime.Now, + }; + instockDs.Add(instockD); + } + else { - id = SnowflakeIdHelper.NextId(), - bill_id = instock.id, - bill_d_id = instockD.id, - line_status = WmsWareHouseConst.BILLSTATUS_ADD_ID, - material_id = mat.id, - material_code = mat.code, - unit_id = mat.unit_id, - barcode = carryCode, - code_batch = item.code_batch, - codeqty = item.codeqty, - is_lock = 0, - is_end = 0, - create_id = _userManager.UserId, - create_time = DateTime.Now, - }; + if (input.data.ContainsKey("details")) + { + instockDs = input.data["details"].Adapt>(); + + } + } + + + WmsInstockCode? instockCode = null; + if (mat != null) + { + instockCode = new() + { + id = SnowflakeIdHelper.NextId(), + bill_id = instock.id, + bill_d_id = instockD?.id ?? string.Empty, + line_status = WmsWareHouseConst.BILLSTATUS_ADD_ID, + material_id = mat.id, + material_code = mat.code, + unit_id = mat.unit_id, + barcode = carryCode, + code_batch = item.code_batch, + codeqty = item.codeqty, + is_lock = 0, + is_end = 0, + create_id = _userManager.UserId, + create_time = DateTime.Now, + }; + } _ = await _db.Insertable(instock).ExecuteCommandAsync(); - _ = await _db.Insertable(instockD).ExecuteCommandAsync(); - _ = await _db.Insertable(instockCode).ExecuteCommandAsync(); + _ = await _db.Insertable(instockDs).ExecuteCommandAsync(); + if (instockCode != null) + { + _ = await _db.Insertable(instockCode).ExecuteCommandAsync(); + } InStockStrategyQuery inStockStrategyInput = new() { warehouse_id = "26103372441637", Size = 1 }; diff --git a/WarehouseMgr/Tnb.WarehouseMgr/WmsPurchaseAndSaleCommonService.cs b/WarehouseMgr/Tnb.WarehouseMgr/WmsPurchaseAndSaleCommonService.cs new file mode 100644 index 00000000..a0288bf5 --- /dev/null +++ b/WarehouseMgr/Tnb.WarehouseMgr/WmsPurchaseAndSaleCommonService.cs @@ -0,0 +1,134 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using JNPF.Common.Contracts; +using JNPF.Common.Core.Manager; +using JNPF.Common.Dtos.VisualDev; +using JNPF.FriendlyException; +using SqlSugar; +using Tnb.BasicData.Entities; +using Tnb.Common.Utils; +using Tnb.WarehouseMgr.Entities; +using Tnb.WarehouseMgr.Entities.Consts; +using Tnb.WarehouseMgr.Entities.Dto; +using Tnb.WarehouseMgr.Entities.Entity.Constraints; +using Tnb.WarehouseMgr.Interfaces; + +namespace Tnb.WarehouseMgr +{ + /// + /// 采购收货、销售发货,通用业务类 + /// + /// + public class WmsPurchaseAndSaleCommonService : BaseWareHouseService where TEntity : BaseEntity, IPurchaseAndSaleEntity, IPurchaseAndSaleQueryEntity + { + private readonly ISqlSugarClient _db; + private readonly IUserManager _userManager; + private readonly IWmsPDAScanInStockService _wmsPDAScanInStockService; + private readonly IWmsOutStockService _wmsOutStockService; + private static Dictionary s_materialMap = new(); + + public WmsPurchaseAndSaleCommonService(ISqlSugarRepository repo, IUserManager userManager, IWmsOutStockService? wmsOutStockService = null) + { + _db = repo.AsSugarClient(); + _userManager = userManager; + _wmsOutStockService = wmsOutStockService!; + } + + protected async Task PurchaseAndSaleUpdate(PurchaseAndReceiveUpInput input) + { + if (input == null) throw new ArgumentNullException("input"); + if (input.details == null) throw new ArgumentNullException(nameof(input.details)); + + + var dicMaterialPurchaseArriveQty = input.details.ToDictionary(x => x.material_id, x => x.purchase_arriveqty); + var materialIds = input.details.Select(x => x.material_id).ToList(); + var purchaseDs = await _db.Queryable().Where(it => materialIds.Contains(it.material_id)).ToListAsync(); + + if (purchaseDs?.Count > 0) + { + var errMaterialTipList = new List<(string materialName, decimal purchaseArriveQty, decimal topPurchaseQty)>(); + foreach (var pd in purchaseDs) + { + pd.purchase_prqty += dicMaterialPurchaseArriveQty.ContainsKey(pd.material_id) ? dicMaterialPurchaseArriveQty[pd.material_id] : 0; + var pdInput = input.details.Find(x => x.material_id == pd.material_id); + if (pdInput != null) + { + var topPurchaseQty = pd.purchase_qty - pd.purchase_prqty; + if (pdInput.purchase_arriveqty > topPurchaseQty) + { + if (s_materialMap.ContainsKey(pdInput.material_id) && s_materialMap[pdInput.material_id] != null) + { + errMaterialTipList.Add((s_materialMap[pdInput.material_id].ToString()!, pdInput.purchase_arriveqty, topPurchaseQty)); + continue; + } + } + } + if (pd.purchase_prqty >= pd.purchase_qty) + { + pd.line_status = WmsWareHouseConst.BILLSTATUS_COMPLETE_ID; + } + else + { + pd.line_status = WmsWareHouseConst.BILLSTATUS_ON_ID; + } + } + if (errMaterialTipList.Count > 0) + { + var errMsgList = new List(); + if (typeof(TEntity) == typeof(WmsPurchaseD)) + { + errMsgList = errMaterialTipList.Select(x => $"物料:{x.materialName},实际收货数:{x.purchaseArriveQty}已超出可收货数:{x.topPurchaseQty}").ToList(); + } + else + { + errMsgList = errMaterialTipList.Select(x => $"物料:{x.materialName},实际发货数:{x.purchaseArriveQty}已超出可发货数:{x.topPurchaseQty}").ToList(); + } + var errMsg = string.Join("\r\n", errMsgList); + throw new AppFriendlyException(errMsg, 500); + } + + purchaseDs.ForEach(x => + { + x.modify_id = _userManager.UserId; + x.modify_time = DateTime.Now; + }); + await _db.Updateable(purchaseDs).ExecuteCommandAsync(); + if (purchaseDs.All(x => x.line_status == WmsWareHouseConst.BILLSTATUS_COMPLETE_ID)) + { + var purchase = await _db.Queryable().FirstAsync(it => it.bill_code == input.bill_code); + if (purchase != null) + { + purchase.status = WmsWareHouseConst.BILLSTATUS_COMPLETE_ID; + purchase.modify_id = _userManager.UserId; + purchase.modify_time = DateTime.Now; + await _db.Updateable(purchase).UpdateColumns(it => it.status).ExecuteCommandAsync(); + } + } + } + VisualDevModelDataCrInput visualDevModelDataInput = new(); + visualDevModelDataInput.data = PocoToDictionary.ToDictionary(input) as Dictionary; + if (_wmsOutStockService != null) + { + await _wmsOutStockService.OutStockApplyFor(visualDevModelDataInput); + } + + return await Task.FromResult(true); + } + + protected async Task> GetDetailsByPkId(string pkId) + { + if (s_materialMap.Count == 0) + { + s_materialMap = await _db.Queryable().ToDictionaryAsync(x => x.id, x => x.name); + } + var list = await _db.Queryable().Where(it => it.bill_id == pkId) + .Mapper(it => it.material_name = s_materialMap.ContainsKey(it.material_id) ? s_materialMap[it.material_id]?.ToString() ?? "" : "") + .ToListAsync(); + return list; + + } + } +} diff --git a/WarehouseMgr/Tnb.WarehouseMgr/WmsPurchaseService.cs b/WarehouseMgr/Tnb.WarehouseMgr/WmsPurchaseService.cs new file mode 100644 index 00000000..293ffdb2 --- /dev/null +++ b/WarehouseMgr/Tnb.WarehouseMgr/WmsPurchaseService.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using JNPF.Common.Core.Manager; +using JNPF.Common.Dtos.VisualDev; +using JNPF.Common.Security; +using JNPF.DependencyInjection; +using JNPF.FriendlyException; +using JNPF.Logging; +using JNPF.VisualDev; +using Mapster; +using Microsoft.AspNetCore.Mvc; +using Newtonsoft.Json; +using NPOI.OpenXmlFormats; +using NPOI.OpenXmlFormats.Dml.Diagram; +using SqlSugar; +using Tnb.BasicData.Entities; +using Tnb.Common.Utils; +using Tnb.WarehouseMgr.Entities; +using Tnb.WarehouseMgr.Entities.Consts; +using Tnb.WarehouseMgr.Entities.Dto; +using Tnb.WarehouseMgr.Entities.Dto.Inputs; +using Tnb.WarehouseMgr.Interfaces; + +namespace Tnb.WarehouseMgr +{ + /// + /// 采购收货 + /// + [OverideVisualDev(ModuleConsts.MODULE_WMSPURCHASE_ID)] + public class WmsPurchaseService : WmsPurchaseAndSaleCommonService + { + private readonly ISqlSugarClient _db; + private readonly IUserManager _userManager; + public WmsPurchaseService(ISqlSugarRepository repo, IUserManager userManager) + : base(repo, userManager) + { + _db = repo.AsSugarClient(); + _userManager = userManager; + } + + private async Task xxx(VisualDevModelDataCrInput input) + { + PurchaseAndReceiveUpInput input2 = new(); + var input3 = input.data.ToObject(); + input3.details = input.data["tablefield177"].ToObject>(); + var sss = JsonConvert.SerializeObject(input3); + return await Task.FromResult(sss); + } + + /// + /// 采购收货 + /// + /// + /// + [HttpPost] + public async Task Purchase(PurchaseAndReceiveUpInput input) + { + var blFlag = true; + try + { + await _db.Ado.BeginTranAsync(); + + blFlag = await PurchaseAndSaleUpdate(input); + if (blFlag) + { + var instock = input.Adapt(); + instock.id = SnowflakeIdHelper.NextId(); + instock.create_id = _userManager.UserId; + instock.create_time = DateTime.Now; + instock.org_id = _userManager.User.OrganizeId; + await _db.Insertable(instock).ExecuteCommandAsync(); + + var instockD = input.details.Adapt(); + instockD.create_id = _userManager.UserId; + instockD.create_time = DateTime.Now; + instockD.org_id = _userManager.User.OrganizeId; + await _db.Insertable(instockD).ExecuteCommandAsync(); + } + + await _db.Ado.CommitTranAsync(); + } + catch (Exception ex) + { + blFlag = false; + await _db.Ado.RollbackTranAsync(); + Log.Error("采购收货失败", ex); + throw; + } + return await Task.FromResult(blFlag); + } + /// + /// 根据主表Id获取采购收货明细 + /// + /// 主表Id + /// + [HttpGet("id")] + public async Task GetPurchaseDetailByBillId(string id) + { + return await GetDetailsByPkId(id); + } + } +} diff --git a/WarehouseMgr/Tnb.WarehouseMgr/WmsSaleService.cs b/WarehouseMgr/Tnb.WarehouseMgr/WmsSaleService.cs new file mode 100644 index 00000000..4c59a752 --- /dev/null +++ b/WarehouseMgr/Tnb.WarehouseMgr/WmsSaleService.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using JNPF.Common.Core.Manager; +using Microsoft.AspNetCore.Mvc; +using SqlSugar; +using Tnb.WarehouseMgr.Entities; +using Tnb.WarehouseMgr.Entities.Dto; +using Tnb.WarehouseMgr.Interfaces; + +namespace Tnb.WarehouseMgr +{ + /// + /// 销售发货 + /// + public class WmsSaleService : WmsPurchaseAndSaleCommonService + { + public WmsSaleService(ISqlSugarRepository repo, IUserManager userManager, IWmsOutStockService wmsOutStockService) + : base(repo, userManager, wmsOutStockService: wmsOutStockService) + { + + } + + [HttpPost] + public async Task Sale(PurchaseAndReceiveUpInput input) + { + return await PurchaseAndSaleUpdate(input); + } + + [HttpGet("id")] + public async Task GetSaleDetailsByBillId(string id) + { + return await GetDetailsByPkId(id); + } + + } +} diff --git a/common/Tnb.Common/Utils/PocoToDictionary.cs b/common/Tnb.Common/Utils/PocoToDictionary.cs new file mode 100644 index 00000000..46a13eb2 --- /dev/null +++ b/common/Tnb.Common/Utils/PocoToDictionary.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace Tnb.Common.Utils +{ + public static class PocoToDictionary + { + private static readonly MethodInfo AddToDicitonaryMethod = typeof(IDictionary).GetMethod("Add"); + private static readonly ConcurrentDictionary>> Converters = new ConcurrentDictionary>>(); + private static readonly ConstructorInfo DictionaryConstructor = typeof(Dictionary).GetConstructors().FirstOrDefault(c => c.IsPublic && !c.GetParameters().Any()); + + public static IDictionary ToDictionary(this object obj) => obj == null ? null : Converters.GetOrAdd(obj.GetType(), o => + { + var outputType = typeof(IDictionary); + var inputType = obj.GetType(); + var inputExpression = Expression.Parameter(typeof(object), "input"); + var typedInputExpression = Expression.Convert(inputExpression, inputType); + var outputVariable = Expression.Variable(outputType, "output"); + var returnTarget = Expression.Label(outputType); + var body = new List + { + Expression.Assign(outputVariable, Expression.New(DictionaryConstructor)) + }; + body.AddRange( + from prop in inputType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy) + where prop.CanRead //&& (prop.PropertyType.IsPrimitive || prop.PropertyType == typeof(string)) + let getExpression = Expression.Property(typedInputExpression, prop.GetMethod) + let convertExpression = Expression.Convert(getExpression, typeof(object)) + select Expression.Call(outputVariable, AddToDicitonaryMethod, Expression.Constant(prop.Name), convertExpression)); + body.Add(Expression.Return(returnTarget, outputVariable)); + body.Add(Expression.Label(returnTarget, Expression.Constant(null, outputType))); + + var lambdaExpression = Expression.Lambda>>( + Expression.Block(new[] { outputVariable }, body), + inputExpression); + + return lambdaExpression.Compile(); + })(obj); + } +}