Murphy 2 роки тому
батько
коміт
bcf84388f7
22 змінених файлів з 1305 додано та 408 видалено
  1. 69 0
      MicroServices/Business/Business.Application.Contracts/Dto/BindingSubstituteDto.cs
  2. 1 1
      MicroServices/Business/Business.Application.Contracts/Dto/LineScheduledDto.cs
  3. 1 1
      MicroServices/Business/Business.Application.Contracts/Dto/LineStartDto.cs
  4. 109 0
      MicroServices/Business/Business.Application.Contracts/Dto/SubstituteDto.cs
  5. 20 0
      MicroServices/Business/Business.Application.Contracts/Dto/WorkOrdMstDto.cs
  6. 6 0
      MicroServices/Business/Business.Application.Contracts/ResourceExamineManagement/Dto/BomChildExamineDto.cs
  7. 16 2
      MicroServices/Business/Business.Application.Contracts/ResourceExamineManagement/IResourceExamineAppService.cs
  8. 62 61
      MicroServices/Business/Business.Application/ResourceExamineManagement/CalcBomViewAppService.cs
  9. 6 0
      MicroServices/Business/Business.Application/ResourceExamineManagement/PretreatmentAppService.cs
  10. 438 269
      MicroServices/Business/Business.Application/ResourceExamineManagement/ProductionScheduleAppService.cs
  11. 420 71
      MicroServices/Business/Business.Application/ResourceExamineManagement/ResourceExamineAppService.cs
  12. 6 0
      MicroServices/Business/Business.Domain/MongoDB/MES/IC/mo_ic_bom_child.cs
  13. 7 0
      MicroServices/Business/Business.Domain/MongoDB/SRM/mo_srm_pr_main.cs
  14. 68 0
      MicroServices/Business/Business.Domain/MongoDB/SRM/mo_srm_purchase.cs
  15. 6 0
      MicroServices/Business/Business.Domain/StructuredDB/Bang/b_bom_child_examine.cs
  16. 6 0
      MicroServices/Business/Business.Domain/StructuredDB/Bang/b_bom_pretreatment.cs
  17. 6 0
      MicroServices/Business/Business.Domain/StructuredDB/MES/IC/PurOrdMaster.cs
  18. 6 0
      MicroServices/Business/Business.Domain/StructuredDB/MES/IC/ic_bom_child.cs
  19. 6 0
      MicroServices/Business/Business.Domain/StructuredDB/Production/WorkOrdRouting.cs
  20. 6 0
      MicroServices/Business/Business.Domain/StructuredDB/SRM/srm_pr_main.cs
  21. 13 0
      MicroServices/Business/Business.Domain/StructuredDB/SRM/srm_purchase.cs
  22. 27 3
      MicroServices/Business/Business.HttpApi/Controllers/ResourceExamineController.cs

+ 69 - 0
MicroServices/Business/Business.Application.Contracts/Dto/BindingSubstituteDto.cs

@@ -0,0 +1,69 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Business.Dto
+{
+    public class BindingSubstituteDto
+    {
+        /// <summary>
+        /// BOM主键
+        /// </summary>
+        public long id { get; set; }
+
+        /// <summary>
+        /// 替代方案编码
+        /// </summary>
+        public string bom_number { get; set; }
+
+        /// <summary>
+        /// bom明细
+        /// </summary>
+        public List<BomDetails> bomDetail { get; set; }
+
+        /// <summary>
+        /// 租户ID
+        /// </summary>
+        public long? tenant_id { get; set; }
+
+        /// <summary>
+        /// 公司ID
+        /// </summary>
+        public long? company_id { get; set; }
+
+        /// <summary>
+        /// 工厂ID
+        /// </summary>
+        public long? factory_id { get; set; }
+
+        // <summary>
+        /// 用户id
+        /// </summary>
+        public long create_by { get; set; }
+
+        // <summary>
+        /// 用户名称
+        /// </summary>
+        public string create_by_name { get; set; }
+    }
+
+    public class BomDetails
+    {
+        /// <summary>
+        /// 替代明细主键
+        /// </summary>
+        public long? id { get; set; }
+
+        /// <summary>
+        /// 替代料编码
+        /// </summary>
+        public string icitem_number { get; set; }
+
+        /// <summary>
+        /// 替代方案
+        /// </summary>
+        public string substitute_code { get; set; }
+    }
+}

+ 1 - 1
MicroServices/Business/Business.Application.Contracts/Dto/LineScheduledDto.cs

@@ -22,7 +22,7 @@ namespace Business.Dto
         public DateTime EndTime { get; set; }
 
         /// <summary>
-        /// 有效生产时长(小时)
+        /// 有效生产时长(分钟)
         /// </summary>
         public decimal EffTime { get; set; }
 

+ 1 - 1
MicroServices/Business/Business.Application.Contracts/Dto/LineStartDto.cs

@@ -27,7 +27,7 @@ namespace Business.Dto
         public int Op { get; set; }
 
         /// <summary>
-        /// 产线准备时间
+        /// 产线准备时间(小时)
         /// </summary>
         public decimal setupTime { get; set; }
 

+ 109 - 0
MicroServices/Business/Business.Application.Contracts/Dto/SubstituteDto.cs

@@ -0,0 +1,109 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Business.Dto
+{
+    public class SubstituteDto
+    {
+        /// <summary>
+        /// 替代方案主键
+        /// </summary>
+        public long? id { get; set; }
+
+        /// <summary>
+        /// 替代方案编码
+        /// </summary>
+        public string scode { get; set; }
+
+        /// <summary>
+        /// 替代策略
+        /// </summary>
+        public int sstrategy { get; set; }
+
+        /// <summary>
+        /// 替代方式
+        /// </summary>
+        public int smode { get; set; }
+
+        /// <summary>
+        /// 替代明细组
+        /// </summary>
+        public List<SubstituteDtlDto> srows { get; set; }
+
+        /// <summary>
+        /// 租户ID
+        /// </summary>
+        public long? tenant_id { get; set; }
+
+        /// <summary>
+        /// 公司ID
+        /// </summary>
+        public long? company_id { get; set; }
+
+        /// <summary>
+        /// 工厂ID
+        /// </summary>
+        public long? factory_id { get; set; }
+
+        // <summary>
+        /// 用户id
+        /// </summary>
+        public long create_by { get; set; }
+
+        // <summary>
+        /// 用户名称
+        /// </summary>
+        public string create_by_name { get; set; }
+    }
+
+    public class SubstituteDtlDto
+    {
+        /// <summary>
+        /// 替代明细主键
+        /// </summary>
+        public long? id { get; set; }
+
+        /// <summary>
+        /// 替代分组主键
+        /// </summary>
+        public long? field_dfdfdd94566d9724e8e148283fdb2b61 { get; set; }
+
+        /// <summary>
+        /// 替代明细主键
+        /// </summary>
+        public long? icitem_id { get; set; }
+
+        /// <summary>
+        /// 替代料编码
+        /// </summary>
+        public string icitem_number { get; set; }
+
+        /// <summary>
+        /// 分组名称
+        /// </summary>
+        public string substitute_code { get; set; }
+
+        /// <summary>
+        /// 替代数量
+        /// </summary>
+        public decimal? replace_qty { get; set; }
+
+        /// <summary>
+        /// 顺序
+        /// </summary>
+        public int? seq { get; set; }
+
+        /// <summary>
+        /// 群组优先级
+        /// </summary>
+        public int? field_f8988ed2955a264f8f762faaed2c5f6a { get; set; }
+
+        /// <summary>
+        /// 是否标准件
+        /// </summary>
+        public string field_83817a9f5a15a4f78686105c694b0a39 { get; set; }
+    }
+}

+ 20 - 0
MicroServices/Business/Business.Application.Contracts/Dto/WorkOrdMstDto.cs

@@ -16,6 +16,16 @@ namespace Business.Dto
         /// </summary>
         public string WorkOrd { get; set; }
 
+        /// <summary>
+        /// 工单计划开始时间
+        /// </summary>
+        public DateTime OrdDate { get; set; }
+
+        /// <summary>
+        /// 特殊工单产线
+        /// </summary>
+        public string ProdLine { get; set; }
+
         /// <summary>
         /// 物料编号
         /// </summary>
@@ -45,5 +55,15 @@ namespace Business.Dto
         /// 工序
         /// </summary>
         public int Op { get; set; }
+
+        /// <summary>
+        /// 工序清场时长(分钟)
+        /// </summary>
+        public decimal WaitTime { get; set; }
+
+        /// <summary>
+        /// 工单计划开始时间
+        /// </summary>
+        public DateTime PlanDate { get; set; }
     }
 }

+ 6 - 0
MicroServices/Business/Business.Application.Contracts/ResourceExamineManagement/Dto/BomChildExamineDto.cs

@@ -260,6 +260,11 @@ namespace Business.ResourceExamineManagement.Dto
         /// 是否使用此物料
         /// </summary>
         public bool is_use { get; set; }
+
+        /// <summary>
+        /// 工序
+        /// </summary>
+        public int Op { get; set; }
     }
 
     /// <summary>
@@ -492,6 +497,7 @@ namespace Business.ResourceExamineManagement.Dto
         /// 加工单位编码
         /// </summary>
         public string? production_unit_code { get; set; }
+
     }
 
 }

+ 16 - 2
MicroServices/Business/Business.Application.Contracts/ResourceExamineManagement/IResourceExamineAppService.cs

@@ -17,9 +17,9 @@ namespace Business.ResourceExamineManagement
         /// <summary>
         /// 生产排产
         /// </summary>
-        /// <param name="workOrds"></param>
+        /// <param name="domain"></param>
         /// <returns></returns>
-        Task<string> ProductionSchedule(string workOrds, string domain);
+        Task<string> ProductionSchedule(string domain);
 
         /// <summary>
         /// 下达领料
@@ -105,6 +105,20 @@ namespace Business.ResourceExamineManagement
         /// <returns></returns>
         Task<string> ProduceWorkOrdKittingCheck(string workord, string domain, string userAccount);
 
+        /// <summary>
+        /// 替代方案保存
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        Task<string> SubstituteSave(SubstituteDto dto);
+
+        /// <summary>
+        /// BOM关联替代方案
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        Task<string> BindingSubstitute(BindingSubstituteDto dto);
+
         /// <summary>
         /// 更新补货模型月度参数
         /// </summary>

+ 62 - 61
MicroServices/Business/Business.Application/ResourceExamineManagement/CalcBomViewAppService.cs

@@ -1225,81 +1225,82 @@ namespace Business.ResourceExamineManagement
         private SRMPRDto CreateSRMPR(BomChildExamineDto returnlist, long? companyId, long factoryid, long bangId, int orderType, List<ICItemLeadTimeDto> iCItemLeadTimes, List<mo_srm_purchase> supplierList, List<mo_ic_item> planList, crm_seorderentry sentrys)
         {
             SRMPRDto sRMPR = new SRMPRDto();
-            var supplier = supplierList.Where(x => x.icitem_id == returnlist.item_id).ToList();//默认取第一个供应商
+            var supplier = supplierList.OrderBy(s => s.quota_priority).FirstOrDefault();//默认取配额优先级
             var plan = planList.Find(x => x.mysql_id == returnlist.item_id);
             sRMPR.srm_Pr_Main = new List<mo_srm_pr_main>();
-            if (!supplier.Any() || plan == null)
+            if (supplier == null || plan == null)
             {
                 sRMPR.lastStartTmie = DateTime.Now.AddDays(7);//默认采购提前期
                 return sRMPR;
                 //throw new NotImplementedException("未找到物料ic_factory_details或ic_item_pur或ic_plan信息!");
             }
-
-            supplier.ForEach(x =>
+            mo_srm_pr_main srm_Pr = new mo_srm_pr_main();
+            srm_Pr.GenerateNewId(help.NextId());
+            srm_Pr.mysql_id = help.NextId();
+            srm_Pr.pr_billno = returnlist.erp_cls == 2 ? getOrderNum("WWPR") : getOrderNum("PR");//pr单号
+            if (mes_morder != null)
             {
-                x.netpurchase_price = rnd.Next(1, 100);
-                x.taxrate = 0.13m;//固定13%增值税
-                mo_srm_pr_main srm_Pr = new mo_srm_pr_main();
-                srm_Pr.GenerateNewId(help.NextId());
-                srm_Pr.mysql_id = help.NextId();
-                srm_Pr.pr_billno = returnlist.erp_cls == 2 ? getOrderNum("WWPR") : getOrderNum("PR");//pr单号
-                if (mes_morder != null)
-                {
-                    srm_Pr.pr_mono = mes_morder.morder_no;//关联工单号
-                    srm_Pr.entity_id = 1;//工单行号
-                }
-                srm_Pr.pr_purchaseid = x.supplier_id;//供应商id  
-                srm_Pr.pr_purchasenumber = x.supplier_number;//供应商编码
-                srm_Pr.pr_purchasename = x.supplier_name;//供应商名称
-                srm_Pr.pr_purchaser = x.purcher;//采购员
-                srm_Pr.pr_purchaser_num = "";//采购员工号(采购信息表)
-                srm_Pr.pr_rqty = returnlist.lack_qty;//需求数量
-                srm_Pr.pr_aqty = returnlist.lack_qty;//申请数量
-                srm_Pr.pr_sqty = returnlist.lack_qty;//建议数量
-                srm_Pr.icitem_id = returnlist.item_id;//物料id
-                srm_Pr.icitem_name = returnlist.item_name;//物料名称
-                srm_Pr.num = returnlist.num;
-                var tomorrow = DateTime.Now.Date.AddDays(1);
-                srm_Pr.pr_order_type = 1;//单据类型
-                srm_Pr.pr_ssend_date = tomorrow;//系统建议下单日期
-                srm_Pr.pr_sarrive_date = DateTime.Now.AddDays((double)plan.order_leadtime).AddDays((double)plan.transportation_leadtime);//系统建议到达日期(建议到货日期)
-                srm_Pr.pr_psend_date = tomorrow;//计划下单日期
-                srm_Pr.pr_parrive_date = DateTime.Now.AddDays((double)plan.order_leadtime).AddDays((double)plan.transportation_leadtime);//计划到达日期
-                srm_Pr.pr_rarrive_date = DateTime.Now.AddDays((double)plan.order_leadtime).AddDays((double)plan.transportation_leadtime);//需求到货日期
-                srm_Pr.pr_sysprice = returnlist.lack_qty * x.netpurchase_price * (1 + x.taxrate);//系统价格(含税)
-                srm_Pr.pr_orderprice = returnlist.lack_qty * x.netpurchase_price * (1 + x.taxrate);//订单价格(含税)
-                srm_Pr.pr_price = x.netpurchase_price;//采购净价(不含税)
-                srm_Pr.pr_rate = x.taxrate;//税率
-                srm_Pr.pr_unit = returnlist.unit;//单位
-                srm_Pr.state = 1;//状态
-                srm_Pr.old_apply_aqty = 0;//已申请数量
-                srm_Pr.pr_type = orderType;//申请类型
-                srm_Pr.currencytype = x.currency_type == null ? 1 : x.currency_type.Value;//币种
-                srm_Pr.secInv_ratio = plan.secinv_ratio;//安全库存触发采购比例
-                srm_Pr.tenant_id = companyId.GetValueOrDefault();
-                srm_Pr.company_id = companyId;
-                srm_Pr.factory_id = factoryid;
-                srm_Pr.bang_id = bangId;
-                if (sentrys != null)
-                {
-                    srm_Pr.sentry_id = sentrys.Id;
-                }
-                //_srm_pr_main.InsertOne(srm_Pr);
-                decimal? totalLeadTime = plan.transportation_leadtime + plan.stock_leadtime + plan.production_leadtime + plan.order_leadtime;
-                srm_Pr.totalLeadTime= totalLeadTime;
-                srm_Pr.create_time = DateTime.Now;
-                srm_Pr.create_by_name = "admin";
-                srm_Pr.update_time = DateTime.Now;
-                srm_Pr.update_by_name = "admin";
-                sRMPR.srm_Pr_Main.Add(srm_Pr);
-            });
+                srm_Pr.pr_mono = mes_morder.morder_no;//关联工单号
+                srm_Pr.entity_id = 1;//工单行号
+            }
+            srm_Pr.IsRequireGoods = supplier.IsRequireGoods;
+            srm_Pr.pr_purchaseid = supplier.supplier_id;//供应商id  
+            srm_Pr.pr_purchasenumber = supplier.supplier_number;//供应商编码
+            srm_Pr.pr_purchasename = supplier.supplier_name;//供应商名称
+            srm_Pr.pr_purchaser = supplier.purcher;//采购员
+            srm_Pr.pr_purchaser_num = "";//采购员工号(采购信息表)
+                                         //数量圆整 按最小包装量向上圆整
+            decimal qty = Math.Ceiling(returnlist.lack_qty / (supplier.packaging_qty.GetValueOrDefault() == 0 ? 1 : supplier.packaging_qty.GetValueOrDefault()));
+            //判断最小起订量
+            qty = qty > supplier.qty_min ? qty : supplier.qty_min.GetValueOrDefault();
+            srm_Pr.pr_rqty = returnlist.lack_qty;//需求数量
+            srm_Pr.pr_aqty = qty;//申请数量
+            srm_Pr.pr_sqty = qty;//建议数量
+            srm_Pr.icitem_id = returnlist.item_id;//物料id
+            srm_Pr.icitem_name = returnlist.item_name;//物料名称
+            srm_Pr.num = returnlist.num;
+            var tomorrow = DateTime.Now.Date.AddDays(1);
+            srm_Pr.pr_order_type = 1;//单据类型
+            srm_Pr.pr_ssend_date = tomorrow;//系统建议下单日期
+            srm_Pr.pr_sarrive_date = DateTime.Now.AddDays((double)plan.order_leadtime).AddDays((double)plan.transportation_leadtime);//系统建议到达日期(建议到货日期)
+            srm_Pr.pr_psend_date = tomorrow;//计划下单日期
+            srm_Pr.pr_parrive_date = DateTime.Now.AddDays((double)plan.order_leadtime).AddDays((double)plan.transportation_leadtime);//计划到达日期
+            srm_Pr.pr_rarrive_date = DateTime.Now.AddDays((double)plan.order_leadtime).AddDays((double)plan.transportation_leadtime);//需求到货日期
+            srm_Pr.pr_sysprice = supplier.order_price;//系统价格(含税)
+            srm_Pr.pr_orderprice = qty * supplier.order_price;//订单价格(含税)
+            srm_Pr.pr_price = supplier.netpurchase_price;//采购净价(不含税)
+            /*srm_Pr.pr_sysprice = qty * x.netpurchase_price * (1 + x.taxrate);//系统价格(含税)
+            srm_Pr.pr_orderprice = qty * x.netpurchase_price * (1 + x.taxrate);//订单价格(含税)
+            srm_Pr.pr_price = x.netpurchase_price;//采购净价(不含税)*/
+            srm_Pr.pr_rate = supplier.taxrate;//税率
+            srm_Pr.pr_unit = returnlist.unit;//单位
+            srm_Pr.state = 1;//状态
+            srm_Pr.old_apply_aqty = 0;//已申请数量
+            srm_Pr.pr_type = orderType;//申请类型
+            srm_Pr.currencytype = supplier.currency_type == null ? 1 : supplier.currency_type.Value;//币种
+            srm_Pr.secInv_ratio = plan.secinv_ratio;//安全库存触发采购比例
+            srm_Pr.tenant_id = companyId.GetValueOrDefault();
+            srm_Pr.company_id = companyId;
+            srm_Pr.factory_id = factoryid;
+            srm_Pr.bang_id = bangId;
+            if (sentrys != null)
+            {
+                srm_Pr.sentry_id = sentrys.Id;
+            }
+            decimal? totalLeadTime = plan.transportation_leadtime + plan.stock_leadtime + plan.production_leadtime + plan.order_leadtime;
+            srm_Pr.totalLeadTime = totalLeadTime;
+            srm_Pr.create_time = DateTime.Now;
+            srm_Pr.create_by_name = "admin";
+            srm_Pr.update_time = DateTime.Now;
+            srm_Pr.update_by_name = "admin";
+            sRMPR.srm_Pr_Main.Add(srm_Pr);
             if (sRMPR.srm_Pr_Main.Any())
             {
                 sRMPR.srm_Pr_Main.OrderBy(x => x.totalLeadTime.GetValueOrDefault()).ThenBy(x => x.pr_orderprice.GetValueOrDefault()).First().isbestoptions = true;
             }
             sRMPR.item_no = returnlist.num;
             sRMPR.orderentry_id = returnlist.sentry_id;
-            sRMPR.lastStartTmie = DateTime.Now.AddDays((double)(sRMPR.srm_Pr_Main.MinBy(x=>x.totalLeadTime).totalLeadTime.GetValueOrDefault()+plan.clean_leadtime.GetValueOrDefault()));//加上提前期和备料期,得到齐套时间
+            sRMPR.lastStartTmie = DateTime.Now.AddDays((double)(sRMPR.srm_Pr_Main.MinBy(x => x.totalLeadTime).totalLeadTime.GetValueOrDefault() + plan.clean_leadtime.GetValueOrDefault()));//加上提前期和备料期,得到齐套时间
             return sRMPR;
         }
         // 生成订单编号 字母+年月日+8位随机数+时间戳

+ 6 - 0
MicroServices/Business/Business.Application/ResourceExamineManagement/PretreatmentAppService.cs

@@ -50,6 +50,7 @@ namespace Business.ResourceExamineManagement
             dto.haveicsubs = 0;
             dto.substitute_code = "";
             dto.icitem_ids = "";
+            dto.Op = 0;
             int type = 0;
             GetBomList(bomlist, bomchildlist, icitemlist, dto, returnlist, type);
             return returnlist;
@@ -124,6 +125,7 @@ namespace Business.ResourceExamineManagement
                     cdto.item_id = childBom.icitem_id;
                     cdto.bom_id = childBom.mysql_id;
                     cdto.bom_number = childBom.bom_number;
+                    cdto.Op = c.Op;
                     //递归寻找子级
                     GetBomList(bomlist, bomchildlist, icitemlist, cdto, returnlist, type);
                 }
@@ -156,6 +158,7 @@ namespace Business.ResourceExamineManagement
                         childDto.icitem_ids = c.icitem_ids;
                         childDto.type = type;
                         childDto.item_number = icitem.number;
+                        childDto.Op = c.Op;
                         returnlist.Add(childDto);
                     }
                 }
@@ -194,6 +197,7 @@ namespace Business.ResourceExamineManagement
                 if (sl != null)
                 {
                     var sall = suballlist.Where(s => s.substitute_group_id == sl.mysql_id).ToList();
+                    //var bz = sall.Where(s => s.main_material.GetValueOrDefault() == 1).FirstOrDefault();
                     foreach (var sal in sall)
                     {
                         var sadl = subdtllist.Where(s => s.substitute_group_id == sal.mysql_id).OrderBy(c => c.seq).ToList();
@@ -269,6 +273,8 @@ namespace Business.ResourceExamineManagement
             dto.substitute_mode = sl.substitute_mode == null ? 0 : sl.substitute_mode.Value;//替代方式
             dto.type = type;
             dto.substitute_all_num = sal.order_num;//群组优先级
+            //先按标准料的工序给替代料赋值。
+            dto.Op = toDto.Op;
             if (bom != null)
             {
                 dto.bom_id = bom.mysql_id;

Різницю між файлами не показано, бо вона завелика
+ 438 - 269
MicroServices/Business/Business.Application/ResourceExamineManagement/ProductionScheduleAppService.cs


+ 420 - 71
MicroServices/Business/Business.Application/ResourceExamineManagement/ResourceExamineAppService.cs

@@ -146,18 +146,33 @@ namespace Business.ResourceExamineManagement
         private IRepository<b_purchase_occupy, long> _mysql_purchase_occupy;
 
         /// <summary>
-        /// 替代群组
+        /// 替代方案
         /// </summary>
         private readonly IRepository<mo_ic_substitute,long> _ic_substitute;
         /// <summary>
-        /// 替代群组
+        /// 替代方案群组
         /// </summary>
         private readonly IRepository<mo_ic_substitute_group,long> _ic_substitute_group;
         /// <summary>
-        /// 替代群组
+        /// 替代明细
         /// </summary>
         private readonly IRepository<mo_ic_substitute_group_detail,long> _ic_substitute_group_detail;
 
+        /// <summary>
+        /// 替代方案
+        /// </summary>
+        private readonly IRepository<ic_substitute, long> _mysql_ic_substitute;
+
+        /// <summary>
+        /// 替代方案群组
+        /// </summary>
+        private readonly IRepository<ic_substitute_group, long> _mysql_ic_substitute_group;
+
+        /// <summary>
+        /// 替代明细
+        /// </summary>
+        private readonly IRepository<ic_substitute_group_detail, long> _mysql_ic_substitute_group_detail;
+
         /// <summary>
         /// 生产工单主表
         /// </summary>
@@ -453,6 +468,9 @@ namespace Business.ResourceExamineManagement
             ISqlRepository<ItemPackMaster> itemPackMaster,
             ISqlRepository<GeneralizedCodeMaster> generalizedCodeMaster,
             ISqlRepository<ScheduleResultOpMaster> scheduleResultOpMaster,
+            IRepository<ic_substitute, long> mysql_ic_substitute,
+            IRepository<ic_substitute_group, long> mysql_ic_substitute_group,
+            IRepository<ic_substitute_group_detail, long> mysql_ic_substitute_group_detail,
             IRepository<ReplenishmentModel, long> replenishmentModel,
             IRepository<DomesticTerminalFcst, long> domesticTerminalFcst,
             ISqlRepository<ASNBOLShipperDetail> ASNBOLShipperDetail,
@@ -481,6 +499,9 @@ namespace Business.ResourceExamineManagement
             _ic_substitute = ic_substitute;
             _ic_substitute_group = ic_substitute_group;
             _ic_substitute_group_detail = ic_substitute_group_detail;
+            _mysql_ic_substitute = mysql_ic_substitute;
+            _mysql_ic_substitute_group = mysql_ic_substitute_group;
+            _mysql_ic_substitute_group_detail = mysql_ic_substitute_group_detail;
             _mes_morder = mes_morder;
             _mes_moentry = mes_moentry;
             _mes_mooccupy = mes_mooccupy;
@@ -990,24 +1011,24 @@ namespace Business.ResourceExamineManagement
             //物料、供应商为相同才允许合并。
             var idList = AnalysisIdList(ids);
             List<srm_pr_main> prlist = _mysql_srm_pr_main.GetListAsync(s => idList.Contains(s.Id)).Result;
-            if (prlist.Where(s => s.state == 0).Count() > 0)
-            {
-                return JsonConvert.SerializeObject("所选包含已关闭采购申请,请重新选择。");
-            }
-            if (prlist.Where(s => s.state == 2).Count() > 0)
-            {
-                return JsonConvert.SerializeObject("所选包含已提交评审采购申请,请重新选择。");
-            }
-            if (prlist.Where(s => s.state == 4).Count() > 0)
-            {
-                return JsonConvert.SerializeObject("所选包含已评审通过采购申请,请重新选择。");
-            }
             if (prlist.Any())
             {
-                var list = prlist.GroupBy(s => new { s.icitem_id, s.pr_purchaseid });
+                if (prlist.Where(s => s.state == 0).Count() > 0)
+                {
+                    return JsonConvert.SerializeObject("所选包含已关闭采购申请,请重新选择。");
+                }
+                if (prlist.Where(s => s.state == 2).Count() > 0)
+                {
+                    return JsonConvert.SerializeObject("所选包含已提交评审采购申请,请重新选择。");
+                }
+                if (prlist.Where(s => s.state == 4).Count() > 0)
+                {
+                    return JsonConvert.SerializeObject("所选包含已评审通过采购申请,请重新选择。");
+                }
+                var list = prlist.GroupBy(s => new { s.icitem_id, s.pr_purchaseid, s.IsRequireGoods });
                 if (list.Count() > 1)
                 {
-                    return JsonConvert.SerializeObject("所选行的物料编码,供应商名称必须相同");
+                    return JsonConvert.SerializeObject("所选行的物料编码、供应商名称、采购类型必须相同");
                 }
             }
             else {
@@ -1036,8 +1057,8 @@ namespace Business.ResourceExamineManagement
             srm_Pr.pr_psend_date = prlist.Min(s => s.pr_psend_date);//计划下单日期
             srm_Pr.pr_parrive_date = prlist.Min(s => s.pr_parrive_date);//计划到达日期
             srm_Pr.pr_rarrive_date = prlist.Min(s => s.pr_rarrive_date);//需求到货日期
-            srm_Pr.pr_sysprice = prlist.Sum(s => s.pr_rqty) * prlist[0].pr_price * (1 + prlist[0].pr_rate);//系统价格(含税)
-            srm_Pr.pr_orderprice = prlist.Sum(s => s.pr_rqty) * prlist[0].pr_price * (1 + prlist[0].pr_rate);//订单价格(含税)
+            //srm_Pr.pr_sysprice = prlist.Sum(s => s.pr_rqty) * prlist[0].pr_price * (1 + prlist[0].pr_rate);//系统价格(含税)
+            srm_Pr.pr_orderprice = prlist.Sum(s => s.pr_aqty) * prlist[0].pr_sysprice;//订单价格(含税)
             /*srm_Pr.icitem_id = returnlist.item_id;//物料id
             srm_Pr.icitem_name = returnlist.item_name;//物料名称
             srm_Pr.pr_order_type = 1;//单据类型
@@ -1091,15 +1112,15 @@ namespace Business.ResourceExamineManagement
             var moPrlist = ObjectMapper.Map<List<srm_pr_main>, List<mo_srm_pr_main>>(prlist);
             foreach (var pr in prlist)
             {
-                bool bl = pr.sentry_id == null;
-                //找到是否生成了新的PR
-                //var newPr = insetPrList.Find(s => s.pr_purchaseid == pr.pr_purchaseid && s.icitem_id == pr.icitem_id && (s.sentry_id == null) == bl);
-                var newPr = insetPrList.Find(s => s.pr_purchaseid == pr.pr_purchaseid && s.icitem_id == pr.icitem_id);
+                bool bl = pr.sentry_id == null;//区分是销售订单和非销售订单的合并。
+                //找到是否生成了新的PR  当前数据是否已经产生合并,则不再合并。
+                var newPr = insetPrList.Find(s => s.pr_purchaseid == pr.pr_purchaseid && s.icitem_id == pr.icitem_id && s.IsRequireGoods == pr.IsRequireGoods && (s.sentry_id == null) == bl);
+                //var newPr = insetPrList.Find(s => s.pr_purchaseid == pr.pr_purchaseid && s.icitem_id == pr.icitem_id);
                 if (newPr == null)
                 {
                     //有多条才进行合并
-                    //var ilist = prlist.Where(s => s.pr_purchaseid == pr.pr_purchaseid && s.icitem_id == pr.icitem_id && (s.sentry_id == null) == bl).ToList();
-                    var ilist = prlist.Where(s => s.pr_purchaseid == pr.pr_purchaseid && s.icitem_id == pr.icitem_id).ToList();
+                    var ilist = prlist.Where(s => s.pr_purchaseid == pr.pr_purchaseid && s.icitem_id == pr.icitem_id && s.IsRequireGoods == pr.IsRequireGoods && (s.sentry_id == null) == bl).ToList();
+                    //var ilist = prlist.Where(s => s.pr_purchaseid == pr.pr_purchaseid && s.icitem_id == pr.icitem_id).ToList();
                     if (ilist.Count > 1)
                     {
                         var icitem = ic_Items.Find(s => s.Id == pr.icitem_id);
@@ -1124,8 +1145,8 @@ namespace Business.ResourceExamineManagement
                         newPr.pr_sarrive_date = newPr.pr_rarrive_date;//系统建议到达日期(建议到货日期)
                         newPr.pr_parrive_date = newPr.pr_rarrive_date;//计划到达日期
                         
-                        newPr.pr_sysprice = newPr.pr_rqty * pr.pr_price * (1 + pr.pr_rate);//系统价格(含税)
-                        newPr.pr_orderprice = newPr.pr_rqty * pr.pr_price * (1 + pr.pr_rate);//订单价格(含税)
+                        //newPr.pr_sysprice = newPr.pr_rqty * pr.pr_price * (1 + pr.pr_rate);//系统价格(含税)
+                        newPr.pr_orderprice = newPr.pr_aqty * pr.pr_sysprice;//订单价格(含税)
                         ilist.ForEach(s => { s.refer_pr_billno = newPr.pr_billno; });
                         insetPrList.Add(newPr);
                         ilist.ForEach(s => { s.state = 0; });
@@ -1286,7 +1307,8 @@ namespace Business.ResourceExamineManagement
             DateTime toTime = new DateTime(2023, 7, 6);
             DateTime starttime = toTime.AddDays(1);
             DateTime endtime = toTime.AddDays(8);
-            List<srm_pr_main> prlist = _mysql_srm_pr_main.GetListAsync(s => s.company_id.ToString() == companyid && s.pr_rarrive_date >= starttime && s.pr_rarrive_date <= endtime && (s.state == 1|| s.state == 2 || s.state == 3)).Result;
+            List<srm_pr_main> prlist = _mysql_srm_pr_main.GetListAsync(s => s.company_id.ToString() == companyid && s.IsRequireGoods == 0 && s.pr_rarrive_date >= starttime &&
+            s.pr_rarrive_date <= endtime && (s.state == 1|| s.state == 2 || s.state == 3)).Result;
 
             if (prlist.Any())
             {
@@ -1308,7 +1330,7 @@ namespace Business.ResourceExamineManagement
                         }
                         if (poaction.polist.Any())
                         {
-                            _businessDbContext.BulkInsert(poaction.polist);
+                            _businessDbContext.BulkInsert(poaction.polist); 
                         }
                         if (poaction.poOccupiesList.Any())
                         {
@@ -1317,6 +1339,7 @@ namespace Business.ResourceExamineManagement
 
                         if (poaction.poMasterList.Any())
                         {
+                            poaction.poMasterList.ForEach(s => { s.ReqBy = "DO"; });
                             _purOrdMaster.Insert(poaction.poMasterList);
                             //快开平台用自增列RecId关联,所以需要插入后再查给明细表赋相应的值
                             List<string> nbrs = poaction.poMasterList.Select(a => a.PurOrd).ToList();
@@ -1332,15 +1355,15 @@ namespace Business.ResourceExamineManagement
                     catch (Exception e)
                     {
                         unitOfWork.Dispose();
-                        new NLogHelper("ResourceExamineAppService").WriteLog("PrApprove", "采购申请单合并失败:" + e.Message, _currentTenant.Id.ToString());
-                        return JsonConvert.SerializeObject("合并失败,请联系管理员。");
+                        new NLogHelper("ResourceExamineAppService").WriteLog("PrAutoApprove", "要货令转采购订单失败:" + e.Message, _currentTenant.Id.ToString());
+                        return JsonConvert.SerializeObject("要货令转采购订单失败,请联系管理员。");
                     }
                 }
                 return JsonConvert.SerializeObject("ok");
             }
             else
             {
-                return JsonConvert.SerializeObject("没有需要审核的采购申请单。");
+                return JsonConvert.SerializeObject("没有需要审核的要货令。");
             }
         }
 
@@ -1351,27 +1374,30 @@ namespace Business.ResourceExamineManagement
         /// <returns></returns>
         public async Task<string> PrApprove(string ids)
         {
-            //物料、供应商为相同才允许合并。
             var idList = AnalysisIdList(ids);
             List<srm_pr_main> prlist = _mysql_srm_pr_main.GetListAsync(s => idList.Contains(s.Id)).Result;
             if (!prlist.Any())
             {
-                return JsonConvert.SerializeObject("所选采购申请单未找到,请刷新界面重新操作。");
+                return JsonConvert.SerializeObject("所选要货令未找到,请刷新界面重新操作。");
             }
             if (prlist.Where(s => s.state == 0).Count() > 0)
             {
-                return JsonConvert.SerializeObject("所选包含已关闭采购申请,请重新选择。");
+                return JsonConvert.SerializeObject("所选包含已关闭要货令,请重新选择。");
             }
             if (prlist.Where(s => s.state == 3).Count() > 0)
             {
-                return JsonConvert.SerializeObject("所选包含评审未通过采购申请,请重新选择。");
+                return JsonConvert.SerializeObject("所选包含评审未通过要货令,请重新选择。");
+            }
+            if (prlist.Where(s => s.IsRequireGoods == 0).Count() > 0)
+            {
+                return JsonConvert.SerializeObject("包含采购申请,不允许与要货令转采购订单。");
             }
             List<srm_purchase> purchaselist = _mysql_srm_purchase.GetListAsync(s => prlist.Select(c => c.icitem_id).Contains(s.icitem_id) && prlist.Select(c => c.pr_purchaseid).Contains(s.supplier_id)).Result;
             List<srm_supplier> itemsupplierList = _mysql_srm_supplier.GetListAsync(s => prlist.Select(c => c.pr_purchaseid).Contains(s.Id)).Result;
             var purclist = purchaselist.GroupBy(s => new { s.supplier_type, s.supplier_id });
             if (purclist.Count() > 1)
             {
-                return JsonConvert.SerializeObject("采购申请单的采购类别必须相同。");
+                return JsonConvert.SerializeObject("要货令的供应类别必须相同。");
             }
             List<ic_item> ic_Items = _mysql_ic_item.GetListAsync(s => prlist.Select(c => c.icitem_id).Contains(s.Id)).Result;
             PoActionListDto poaction = new PoActionListDto();
@@ -1398,6 +1424,7 @@ namespace Business.ResourceExamineManagement
 
                     if (poaction.poMasterList.Any())
                     {
+                        poaction.poMasterList.ForEach(s => { s.ReqBy = "DO"; });
                         _purOrdMaster.Insert(poaction.poMasterList);
                         //快开平台用自增列RecId关联,所以需要插入后再查给明细表赋相应的值
                         List<string> nbrs = poaction.poMasterList.Select(a => a.PurOrd).ToList();
@@ -1413,8 +1440,8 @@ namespace Business.ResourceExamineManagement
                 catch (Exception e)
                 {
                     unitOfWork.Dispose();
-                    new NLogHelper("ResourceExamineAppService").WriteLog("PrApprove", "采购申请单合并失败:" + e.Message, _currentTenant.Id.ToString());
-                    return JsonConvert.SerializeObject("合并失败,请联系管理员。");
+                    new NLogHelper("ResourceExamineAppService").WriteLog("PrApprove", "要货令转采购订单失败:" + e.Message, _currentTenant.Id.ToString());
+                    return JsonConvert.SerializeObject("要货令转采购订单失败,请联系管理员。");
                 }
             }
             return JsonConvert.SerializeObject("ok");
@@ -1525,6 +1552,7 @@ namespace Business.ResourceExamineManagement
                 if (newExm != null)
                 {
                     se.progress = "3";
+                    se.rstate = 1;
                     se.sys_material_date = newExm.sys_material_date;
                     se.sys_capacity_date = newExm.sys_capacity_date;
                     //如果计算记录有工单id,则代表有生成工单,而不是占用计划工单
@@ -1564,8 +1592,9 @@ namespace Business.ResourceExamineManagement
                 moderlist = ObjectMapper.Map<List<mo_mes_morder>, List<mes_morder>>(WriteMorder);
 
                 List<RoutingOpDetail> allRoutings = _routingOpDetail.Select(p => moderlist.Select(m => m.product_code).Contains(p.RoutingCode));
+                List<b_bom_child_examine> childExamineList = _mysql_bom_child_examine.GetListAsync(c => exmResult.Select(x => x.Id).Contains(c.examine_id.GetValueOrDefault())).Result;
                 //同步工单
-                CreateWorkOrdDates(moderlist, allRoutings, workOrds, workOrdRoutings, workOrdDetails);
+                CreateWorkOrdDates(moderlist, allRoutings, workOrds, workOrdRoutings, workOrdDetails, exmResult, childExamineList);
             }
             //当前订单号所关联的最新计算结果里的占用记录
             List<mo_mes_mooccupy> mooccupyList = await _mes_mooccupy.GetListAsync(s => seIds.Contains(s.moo_id_billid.Value) && bangidList.Contains(s.bang_id.Value));
@@ -2062,7 +2091,7 @@ namespace Business.ResourceExamineManagement
                 podetail.netprice = item.pr_price;
                 podetail.netmoney = item.pr_aqty.GetValueOrDefault() * item.pr_price.GetValueOrDefault();
                 podetail.rate = item.pr_rate;
-                podetail.price = item.pr_orderprice / item.pr_aqty;
+                podetail.price = item.pr_sysprice;
                 podetail.total_price = item.pr_orderprice;
                 podetail.taxamount = item.pr_orderprice.GetValueOrDefault() - podetail.netmoney;
                 podetail.plan_qty = item.pr_aqty;
@@ -2131,7 +2160,7 @@ namespace Business.ResourceExamineManagement
                                 srm_Po_Occupy.GenerateNewId(help.NextId());
                                 //srm_Po_Occupy.bang_id = bangid;
                                 srm_Po_Occupy.morder_mo = c.pr_mono;
-                                srm_Po_Occupy.qty = c.pr_aqty;
+                                srm_Po_Occupy.qty = c.pr_rqty;
                                 srm_Po_Occupy.eid = c.sentry_id;
                                 srm_Po_Occupy.polist_id = p.Id;
                                 srm_Po_Occupy.polist_row = p.polist_row;
@@ -2548,6 +2577,7 @@ namespace Business.ResourceExamineManagement
             {
                 List<WorkOrdRouting> alllist = workordRList.Where(s => s.WorkOrd == work).ToList();
                 List<WorkOrdRouting> parentlist = alllist.Where(s => s.WorkOrd == work && s.ParentOp == 0).ToList();
+                //非关键工序也要添加
                 copyList.AddRange(parentlist.Where(s => s.MilestoneOp == false).ToList());
                 GetChildOP(parentlist, alllist, copyList);
             }
@@ -3572,26 +3602,6 @@ namespace Business.ResourceExamineManagement
             return Wildcard.Replace(serialNumber, formData);
         }
 
-        /// <summary>
-        /// 生产排产
-        /// </summary>
-        /// <param name="workOrd"></param>
-        /// <returns></returns>
-        /// <exception cref="NotImplementedException"></exception>
-        public async Task<string> ProductionSchedule(string workOrd,string domain)
-        {
-            List<string> workOrds = workOrd.Split(",").ToList();
-            if (workOrds.Count == 0)
-            {
-                return "没有需要排产的工单。";
-            }
-            //获取工单数据
-            var workOrdMasters = _workOrdMaster.Select(p => workOrds.Contains(p.WorkOrd) && p.Domain == domain);
-            //排产
-            //await _productionScheduleAppService.DoProductSchedule(workOrdMasters, workOrdMasters[0].Domain, 1);
-            return "ok";
-        }
-
         /// <summary>
         /// 生成领料单
         /// </summary>
@@ -3733,7 +3743,7 @@ namespace Business.ResourceExamineManagement
         /// </summary>
         /// <param name="morders"></param>
         /// <param name="allRoutings">工艺路线数据</param>
-        public void CreateWorkOrdDates(List<mes_morder> morders, List<RoutingOpDetail> allRoutings, List<WorkOrdMaster> workOrds, List<WorkOrdRouting> workOrdRoutings, List<WorkOrdDetail> workOrdDetails)
+        public void CreateWorkOrdDates(List<mes_morder> morders, List<RoutingOpDetail> allRoutings, List<WorkOrdMaster> workOrds, List<WorkOrdRouting> workOrdRoutings, List<WorkOrdDetail> workOrdDetails, List<b_examine_result> exmResult, List<b_bom_child_examine> childExamineList)
         {
             //工单主表
             WorkOrdMaster workOrd;
@@ -3784,7 +3794,43 @@ namespace Business.ResourceExamineManagement
                     workOrdRoutings.Add(woRouting);
                 }
 
-                List<ProductStructureMaster> curStructures = GetProductStructure(item.product_code, workOrd.QtyOrded, item.factory_id.ToString());
+                var exm = exmResult.Find(s => s.morder_id == item.Id);
+                if (exm != null)
+                {
+                    var childs = childExamineList.Where(s => s.examine_id == exm.Id && s.is_use == true).ToList();
+                    List<b_bom_child_examine> returnList = new List<b_bom_child_examine>();
+                    GetWorkDetalis(childs.Where(s => s.level == 2).ToList(), returnList, childs);
+                    if (returnList.Any())
+                    {
+                        foreach (var structure in returnList)
+                        {
+                            woDetail = workOrdDetails.Find(s => s.ItemNum == structure.item_number && s.WorkOrd == item.morder_no);
+                            if (woDetail == null)
+                            {
+                                //添加工单的物料信息
+                                woDetail = new WorkOrdDetail();
+                                woDetail.Domain = item.factory_id.ToString();
+                                woDetail.WorkOrd = item.morder_no;
+                                woDetail.Op = structure.Op;
+                                woDetail.ItemNum = structure.item_number;
+                                woDetail.QtyRequired = structure.needCount.GetValueOrDefault();
+                                woDetail.QtyPosted = 0m;
+                                woDetail.QtyReturned = 0m;
+                                woDetail.FrozenBOMQty = structure.needCount.GetValueOrDefault();
+                                woDetail.Status = "";
+                                woDetail.IsActive = true;
+                                woDetail.CreateTime = DateTime.Now;
+                                workOrdDetails.Add(woDetail);
+                            }
+                            else
+                            {
+                                woDetail.QtyRequired += structure.needCount.GetValueOrDefault();
+                                woDetail.FrozenBOMQty += structure.needCount.GetValueOrDefault();
+                            }
+                        }
+                    }
+                }
+                /*List<ProductStructureMaster> curStructures = GetProductStructure(item.product_code, workOrd.QtyOrded, item.factory_id.ToString());
                 foreach (var structure in curStructures)
                 {
                     woDetail = workOrdDetails.Find(s => s.ItemNum == structure.ComponentItem);
@@ -3805,12 +3851,30 @@ namespace Business.ResourceExamineManagement
                         woDetail.CreateTime = DateTime.Now;
                         workOrdDetails.Add(woDetail);
                     }
-                    else {
+                    else
+                    {
                         woDetail.QtyRequired += structure.Qty;
                         woDetail.FrozenBOMQty += structure.Qty;
                     }
-                }
+                }*/
+            }
+        }
+
+        /// <summary>
+        /// 获取虚拟件明细
+        /// </summary>
+        /// <param name="dtl"></param>
+        /// <param name="returnList"></param>
+        /// <param name="childs"></param>
+        public void GetWorkDetalis(List<b_bom_child_examine> dtl, List<b_bom_child_examine> returnList, List<b_bom_child_examine> childs)
+        {
+            returnList.AddRange(dtl);
+            var rst = childs.Where(s => dtl.Where(x => x.erp_cls == 4).Select(c => c.fid).Contains(s.parent_id.GetValueOrDefault())).ToList();
+            if (rst.Any())
+            {
+                GetWorkDetalis(rst, returnList, childs);
             }
+            return;
         }
 
         /// <summary>
@@ -3894,6 +3958,291 @@ namespace Business.ResourceExamineManagement
             _productExamineAppService.CalcSuggestTime(sentrys, kittingTimes, icitemlist);
         }
 
+        /// <summary>
+        /// 替代方案保存
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public async Task<string> SubstituteSave(SubstituteDto dto)
+        {
+            ic_substitute stt;
+            if (dto.id == null)
+            {
+                if (_mysql_ic_substitute.GetListAsync(s => s.substitute_code == dto.scode).Result.Count > 0)
+                {
+                    return "已存在【" + dto.scode + "】替代方案。";
+                }
+                var check = SubstituteSaveBeforCheck(dto);
+                if (check != "ok")
+                {
+                    return check;
+                }
+                //新增
+                stt = new ic_substitute();
+                stt.GenerateNewId(help.NextId());
+                stt.substitute_code = dto.scode;
+                stt.substitute_mode = dto.smode;
+                stt.substitute_strategy = dto.sstrategy;
+                stt.create_by = dto.create_by;
+                stt.create_by_name = dto.create_by_name;
+                stt.create_time = DateTime.Now;
+                stt.update_by = dto.create_by;
+                stt.update_by_name = dto.create_by_name;
+                stt.update_time = DateTime.Now;
+                stt.tenant_id = dto.tenant_id;
+                stt.company_id = dto.company_id;
+                stt.factory_id = dto.factory_id;
+                List<ic_substitute_group> glist = new List<ic_substitute_group>();
+                List<ic_substitute_group_detail> dlist = new List<ic_substitute_group_detail>();
+                SubstituteSaveGenerate(dto, stt, glist, dlist);
+                using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
+                {
+                    try
+                    {
+                        _businessDbContext.BulkInsert(new List<ic_substitute> { stt });
+                        if (glist.Any())
+                        {
+                            _businessDbContext.BulkInsert(glist);
+                        }
+                        if (dlist.Any())
+                        {
+                            _businessDbContext.BulkInsert(dlist);
+                        }
+                        await unitOfWork.CompleteAsync();
+                        return "ok";
+                    }
+                    catch (Exception e)
+                    {
+                        new NLogHelper("ResourceExamineAppService").WriteLog("SubstituteSave", "替代方案保存失败:" + e.Message, _currentTenant.Id.ToString());
+                        unitOfWork.Dispose();
+                        return "保存失败,请联系管理员。";
+                    }
+                }
+            }
+            else
+            {
+                //修改
+                stt = _mysql_ic_substitute.FirstAsync(s => s.Id == dto.id.Value).Result;
+                if (stt != null)
+                {
+                    if (_mysql_ic_substitute.GetListAsync(s => s.Id != dto.id && s.substitute_code == dto.scode && s.company_id == dto.company_id && s.factory_id == dto.factory_id).Result.Count > 0)
+                    {
+                        return "已存在【" + dto.scode + "】替代方案。";
+                    }
+                    if (_mysql_ic_bom_child.GetListAsync(s => s.substitute_code == stt.substitute_code).Result.Count() > 0)
+                    {
+                        return "替代方案已被关联使用,不允许修改。";
+                    }
+                    var check = SubstituteSaveBeforCheck(dto);
+                    if (check != "ok")
+                    {
+                        return check;
+                    }
+                    stt.substitute_code = dto.scode;
+                    stt.substitute_mode = dto.smode;
+                    stt.substitute_strategy = dto.sstrategy;
+                    stt.update_by = dto.create_by;
+                    stt.update_by_name = dto.create_by_name;
+                    stt.update_time = DateTime.Now;
+                    List<ic_substitute_group> glist = new List<ic_substitute_group>();
+                    List<ic_substitute_group_detail> dlist = new List<ic_substitute_group_detail>();
+                    SubstituteSaveGenerate(dto, stt, glist, dlist);
+
+                    var delgList = _mysql_ic_substitute_group.GetListAsync(s => s.substitute_group_id == stt.Id).Result;
+                    var deldList = _mysql_ic_substitute_group_detail.GetListAsync(s => delgList.Select(c => c.Id).Contains(s.substitute_group_id)).Result;
+
+                    using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
+                    {
+                        try
+                        {
+                            _businessDbContext.BulkUpdate(new List<ic_substitute> { stt });
+                            if (delgList.Any())
+                            {
+                                await _mysql_ic_substitute_group.HardDeleteAsync(delgList);
+                            }
+                            if (deldList.Any())
+                            {
+                                await _mysql_ic_substitute_group_detail.HardDeleteAsync(deldList);
+                            }
+                            if (glist.Any())
+                            {
+                                _businessDbContext.BulkInsert(glist);
+                            }
+                            if (dlist.Any())
+                            {
+                                _businessDbContext.BulkInsert(dlist);
+                            }
+                            return "ok";
+                        }
+                        catch (Exception e)
+                        {
+                            new NLogHelper("ResourceExamineAppService").WriteLog("SubstituteSave", "替代方案保存失败:" + e.Message, _currentTenant.Id.ToString());
+                            unitOfWork.Dispose();
+                            return "保存失败,请联系管理员。";
+                        }
+                    }
+                }
+                else
+                {
+                    return "当前方案已被删除,请刷新重试。";
+                }
+            }
+
+        }
+
+        /// <summary>
+        /// 校验
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public string SubstituteSaveBeforCheck(SubstituteDto dto)
+        {
+            if (!dto.srows.Any())
+            {
+                return "替代明细不能为空。";
+            }
+            if (dto.srows.Where(s => s.field_83817a9f5a15a4f78686105c694b0a39 == "是").Count() == 0)
+            {
+                return "请设置替代方案里的标准件。";
+            }
+            if (dto.srows.Where(s => s.field_83817a9f5a15a4f78686105c694b0a39 == "否").Count() == 0)
+            {
+                return "请设置替代方案里的替代件。";
+            }
+            if (dto.srows.Select(s => s.field_f8988ed2955a264f8f762faaed2c5f6a.GetValueOrDefault()).Count() < 2)
+            {
+                return "替代方案最低存在两个优先级。";
+            }
+            //判断同一个优先级里,相同是否标准料
+            foreach (var r in dto.srows)
+            {
+                if (dto.srows.Where(s => s.field_f8988ed2955a264f8f762faaed2c5f6a == r.field_f8988ed2955a264f8f762faaed2c5f6a && s.field_83817a9f5a15a4f78686105c694b0a39 != r.field_83817a9f5a15a4f78686105c694b0a39).Count() > 0)
+                {
+                    return "同优先级群组里不允许既有标准件又有替代件。";
+                }
+            }
+            /*if (dto.srows.GroupBy(s => new { s.field_f8988ed2955a264f8f762faaed2c5f6a, s.field_83817a9f5a15a4f78686105c694b0a39 }).Where(g => g.Count() > 1).Count() > 0)
+            {
+                return "同优先级群组里不允许既有标准件又有替代件。";
+            }*/
+            return "ok";
+        }
+
+        /// <summary>
+        /// 组装数据
+        /// </summary>
+        public void SubstituteSaveGenerate(SubstituteDto dto, ic_substitute stt, List<ic_substitute_group> glist, List<ic_substitute_group_detail> dlist)
+        {
+            dto.srows.ForEach(s =>
+            {
+                ic_substitute_group g = glist.Where(x => x.order_num == s.field_f8988ed2955a264f8f762faaed2c5f6a.GetValueOrDefault()).FirstOrDefault();
+                if (g == null)
+                {
+                    g = new ic_substitute_group();
+                    g.GenerateNewId(help.NextId());
+                    g.substitute_group_id = stt.Id;
+                    g.substitute_code = stt.substitute_code;
+                    g.replace_name = s.substitute_code;
+                    g.order_num = s.field_f8988ed2955a264f8f762faaed2c5f6a.GetValueOrDefault();
+                    g.main_material = s.field_83817a9f5a15a4f78686105c694b0a39 == "是" ? 1 : 0;
+                    g.update_by = dto.create_by;
+                    g.update_by_name = dto.create_by_name;
+                    g.update_time = DateTime.Now;
+                    g.tenant_id = dto.tenant_id;
+                    g.company_id = dto.company_id;
+                    g.factory_id = dto.factory_id;
+                    glist.Add(g);
+                }
+                ic_substitute_group_detail d = new ic_substitute_group_detail();
+                d.GenerateNewId(help.NextId());
+                d.substitute_group_id = g.Id;
+                d.substitute_code = stt.substitute_code;
+                d.icitem_id = s.icitem_id.GetValueOrDefault();
+                d.icitem_number = s.icitem_number;
+                d.seq = s.seq;
+                d.replace_qty = s.replace_qty;
+                d.update_by = dto.create_by;
+                d.update_by_name = dto.create_by_name;
+                d.update_time = DateTime.Now;
+                d.tenant_id = dto.tenant_id;
+                d.company_id = dto.company_id;
+                d.factory_id = dto.factory_id;
+                dlist.Add(d);
+            });
+        }
+
+        /// <summary>
+        /// 手动排产接口
+        /// </summary>
+        /// <param name="domain"></param>
+        /// <returns></returns>
+        /// <exception cref="NotImplementedException"></exception>
+        public async Task<string> ProductionSchedule(string domain)
+        {
+            //获取排产锁定期
+            var generalizedCodeMaster = _generalizedCodeMaster.Select(p => p.FldName == "SystemConfig" && p.Val == "WorkOrderLockPeriod" && p.Domain == domain && p.IsActive).FirstOrDefault();
+            decimal lockDays = generalizedCodeMaster != null ? generalizedCodeMaster.UDeci1 : 0;
+
+            //获取需要排产的工单(获取四周的工单:正常工单+已审批通过的特殊工单)
+            DateTime endDate = DateTime.Now.Date.AddDays(28).AddDays(1);
+            //取数开始时间需要排除掉锁定期内的工单
+            DateTime startDate = DateTime.Now.Date.AddDays(1).AddDays((double)lockDays);
+            var workOrds = _workOrdMaster.Select(p => p.IsActive && p.Domain == domain && p.OrdDate < endDate && p.OrdDate >= startDate && string.IsNullOrEmpty(p.Status) && (string.IsNullOrEmpty(p.Typed) || (!string.IsNullOrEmpty(p.Typed) && p.BusinessID > 0))).ToList();
+            await _productionScheduleAppService.DoProductSchedule(workOrds, domain, 2);
+            return "ok";
+        }
+
+        /// <summary>
+        /// BOM关联替代方案
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public async Task<string> BindingSubstitute(BindingSubstituteDto dto)
+        {
+            var list = _mysql_ic_bom_child.GetListAsync(s => s.bom_id == dto.id && s.tenant_id == dto.tenant_id && s.company_id == dto.company_id && s.factory_id == dto.factory_id).Result;
+
+            if (dto.bomDetail.Any())
+            {
+                list.ForEach(s => { s.substitute_code = ""; s.haveicsubs = 0; });
+                var codeList = dto.bomDetail.Where(s => string.IsNullOrEmpty(s.substitute_code) == false).Select(x => x.substitute_code).Distinct().ToList();
+                if (codeList.Any())
+                {
+                    var subGdtls = _mysql_ic_substitute_group.GetListAsync(s => s.tenant_id == dto.tenant_id && s.company_id == dto.company_id && s.factory_id == dto.factory_id && codeList.Contains(s.substitute_code)).Result;
+                    var subDetalis = _mysql_ic_substitute_group_detail.GetListAsync(s => s.tenant_id == dto.tenant_id && s.company_id == dto.company_id && s.factory_id == dto.factory_id && codeList.Contains(s.substitute_code)).Result;
+                    foreach (var code in codeList)
+                    {
+                        var g = subGdtls.Find(s => s.substitute_code == code && s.main_material == 1);
+                        if (g != null)
+                        {
+                            var dtls = subDetalis.Where(s => s.substitute_group_id == g.Id).ToList();
+                            foreach (var dtl in dtls)
+                            {
+                                var l = list.Find(s => s.item_number == dtl.icitem_number && s.qty == dtl.replace_qty);
+                                if (l == null)
+                                {
+                                    return "当前替代方案【" + code + "】的标准件未找到相同数量相同物料的BOM明细。";
+                                }
+                                if (string.IsNullOrEmpty(l.substitute_code))
+                                {
+                                    l.haveicsubs = 1;
+                                    l.substitute_code = code;
+                                }
+                                else
+                                {
+                                    return "当前替代方案【" + code + "】的标准件【" + l.item_number + "】与替代方案【" + l.substitute_code + "】冲突。";
+                                }
+                            }
+                        }
+                        else
+                        {
+                            return "当前替代方案【" + code + "】未设置标准件。";
+                        }
+                    }
+                }
+                await _mysql_ic_bom_child.UpdateManyAsync(list);
+            }
+            return "ok";
+        }
 
         public async Task<string> WeekPlan(InputDto input)
         {
@@ -4034,9 +4383,9 @@ namespace Business.ResourceExamineManagement
             //Step4:按照Step3制造需求做资源检查,按月统计各物料消耗预测
             //Step5:按照各SKU的历史出库数据和Step4里计算的预测消耗数量计算参数
             //Step6:计算各SKU的12周采购补货
-            
-            
-            
+
+
+
             //获取月度发货计划(一次导入三个月的销售预测),因为是固定格式yyyy-MM所以可以用字符串比较,避免写很多字符串判断相等
             string planMonth = $"{DateTime.Now.Year}-{DateTime.Now.Month.ToString("00")}";
             string planMonthMax = $"{DateTime.Now.AddMonths(replenishmentDto.SaleFcstMonth).Year}-{DateTime.Now.AddMonths(replenishmentDto.SaleFcstMonth).Month.ToString("00")}";
@@ -4098,7 +4447,7 @@ namespace Business.ResourceExamineManagement
                     rop.model = a.Model;
                     rop.erp_cls = icItem.erp_cls; //物料属性: 0.配置类 1.自制 2.委外加工 3.外购 4.虚拟件
                     rop.fversion = icItem.fversion;
-                    rop.min_pack_qty = icItem.minpackqty;             
+                    rop.min_pack_qty = icItem.minpackqty;
                     rop.moq = icItem.moq;
                 }
                 rop.actual_period_start_instock = 0;
@@ -4454,7 +4803,7 @@ namespace Business.ResourceExamineManagement
             {
                 replenishmentModel.service_level_pct = (decimal?)0.96;
             }
-            if (replenishmentModel.abc != "A"&& replenishmentModel.fmr == "R")
+            if (replenishmentModel.abc != "A" && replenishmentModel.fmr == "R")
             {
                 replenishmentModel.service_level_pct = (decimal?)0.9;
             }

+ 6 - 0
MicroServices/Business/Business.Domain/MongoDB/MES/IC/mo_ic_bom_child.cs

@@ -151,6 +151,12 @@ namespace Business.Domain
         [StringLength(80)]
         [Comment("版本")]
         public string? version { get; set; }
+
+        /// <summary>
+        /// 工序
+        /// </summary>
+        [Comment("工序")]
+        public int Op { get; set; }
     }
 }
 

+ 7 - 0
MicroServices/Business/Business.Domain/MongoDB/SRM/mo_srm_pr_main.cs

@@ -246,5 +246,12 @@ namespace Business.Domain
         [StringLength(50)]
         [Comment("项次号")]
         public string? num { get; set; }
+
+
+        /// <summary>
+        /// 采购类型 0,采购申请 1,要货令
+        /// </summary>
+        [Comment("采购类型")]
+        public int IsRequireGoods { get; set; }
     }
 }

+ 68 - 0
MicroServices/Business/Business.Domain/MongoDB/SRM/mo_srm_purchase.cs

@@ -1,5 +1,6 @@
 using Business.Core.Attributes;
 using Microsoft.EntityFrameworkCore;
+using System;
 using System.ComponentModel.DataAnnotations;
 using System.ComponentModel.DataAnnotations.Schema;
 
@@ -168,5 +169,72 @@ namespace Business.Domain
         [Comment("供应类别")]
         public string supplier_type { get; set; }
 
+        /// <summary>
+        /// 关税
+        /// </summary>
+        [Precision(18, 5)]
+        [Comment("关税")]
+        public decimal? tariff { get; set; }
+
+        /// <summary>
+        /// 运费
+        /// </summary>
+        [Precision(18, 5)]
+        [Comment("运费")]
+        public decimal? freight { get; set; }
+
+        /// <summary>
+        /// 生效日期
+        /// </summary>
+        [Comment("生效日期")]
+        public DateTime? effective_date { get; set; }
+
+        /// <summary>
+        /// 失效日期
+        /// </summary>
+        [Comment("失效日期")]
+        public DateTime? expiring_date { get; set; }
+
+        /// <summary>
+        /// 配额比例
+        /// </summary>
+        [Precision(18, 5)]
+        [Comment("配额比例")]
+        public decimal? quota_rate { get; set; }
+
+        /// <summary>
+        /// 采购提前期
+        /// </summary>
+        [Precision(18, 5)]
+        [Comment("采购提前期")]
+        public decimal? lead_time { get; set; }
+
+        /// <summary>
+        /// 价格条款
+        /// </summary>
+        [StringLength(64)]
+        [Comment("价格条款")]
+        public string? price_terms { get; set; }
+
+        /// <summary>
+        /// 每箱包装数量
+        /// </summary>
+        [Precision(18, 5)]
+        [Comment("每箱包装数量")]
+        public decimal? packaging_qty { get; set; }
+
+        /// <summary>
+        /// 采购类型 0,采购申请 1,要货令
+        /// </summary>
+        [Comment("采购类型")]
+        public int IsRequireGoods { get; set; }
+
+        /// <summary>
+        /// 配额优先级
+        /// </summary>
+        [Comment("配额优先级")]
+        public int quota_priority { get; set; }
+
+
     }
 }

+ 6 - 0
MicroServices/Business/Business.Domain/StructuredDB/Bang/b_bom_child_examine.cs

@@ -289,5 +289,11 @@ namespace Business.Domain
         /// </summary>
         [Comment("是否使用此物料")]
         public bool is_use { get; set; }
+
+        /// <summary>
+        /// 工序
+        /// </summary>
+        [Comment("工序")]
+        public int Op { get; set; }
     }
 }

+ 6 - 0
MicroServices/Business/Business.Domain/StructuredDB/Bang/b_bom_pretreatment.cs

@@ -170,5 +170,11 @@ namespace Business.Domain
         [Comment("版本")]
         [StringLength(80)]
         public string version { get; set; }
+
+        /// <summary>
+        /// 工序
+        /// </summary>
+        [Comment("工序")]
+        public int Op { get; set; }
     }
 }

+ 6 - 0
MicroServices/Business/Business.Domain/StructuredDB/MES/IC/PurOrdMaster.cs

@@ -123,5 +123,11 @@ namespace Business.Domain
         /// </summary>
         [Comment("修改人")]
         public string UpdateUser { get; set; }
+
+        /// <summary>
+        /// 类型 DO:要货令
+        /// </summary>
+        [Comment("类型")]
+        public string ReqBy { get; set; }
     }
 }

+ 6 - 0
MicroServices/Business/Business.Domain/StructuredDB/MES/IC/ic_bom_child.cs

@@ -155,6 +155,12 @@ namespace Business.Domain
         [Comment("版本")]
         public string version { get; set; }
 
+        /// <summary>
+        /// 工序
+        /// </summary>
+        [Comment("工序")]
+        public int Op { get; set; }
+
         //[ForeignKey("Id")]
         //public virtual ic_bom Bom { get; set; }
     }

+ 6 - 0
MicroServices/Business/Business.Domain/StructuredDB/Production/WorkOrdRouting.cs

@@ -81,6 +81,12 @@ namespace Business.Domain
         [Comment("订单数量")]
         public decimal? QtyOrded { get; set; }
 
+        /// <summary>
+        /// 工序清场时长(小时)
+        /// </summary>
+        [Comment("工序清场时长")]
+        public decimal WaitTime { get; set; }
+
         /// <summary>
         /// 平行加工件数,下序开工前置数量
         /// </summary>

+ 6 - 0
MicroServices/Business/Business.Domain/StructuredDB/SRM/srm_pr_main.cs

@@ -238,5 +238,11 @@ namespace Business.Domain
         [StringLength(50)]
         [Comment("项次号")]
         public string? num { get; set; }
+
+        /// <summary>
+        /// 采购类型 0,采购申请 1,要货令
+        /// </summary>
+        [Comment("采购类型")]
+        public int IsRequireGoods { get; set; }
     }
 }

+ 13 - 0
MicroServices/Business/Business.Domain/StructuredDB/SRM/srm_purchase.cs

@@ -229,5 +229,18 @@ namespace Business.Domain
         [Comment("每箱包装数量")]
         public decimal? packaging_qty { get; set; }
 
+        /// <summary>
+        /// 采购类型 0,采购申请 1,要货令
+        /// </summary>
+        [Comment("采购类型")]
+        public int IsRequireGoods { get; set; }
+
+        /// <summary>
+        /// 配额优先级
+        /// </summary>
+        [Comment("配额优先级")]
+        public int quota_priority { get; set; }
+        
+
     }
 }

+ 27 - 3
MicroServices/Business/Business.HttpApi/Controllers/ResourceExamineController.cs

@@ -35,13 +35,13 @@ namespace Business.Controllers
         /// <summary>
         /// 生产排产
         /// </summary>
-        /// <param name="workOrds"></param>
+        /// <param name="domain"></param>
         /// <returns></returns>
         [HttpPost]
         [Route("productionschedule")]
-        public Task<string> ProductionSchedule(string workOrds, string domain)
+        public Task<string> ProductionSchedule(string domain)
         {
-            return _ResourceExamineAppService.ProductionSchedule(workOrds, domain);
+            return _ResourceExamineAppService.ProductionSchedule(domain);
         }
 
         /// <summary>
@@ -182,6 +182,30 @@ namespace Business.Controllers
             return _ResourceExamineAppService.ProduceWorkOrdKittingCheck(workord, domain, userAccount);
         }
 
+        /// <summary>
+        /// 替代方案保存
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost]
+        [Route("SubstituteSave")]
+        public Task<string> SubstituteSave(SubstituteDto dto)
+        {
+            return _ResourceExamineAppService.SubstituteSave(dto);
+        }
+
+        /// <summary>
+        /// BOM关联替代方案
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost]
+        [Route("BindingSubstitute")]
+        public Task<string> BindingSubstitute(BindingSubstituteDto dto)
+        {
+            return _ResourceExamineAppService.BindingSubstitute(dto);
+        }
+
         /// <summary>
         /// 更新补货模型月度参数
         /// </summary>

Деякі файли не було показано, через те що забагато файлів було змінено