|
|
@@ -38,6 +38,8 @@ using Volo.Abp.Uow;
|
|
|
using Spire.Pdf.Exporting.XPS.Schema;
|
|
|
using Business.PriorityManagement;
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
+using Business.Dto;
|
|
|
+using NetTopologySuite.Simplify;
|
|
|
|
|
|
namespace Business.ResourceExamineManagement
|
|
|
{
|
|
|
@@ -220,14 +222,53 @@ namespace Business.ResourceExamineManagement
|
|
|
/// </summary>
|
|
|
private readonly ISqlRepository<RoutingOpDetail> _routingOpDetail;
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// 生产线明细
|
|
|
+ /// </summary>
|
|
|
+ private readonly ISqlRepository<ProdLineDetail> _prodLineDetail;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 排产记录表
|
|
|
+ /// </summary>
|
|
|
+ private readonly ISqlRepository<PeriodSequenceDet> _periodSequenceDet;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 工作日历
|
|
|
+ /// </summary>
|
|
|
+ private readonly ISqlRepository<ShopCalendarWorkCtr> _shopCalendarWorkCtr;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 休息时间段
|
|
|
+ /// </summary>
|
|
|
+ private readonly ISqlRepository<QualityLineWorkDetail> _qualityLineWorkDetail;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 节假日
|
|
|
+ /// </summary>
|
|
|
+ private readonly ISqlRepository<HolidayMaster> _holidayMaster;
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// 标准BOM表
|
|
|
/// </summary>
|
|
|
private readonly ISqlRepository<ProductStructureMaster> _productStructureMaster;
|
|
|
- private readonly ISqlRepository<WorkOrdRouting> _workOrdRouting;
|
|
|
- private readonly ISqlRepository<WorkOrdMaster> _workOrdMaster;
|
|
|
- private readonly ISqlRepository<WorkOrdDetail> _workOrdDetail;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 工单工序表
|
|
|
+ /// </summary>
|
|
|
+ private ISqlRepository<WorkOrdRouting> _workOrdRouting;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 工单主表
|
|
|
+ /// </summary>
|
|
|
+ private ISqlRepository<WorkOrdMaster> _workOrdMaster;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 工单物料明细
|
|
|
+ /// </summary>
|
|
|
+ private ISqlRepository<WorkOrdDetail> _workOrdDetail;
|
|
|
+
|
|
|
private readonly ISqlRepository<rf_serialnumber> _rf_serialnumber;
|
|
|
+ private readonly ISqlRepository<LocationDetail> _locationDetail;
|
|
|
/// <summary>
|
|
|
/// 资源检查入参
|
|
|
/// </summary>
|
|
|
@@ -263,17 +304,13 @@ namespace Business.ResourceExamineManagement
|
|
|
private readonly BusinessDbContext _businessDbContext;
|
|
|
private readonly ISqlRepository<TagMaster> _tagMasterRepository;
|
|
|
/// <summary>
|
|
|
- /// 生产周期明细
|
|
|
- /// </summary>
|
|
|
- private ISqlRepository<PeriodSequenceDet> _periodSequenceDet;
|
|
|
- /// <summary>
|
|
|
/// 生产线维护表
|
|
|
/// </summary>
|
|
|
private ISqlRepository<LineMaster> _lineMaster;
|
|
|
private ISqlRepository<ItemMaster> _itemMaster;
|
|
|
private ISqlRepository<NbrMaster> _nbrMaster;
|
|
|
private ISqlRepository<NbrDetail> _nbrDetail;
|
|
|
-
|
|
|
+ private ISqlRepository<ItemPackMaster> _itemPackMaster;
|
|
|
/// <summary>
|
|
|
/// 生产排产
|
|
|
/// </summary>
|
|
|
@@ -283,6 +320,41 @@ namespace Business.ResourceExamineManagement
|
|
|
/// 优先级
|
|
|
/// </summary>
|
|
|
private readonly PriorityAppService _priorityAppService;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 产能检查
|
|
|
+ /// </summary>
|
|
|
+ private readonly ProductExamineAppService _productExamineAppService;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 生产线明细表
|
|
|
+ /// </summary>
|
|
|
+ public List<ProdLineDetail> prodLines = new List<ProdLineDetail>();
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 标准工艺路径表
|
|
|
+ /// </summary>
|
|
|
+ public List<RoutingOpDetail> routingOps = new List<RoutingOpDetail>();
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 排产记录表
|
|
|
+ /// </summary>
|
|
|
+ public List<PeriodSequenceDet> periodSequences = new List<PeriodSequenceDet>();
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 工作日历
|
|
|
+ /// </summary>
|
|
|
+ public List<ShopCalendarWorkCtr> calendarWorks = new List<ShopCalendarWorkCtr>();
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 休息时间段
|
|
|
+ /// </summary>
|
|
|
+ public List<QualityLineWorkDetail> qualityLineWorks = new List<QualityLineWorkDetail>();
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 节假日
|
|
|
+ /// </summary>
|
|
|
+ public List<HolidayMaster> holidays = new List<HolidayMaster>();
|
|
|
#endregion
|
|
|
|
|
|
#region 构造函数
|
|
|
@@ -366,7 +438,14 @@ namespace Business.ResourceExamineManagement
|
|
|
ISqlRepository<NbrMaster> nbrMaster,
|
|
|
ISqlRepository<NbrDetail> nbrDetail,
|
|
|
PriorityAppService priorityAppService,
|
|
|
- ISqlRepository<rf_serialnumber> rf_serialnumber
|
|
|
+ ISqlRepository<ProdLineDetail> prodLineDetail,
|
|
|
+ ISqlRepository<ShopCalendarWorkCtr> shopCalendarWorkCtr,
|
|
|
+ ISqlRepository<QualityLineWorkDetail> qualityLineWorkDetail,
|
|
|
+ ISqlRepository<HolidayMaster> holidayMaster,
|
|
|
+ ProductExamineAppService productExamineAppService,
|
|
|
+ ISqlRepository<rf_serialnumber> rf_serialnumber,
|
|
|
+ ISqlRepository<LocationDetail> locationDetail,
|
|
|
+ ISqlRepository<ItemPackMaster> itemPackMaster
|
|
|
)
|
|
|
{
|
|
|
_mes_technique = mes_technique;
|
|
|
@@ -441,7 +520,14 @@ namespace Business.ResourceExamineManagement
|
|
|
_nbrDetail = nbrDetail;
|
|
|
_priorityAppService= priorityAppService;
|
|
|
_rf_serialnumber = rf_serialnumber;
|
|
|
- }
|
|
|
+ _prodLineDetail = prodLineDetail;
|
|
|
+ _shopCalendarWorkCtr = shopCalendarWorkCtr;
|
|
|
+ _qualityLineWorkDetail = qualityLineWorkDetail;
|
|
|
+ _holidayMaster = holidayMaster;
|
|
|
+ _productExamineAppService= productExamineAppService;
|
|
|
+ _locationDetail = locationDetail;
|
|
|
+ _itemPackMaster = itemPackMaster;
|
|
|
+ }
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
@@ -452,8 +538,23 @@ namespace Business.ResourceExamineManagement
|
|
|
/// <param name="input"></param>
|
|
|
/// <returns></returns>
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
|
- public async Task<string> ReceiveResult(ResourceCheckInputDto input)
|
|
|
+ public async Task<string> ReceiveResult(string ids)
|
|
|
{
|
|
|
+ if (string.IsNullOrEmpty(ids))
|
|
|
+ {
|
|
|
+ throw new NotImplementedException("请输入正确的订单号!");
|
|
|
+ }
|
|
|
+ Array alist = ids.Split(',');
|
|
|
+
|
|
|
+ ResourceCheckInputDto input = new ResourceCheckInputDto();
|
|
|
+ input.sorderId = new List<long>();
|
|
|
+ foreach (string longid in alist)
|
|
|
+ {
|
|
|
+ input.sorderId.Add(long.Parse(longid));
|
|
|
+ }
|
|
|
+ input.tenantId = 1000;
|
|
|
+ input.factoryId = 1001;
|
|
|
+
|
|
|
//资源检查入参全局变量赋值
|
|
|
param.tenantId = input.tenantId;
|
|
|
param.factoryId = input.factoryId;
|
|
|
@@ -479,6 +580,9 @@ namespace Business.ResourceExamineManagement
|
|
|
//获取订单行数据
|
|
|
List<crm_seorderentry> sentrys = await _mysql_crm_seorderentry.GetListAsync(p => p.tenant_id == input.tenantId && p.factory_id == input.factoryId && input.sorderId.Contains(p.seorder_id.GetValueOrDefault()) && !p.IsDeleted);
|
|
|
|
|
|
+ //处理销售订单优先级
|
|
|
+ sorders = _priorityAppService.CalcOrderPriority(sorders, sentrys);
|
|
|
+ AsyncItemStockFromWMS(sentrys);
|
|
|
//处理订单行优先级
|
|
|
sentrys = _priorityAppService.CalcOrderEntryPriority(sorders, sentrys);
|
|
|
|
|
|
@@ -512,7 +616,8 @@ namespace Business.ResourceExamineManagement
|
|
|
AutoCreateBomBill(autoCreates);
|
|
|
pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result;
|
|
|
}
|
|
|
-
|
|
|
+ //记录订单行的物料齐套时间
|
|
|
+ List<KittingTimeDto> kittingTimes = new List<KittingTimeDto>();
|
|
|
DataInitialization(boms, bangid, icitemlist, stocklist, pretreatments);
|
|
|
foreach (var sorder in sorders)
|
|
|
{
|
|
|
@@ -569,8 +674,18 @@ namespace Business.ResourceExamineManagement
|
|
|
dtl.BomChildExamineList = getBomList;
|
|
|
//添加订单行开工信息
|
|
|
examines.Add(dtl);
|
|
|
+
|
|
|
+ //记录订单行的建议交期
|
|
|
+ KittingTimeDto dto = new KittingTimeDto();
|
|
|
+ dto.sentry_id = item.Id;
|
|
|
+ dto.ItemNum = item.item_number;
|
|
|
+ dto.LackQty = getBomList.First(p => p.level == 1).lack_qty;
|
|
|
+ dto.kitting_time = dtl.kitting_times;
|
|
|
+ kittingTimes.Add(dto);
|
|
|
}
|
|
|
}
|
|
|
+ //计算订单行的建议交期(产能/物料)
|
|
|
+ CalcSuggestDate(sentrys, kittingTimes);
|
|
|
|
|
|
await _mysql_crm_seorderentry.UpdateManyAsync(sentrys);
|
|
|
|
|
|
@@ -582,9 +697,8 @@ namespace Business.ResourceExamineManagement
|
|
|
var mesorders = ObjectMapper.Map<List<mo_mes_morder>, List<mes_morder>>(_CalcBomViewAppService.mordersInsertList);
|
|
|
_businessDbContext.BulkInsert(mesorders);
|
|
|
rtn.mordersList = _CalcBomViewAppService.mordersInsertList;
|
|
|
-
|
|
|
- //插入工单相关数据
|
|
|
- CreateWorkOrdDates(_CalcBomViewAppService.mordersInsertList);
|
|
|
+ //同步工单
|
|
|
+ CreateWorkOrdDates(mesorders);
|
|
|
}
|
|
|
if (_CalcBomViewAppService.mooccupyAllInsertList.Any())
|
|
|
{
|
|
|
@@ -656,8 +770,16 @@ namespace Business.ResourceExamineManagement
|
|
|
b_ex.GenerateNewId();// = help.NextId();
|
|
|
if (_CalcBomViewAppService.mordersInsertList.Any())
|
|
|
{
|
|
|
- b_ex.morder_id = _CalcBomViewAppService.mordersInsertList[0].mysql_id;
|
|
|
- b_ex.morder_no = _CalcBomViewAppService.mordersInsertList[0].morder_no;
|
|
|
+ var moentry = _CalcBomViewAppService.moentriesInsertList.Where(s => s.soentry_id == b_ex.sentry_id).FirstOrDefault();
|
|
|
+ if (moentry != null)
|
|
|
+ {
|
|
|
+ var sentryMo = _CalcBomViewAppService.mordersInsertList.Where(s => s.mysql_id == moentry.moentry_moid).FirstOrDefault();
|
|
|
+ if (sentryMo != null)
|
|
|
+ {
|
|
|
+ b_ex.morder_id = sentryMo.mysql_id;
|
|
|
+ b_ex.morder_no = sentryMo.morder_no;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
b_ex.create_time = DateTime.Now;
|
|
|
b_ex.tenant_id = param.tenantId;
|
|
|
@@ -997,7 +1119,10 @@ namespace Business.ResourceExamineManagement
|
|
|
stock_leadtime = x.stock_leadtime,
|
|
|
production_leadtime = x.production_leadtime,
|
|
|
order_leadtime = x.order_leadtime,
|
|
|
- minorderqty = x.minorderqty
|
|
|
+ minorderqty = x.minorderqty,
|
|
|
+ put_integer=x.put_integer,
|
|
|
+ minpackqty=x.minpackqty,
|
|
|
+ ordissu_days=x.ordissu_days
|
|
|
}).AsQueryable<ICItemLeadTimeDto>().ToList();
|
|
|
}
|
|
|
|
|
|
@@ -1089,13 +1214,14 @@ namespace Business.ResourceExamineManagement
|
|
|
{
|
|
|
List<mo_srm_po_main> polist = new List<mo_srm_po_main>();
|
|
|
List<mo_srm_po_list> podetaillist = new List<mo_srm_po_list>();
|
|
|
+ var itemList = _ic_item.Find(a => a.tenant_id == input.tenantId && a.factory_id == input.factoryId).Result;
|
|
|
//将PR按供应商和物料和日期(一周内)进行合并,生成PO
|
|
|
//1.按照供应商、需求日期排序
|
|
|
//2.判断是不是同一个供应商,不是的话就新建一个PO;是的话判断是不是同一周,不是的话就新建一个PO,是的话判断有没有相同物料,有的话合并物料数量价格,没有的话新建一条明细
|
|
|
list = list.OrderBy(a => a.pr_purchaseid).ThenBy(b => b.pr_rarrive_date).ToList();
|
|
|
long? supplierId = -1;
|
|
|
DateTime supplierDate = DateTime.Now;
|
|
|
- foreach (var item in list)
|
|
|
+ foreach (mo_srm_pr_main item in list)
|
|
|
{
|
|
|
if (item.pr_purchaseid != supplierId)
|
|
|
{
|
|
|
@@ -1144,6 +1270,7 @@ namespace Business.ResourceExamineManagement
|
|
|
podetail.pr_purchase_id = po_Main.supplier_id;
|
|
|
podetail.pr_purchase_name = po_Main.supplier_name;
|
|
|
podetail.icitem_id = item.icitem_id;
|
|
|
+ podetail.ItemNum = itemList.First(a => a.mysql_id == item.icitem_id).number;
|
|
|
podetail.icitem_name = item.icitem_name;
|
|
|
podetail.qty = item.pr_aqty;
|
|
|
podetail.netprice = item.pr_price;
|
|
|
@@ -1198,6 +1325,7 @@ namespace Business.ResourceExamineManagement
|
|
|
podetail.pr_purchase_id = pomain.supplier_id;
|
|
|
podetail.pr_purchase_name = pomain.supplier_name;
|
|
|
podetail.icitem_id = item.icitem_id;
|
|
|
+ podetail.ItemNum = itemList.First(a => a.mysql_id == item.icitem_id).number;
|
|
|
podetail.icitem_name = item.icitem_name;
|
|
|
podetail.qty = item.pr_aqty;
|
|
|
podetail.netprice = item.pr_price;
|
|
|
@@ -1268,6 +1396,7 @@ namespace Business.ResourceExamineManagement
|
|
|
podetail.pr_purchase_id = po_Main.supplier_id;
|
|
|
podetail.pr_purchase_name = po_Main.supplier_name;
|
|
|
podetail.icitem_id = item.icitem_id;
|
|
|
+ podetail.ItemNum = itemList.First(a => a.mysql_id == item.icitem_id).number;
|
|
|
podetail.icitem_name = item.icitem_name;
|
|
|
podetail.qty = item.pr_aqty;
|
|
|
podetail.netprice = item.pr_price;
|
|
|
@@ -1303,6 +1432,7 @@ namespace Business.ResourceExamineManagement
|
|
|
{
|
|
|
List<mo_srm_po_main> polist = new List<mo_srm_po_main>();
|
|
|
List<mo_srm_po_list> podetaillist = new List<mo_srm_po_list>();
|
|
|
+ var itemList = _ic_item.Find(a => a.tenant_id == input.tenantId && a.factory_id == input.factoryId).Result;
|
|
|
//将PR按供应商和物料和日期(一周内)进行合并,生成PO
|
|
|
//1.按照供应商、需求日期排序
|
|
|
//2.判断是不是同一个供应商,不是的话就新建一个PO;是的话判断是不是同一周,不是的话就新建一个PO,是的话判断有没有相同物料,有的话合并物料数量价格,没有的话新建一条明细
|
|
|
@@ -1358,6 +1488,7 @@ namespace Business.ResourceExamineManagement
|
|
|
podetail.pr_purchase_id = po_Main.supplier_id;
|
|
|
podetail.pr_purchase_name = po_Main.supplier_name;
|
|
|
podetail.icitem_id = item.icitem_id;
|
|
|
+ podetail.ItemNum = itemList.First(a => a.mysql_id == item.icitem_id).number;
|
|
|
podetail.icitem_name = item.icitem_name;
|
|
|
podetail.qty = item.pr_aqty;
|
|
|
podetail.netprice = item.pr_price;
|
|
|
@@ -1412,6 +1543,7 @@ namespace Business.ResourceExamineManagement
|
|
|
podetail.pr_purchase_id = pomain.supplier_id;
|
|
|
podetail.pr_purchase_name = pomain.supplier_name;
|
|
|
podetail.icitem_id = item.icitem_id;
|
|
|
+ podetail.ItemNum = itemList.First(a => a.mysql_id == item.icitem_id).number;
|
|
|
podetail.icitem_name = item.icitem_name;
|
|
|
podetail.qty = item.pr_aqty;
|
|
|
podetail.netprice = item.pr_price;
|
|
|
@@ -1482,6 +1614,7 @@ namespace Business.ResourceExamineManagement
|
|
|
podetail.pr_purchase_id = po_Main.supplier_id;
|
|
|
podetail.pr_purchase_name = po_Main.supplier_name;
|
|
|
podetail.icitem_id = item.icitem_id;
|
|
|
+ podetail.ItemNum = itemList.First(a => a.mysql_id == item.icitem_id).number;
|
|
|
podetail.icitem_name = item.icitem_name;
|
|
|
podetail.qty = item.pr_aqty;
|
|
|
podetail.netprice = item.pr_price;
|
|
|
@@ -1838,29 +1971,23 @@ namespace Business.ResourceExamineManagement
|
|
|
{
|
|
|
List<long> itemIds = pretreatments.Select(p => p.item_id.GetValueOrDefault()).ToList();
|
|
|
icitemlist.AddRange(_ic_item.GetManyByCondition(p => itemIds.Contains(p.mysql_id) && !p.IsDeleted).Result);
|
|
|
- #region 1、数据准备
|
|
|
- //1.1、获取工艺路径数据
|
|
|
- List<mo_ic_bom> bomlist = _ic_bom.GetManyByCondition(p => itemIds.Contains(p.icitem_id) && p.use_status == 1 && p.tenant_id == param.tenantId && p.factory_id == param.factoryId && !p.IsDeleted).Result.ToList();
|
|
|
- List<mo_mes_technique> techs = GetMesTechniques(bomlist);
|
|
|
- if (techs.Count == 0)
|
|
|
- {
|
|
|
- //throw new NotImplementedException("请先配置工艺路径!");
|
|
|
- }
|
|
|
|
|
|
- //1.2、获取工艺路径关联工序数据
|
|
|
- List<mo_mes_tech_process> tech_Processes = _mes_tech_process.GetManyByCondition(p => techs.Select(m => m.mysql_id).Contains(p.tech_id) && p.tenant_id == param.tenantId && p.factory_id == param.factoryId && !p.IsDeleted).Result;
|
|
|
- if (tech_Processes.Count == 0)
|
|
|
- {
|
|
|
- //throw new NotImplementedException("请先配置工序!");
|
|
|
- }
|
|
|
-
|
|
|
- //1.3、获取当前工艺路径下的工序数据
|
|
|
- List<long> procIds = tech_Processes.Select(m => m.proc_id).ToList();
|
|
|
- List<mo_mes_process> process = _mes_process.GetManyByCondition(p => procIds.Contains(p.mysql_id) && p.tenant_id == param.tenantId && p.factory_id == param.factoryId && !p.IsDeleted).Result;
|
|
|
+ #region 1、数据准备
|
|
|
+ //1.1、获取产能检查相关数据
|
|
|
+ //产品物料编码
|
|
|
+ List<string> itemnums = pretreatments.Where(p => p.level == 1).Select(p => p.item_number).Distinct().ToList();
|
|
|
+ //产线明细
|
|
|
+ prodLines = _prodLineDetail.Select(p=> itemnums.Contains(p.Part)).ToList();
|
|
|
+ //标准工序
|
|
|
+ routingOps = _routingOpDetail.Select(p => itemnums.Contains(p.RoutingCode)).ToList();
|
|
|
+ List<string> lines = prodLines.Select(p=>p.Line).Distinct().ToList();
|
|
|
+ //工作日历
|
|
|
+ calendarWorks = _shopCalendarWorkCtr.Select(p=>lines.Contains(p.ProdLine)).ToList();
|
|
|
+ //休息日
|
|
|
+ qualityLineWorks = _qualityLineWorkDetail.Select(p => lines.Contains(p.ProdLine)).ToList();
|
|
|
+ //节假日
|
|
|
+ holidays = _holidayMaster.Select(p => p.Dated >= DateTime.Now.Date);
|
|
|
|
|
|
- //1.3、获取工艺工序关联工位信息
|
|
|
- List<long> techProcIds = tech_Processes.Select(m => m.mysql_id).ToList();
|
|
|
- List<mo_mes_tech_proc_workshop> tech_Proc_Workshops = _mes_tech_proc_workshop.GetManyByCondition(p => techProcIds.Contains(p.tech_proc_id) && p.tenant_id == param.tenantId && p.factory_id == param.factoryId && !p.IsDeleted).Result;
|
|
|
//主工单
|
|
|
List<mo_mes_morder> mo_Mes_Morders = _mes_morder.GetManyByCondition(x => boms.Select(p => p.bom_number).Contains(x.bom_number) && (x.morder_state != MorderEnum.Accomplish_state || x.morder_state != MorderEnum.Close_state
|
|
|
&& x.morder_icitem_type != MorderEnum.XgwyMorder) && x.tenant_id == param.tenantId && x.bang_id == bangid).Result;
|
|
|
@@ -1888,11 +2015,14 @@ namespace Business.ResourceExamineManagement
|
|
|
_CalcBomViewAppService.planList = planList;
|
|
|
_CalcBomViewAppService.leadTimeList = leadTimeList;
|
|
|
_CalcBomViewAppService.supplierList = supplierList;
|
|
|
- //资源检查添加工艺路径数据
|
|
|
- _CalcBomViewAppService.techs = techs;//工艺路径
|
|
|
- _CalcBomViewAppService.tech_Processes = tech_Processes;//工艺关联工序
|
|
|
- _CalcBomViewAppService.process = process;//工序
|
|
|
- _CalcBomViewAppService.tech_Proc_Workshops = tech_Proc_Workshops;//工艺工序关联工位
|
|
|
+
|
|
|
+ //资源检查添加产线工序等数据
|
|
|
+ _CalcBomViewAppService.prodLines = prodLines;
|
|
|
+ _CalcBomViewAppService.routingOps = routingOps;
|
|
|
+ _CalcBomViewAppService.calendarWorks = calendarWorks;
|
|
|
+ _CalcBomViewAppService.qualityLineWorks = qualityLineWorks;
|
|
|
+ _CalcBomViewAppService.holidays = holidays;
|
|
|
+
|
|
|
_CalcBomViewAppService.mordersList = mo_Mes_Morders;//工单
|
|
|
_CalcBomViewAppService.moentriesList = mo_Mes_Moentry;//工单子表
|
|
|
_CalcBomViewAppService.mooccupyAllList = mes_mooccupyList;//工单占用表
|
|
|
@@ -2017,17 +2147,301 @@ namespace Business.ResourceExamineManagement
|
|
|
AutoCreateBomBill();
|
|
|
}
|
|
|
|
|
|
+ public void AutoCreatePickBill(List<string> workOrds)
|
|
|
+ {
|
|
|
+ //获取生产周期数据
|
|
|
+ List<PeriodSequenceDet> dbPeriodSequences = _periodSequenceDet.Select(p => workOrds.Contains(p.WorkOrds) && p.Domain == "1001" && p.IsActive);
|
|
|
+ List<NbrMaster> nbrMasterList = new List<NbrMaster>();//需要生成领料单列表
|
|
|
+ List<NbrDetail> nbrDetailList = new List<NbrDetail>();//需要生成领料单明细列表
|
|
|
+ if (dbPeriodSequences.Any())
|
|
|
+ {
|
|
|
+ //按照工单领料,一个工单一个领料单,之前是按照排产日期和产线分别领料
|
|
|
+ foreach(var workord in workOrds)
|
|
|
+ {
|
|
|
+ Dictionary<string, decimal> dictItemQty = new Dictionary<string, decimal>();
|
|
|
+ List<string> lines = dbPeriodSequences.Where(a=>a.WorkOrds==workord).Select(a => a.Line).Distinct().ToList();
|
|
|
+ List<LineMaster> lineMasters = _lineMaster.Select(p => lines.Contains(p.Line) && p.Domain == "1001" && p.IsActive);
|
|
|
+ List<ProductStructureMaster> itemList = GetProductStructure(dbPeriodSequences.First(a => a.WorkOrds == workord).ItemNum);
|
|
|
+ var childrenList = itemList.Select(a => a.ComponentItem).Distinct().ToList();
|
|
|
+ List<ItemMaster> itemLocList = _itemMaster.Select(p => childrenList.Contains(p.ItemNum) && p.Domain == "1001" && p.IsActive).Distinct().ToList();
|
|
|
+ List<ItemPackMaster> itemPackList = _itemPackMaster.Select(p => childrenList.Contains(p.ItemNum) && p.Domain == "1001" && p.IsActive).Distinct().ToList();
|
|
|
+ var Nbr = GetMaxSerialNumber(417416915624005);
|
|
|
+ //根据某一产线汇总即该工单的总数
|
|
|
+ decimal QtyOrdSum = dbPeriodSequences.Where(a => a.WorkOrds == workord && a.Line == lines[0]).Sum(a => a.OrdQty.GetValueOrDefault());
|
|
|
+ nbrMasterList.Add(new NbrMaster
|
|
|
+ {
|
|
|
+ Domain = "1001",
|
|
|
+ Type = "SM",
|
|
|
+ Nbr = Nbr,
|
|
|
+ Remark = "排产自动领料",
|
|
|
+ Date = dbPeriodSequences.Where(a => a.WorkOrds == workord).Min(a=>a.PlanDate),
|
|
|
+ //ProdLine = item.Line,
|
|
|
+ Status = "",
|
|
|
+ WorkOrd = workord,
|
|
|
+ QtyOrd = QtyOrdSum,
|
|
|
+ IsActive = true,
|
|
|
+ IsChanged = true,
|
|
|
+ Name = "1001",
|
|
|
+ Department = "101",
|
|
|
+ CreateTime = DateTime.Now,
|
|
|
+ UpdateTime = DateTime.Now,
|
|
|
+ CreateUser = "1001",
|
|
|
+ UpdateUser = "1001"
|
|
|
+ });
|
|
|
+ int i = 1;
|
|
|
+ itemList?.ForEach(a =>
|
|
|
+ {
|
|
|
+ var find = itemLocList?.Find(c => c.ItemNum == a.ComponentItem);
|
|
|
+ string LocationTo = "";
|
|
|
+ if (find!=null)
|
|
|
+ {
|
|
|
+ LocationTo=find.Location;
|
|
|
+ }
|
|
|
+ //相同物料汇总
|
|
|
+ var itemComponent = nbrDetailList.Find(b => b.Nbr == Nbr && b.ItemNum == a.ComponentItem);
|
|
|
+ if (itemComponent==null)
|
|
|
+ {
|
|
|
+ nbrDetailList.Add(new NbrDetail
|
|
|
+ {
|
|
|
+ Domain = "1001",
|
|
|
+ Type = "SM",
|
|
|
+ Nbr = Nbr,
|
|
|
+ ItemNum = a.ComponentItem,
|
|
|
+ QtyFrom = 0,
|
|
|
+ QtyTo = 0,
|
|
|
+ LocationFrom = LocationTo,
|
|
|
+ LocationTo = "",
|
|
|
+ WorkOrd = workord,
|
|
|
+ QtyOrd =QtyOrdSum * a.Qty,
|
|
|
+ CurrQtyOpened = QtyOrdSum * a.Qty ,
|
|
|
+ Line = i,
|
|
|
+ IsActive = true,
|
|
|
+ CreateTime = DateTime.Now,
|
|
|
+ UpdateTime = DateTime.Now,
|
|
|
+ CreateUser = "1001",
|
|
|
+ UpdateUser = "1001",
|
|
|
+ UM = a.UM
|
|
|
+ });
|
|
|
+ i++;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ nbrDetailList.First( b=> b.Nbr == Nbr && b.ItemNum == a.ComponentItem).QtyOrd= itemComponent.QtyOrd+ QtyOrdSum * a.Qty;
|
|
|
+ nbrDetailList.First(b => b.Nbr == Nbr && b.ItemNum == a.ComponentItem).CurrQtyOpened = itemComponent.CurrQtyOpened + QtyOrdSum * a.Qty;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ nbrDetailList.ForEach(a =>
|
|
|
+ {
|
|
|
+ if(a.Nbr==Nbr)
|
|
|
+ {
|
|
|
+ var find = itemLocList?.Find(c => c.ItemNum == a.ItemNum);
|
|
|
+ var packfind = itemPackList?.Find(c => c.ItemNum == a.ItemNum);
|
|
|
+ if (find != null && !find.TraceDetail && packfind != null && packfind.PackingQty > 0)
|
|
|
+ {
|
|
|
+ a.CurrQtyOpened = Math.Ceiling(a.CurrQtyOpened.GetValueOrDefault() / packfind.PackingQty.GetValueOrDefault()) * packfind.PackingQty;
|
|
|
+ dictItemQty.Add(a.ItemNum, QtyOrdSum * itemList.First(b => b.ComponentItem == a.ItemNum).Qty);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ dictItemQty.Add(a.ItemNum, QtyOrdSum * itemList.First(b => b.ComponentItem == a.ItemNum).Qty);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ List<string> itemKeys = dictItemQty.Keys.ToList();
|
|
|
+ //var items = _mysql_ic_item.GetListAsync(a => itemKeys.Contains(a.number) && a.factory_id == 1001 && a.tenant_id == 1000).Result;
|
|
|
+ //var itemIds = items.Select(b => b.Id).ToList();
|
|
|
+ //var leadTimes = GetLeadTime(itemIds, 1000, 1001).Max(a=>a.ordissu_days.GetValueOrDefault());
|
|
|
+ decimal leadTimes=itemLocList.Select(a => a.MFGMTTR).Max();
|
|
|
+ //没有维护备料提前期,默认取7天
|
|
|
+ if (leadTimes > 0)
|
|
|
+ {
|
|
|
+ nbrMasterList.First(a => a.Nbr == Nbr).Date = dbPeriodSequences.Where(a => a.WorkOrds == workord).Min(a => a.PlanDate).GetValueOrDefault().AddDays(-1 * Convert.ToDouble(leadTimes));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ nbrMasterList.First(a => a.Nbr == Nbr).Date = dbPeriodSequences.Where(a => a.WorkOrds == workord).Min(a => a.PlanDate).GetValueOrDefault().AddDays(-7);
|
|
|
+ }
|
|
|
+ //TODO:
|
|
|
+ //因为我们并没有模拟发料的过程,在自动生成领料单的时候就要扣减库存,实际业务不能这么做。
|
|
|
+ //在有上料和追溯的系统,可以在扫码上料或报工时(从线边仓)扣减。或者在实际发料出库时扣减。
|
|
|
+ var locStock=_locationDetail.Select(a => itemKeys.Contains(a.ItemNum) && a.IsActive && a.Domain == "1001");
|
|
|
+ locStock?.ForEach(a =>
|
|
|
+ {
|
|
|
+ nbrDetailList.ForEach(b =>
|
|
|
+ {
|
|
|
+ if(a.ItemNum==b.ItemNum && a.Location==b.LocationFrom && a.QtyOnHand - dictItemQty[a.ItemNum] > 0)
|
|
|
+ {
|
|
|
+ a.QtyOnHand = a.QtyOnHand - dictItemQty[a.ItemNum];
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ _locationDetail.Update(locStock);
|
|
|
+ }
|
|
|
+ _nbrMaster.Insert(nbrMasterList);
|
|
|
+ //快开平台用自增列RecId关联,所以需要插入后再查给明细表赋相应的值
|
|
|
+ List<string> nbrs = nbrMasterList.Select(a => a.Nbr).ToList();
|
|
|
+ var nbrList = _nbrMaster.Select(a => a.Domain == "1001" && a.Type == "SM" && nbrs.Contains(a.Nbr));
|
|
|
+ nbrDetailList.ForEach(c =>
|
|
|
+ {
|
|
|
+ c.NbrRecID = nbrList.Where(a => a.Nbr == c.Nbr).First().RecID;
|
|
|
+ });
|
|
|
+ _nbrDetail.Insert(nbrDetailList);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void AsyncItemStockFromWMS(List<crm_seorderentry> sentrys)
|
|
|
+ {
|
|
|
+ //产品编码
|
|
|
+ var itemList = sentrys.Select(a => a.item_number).Distinct().ToList();
|
|
|
+ List<string> itemChildList = new List<string>();
|
|
|
+ itemList.ForEach(a =>
|
|
|
+ {
|
|
|
+ itemChildList.AddRange(GetChildItemNumber(a, new List<string>()));
|
|
|
+ });
|
|
|
+ var stockList = _locationDetail.Select(a => a.Domain == "1001" && a.IsActive && itemChildList.Distinct().Contains(a.ItemNum));
|
|
|
+ var groupList = stockList.
|
|
|
+ GroupBy(m => new { m.ItemNum }).
|
|
|
+ Select(a => new { ItemNum = a.Key.ItemNum, Qty = a.Sum(c => c.QtyOnHand) }).ToList();
|
|
|
+ var itemNums = groupList.Select(b => b.ItemNum).ToList();//需要处理的dop物料编码集合
|
|
|
+ var items = _mysql_ic_item.GetListAsync(a => itemNums.Contains(a.number) && a.factory_id == 1001 && a.tenant_id == 1000).Result;
|
|
|
+ var itemIds = items.Select(b => b.Id).ToList();//需要处理的dop物料id集合
|
|
|
+ List<ic_item_stock> mysqlStock = _mysql_ic_item_stock.GetListAsync(a => itemIds.Contains(a.Id) && a.factory_id == 1001 && a.tenant_id == 1000).Result;
|
|
|
+ List<ic_item_stock> needAddList = new List<ic_item_stock>();
|
|
|
+
|
|
|
+ foreach(var stockWMS in groupList)
|
|
|
+ {
|
|
|
+ foreach (var num in items)
|
|
|
+ {
|
|
|
+ if (stockWMS.ItemNum==num.number)
|
|
|
+ {
|
|
|
+ var item = mysqlStock.Find(a => a.Id == num.Id);
|
|
|
+ if(item!=null)
|
|
|
+ {
|
|
|
+ item.sqty = groupList.First(a => a.ItemNum == num.number).Qty;
|
|
|
+ }else
|
|
|
+ {
|
|
|
+ ic_item_stock stock= new ic_item_stock();
|
|
|
+ stock.GenerateNewId();
|
|
|
+ stock.factory_id = 1001;
|
|
|
+ stock.tenant_id = 1000;
|
|
|
+ stock.icitem_id = num.Id;
|
|
|
+ stock.icitem_name = num.name;
|
|
|
+ stock.sqty= groupList.First(a => a.ItemNum == num.number).Qty;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ };
|
|
|
+ }
|
|
|
+ if(needAddList.Count>0)
|
|
|
+ {
|
|
|
+ _businessDbContext.BulkInsert(needAddList);
|
|
|
+ }
|
|
|
+ _businessDbContext.BulkUpdate(mysqlStock);
|
|
|
+ }
|
|
|
+ //循环获取子级物料编码,包括产品本身,有重复的结果去重即可
|
|
|
+ public List<string> GetChildItemNumber(string itemNum,List<string> list)
|
|
|
+ {
|
|
|
+ list.Add(itemNum);
|
|
|
+ var productStructures = _productStructureMaster.Select(p =>p.ParentItem== itemNum && p.Domain == "1001" && p.IsActive);
|
|
|
+ list.AddRange(productStructures.Select(a=>a.ComponentItem));
|
|
|
+ foreach (var item in productStructures)
|
|
|
+ {
|
|
|
+ if(item.StructureType.ToUpper()=="X")
|
|
|
+ {
|
|
|
+ GetChildItemNumber(item.ComponentItem, list);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 得到一个流水号的最大流水号
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="id">流水号id</param>
|
|
|
+ /// <param name="formData">json数据,可以用json中的某个字段值作为通配符字替换流水号格式。</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public string GetMaxSerialNumber(long id, JObject? formData = null)
|
|
|
+ {
|
|
|
+ var modelList = _rf_serialnumber.Select(s => s.Id == id);
|
|
|
+ if (modelList == null && modelList.Count < 1)
|
|
|
+ {
|
|
|
+ return string.Empty;
|
|
|
+ }
|
|
|
+ var model = modelList[0];
|
|
|
+ int max = model.CurrentNumber + 1;
|
|
|
+ var date = DateTime.Now;
|
|
|
+ var lastDate = model.LastTime;
|
|
|
+ switch (model.NumberType)
|
|
|
+ {
|
|
|
+ case 1: //年流水
|
|
|
+ if (date.Year > lastDate.Year)
|
|
|
+ {
|
|
|
+ max = 1;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 2: //月流水
|
|
|
+ if (date.Year > lastDate.Year || date.Month > lastDate.Month)
|
|
|
+ {
|
|
|
+ max = 1;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 3: //日流水
|
|
|
+ if (date.Year > lastDate.Year || date.Month > lastDate.Month || date.Day > lastDate.Day)
|
|
|
+ {
|
|
|
+ max = 1;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ string number = max.ToString().PadLeft(model.NumberSize, '0');
|
|
|
+ string serialNumber = string.IsNullOrWhiteSpace(model.Format) ? number
|
|
|
+ : model.Format.ContainsIgnoreCase("{number}")
|
|
|
+ ? model.Format.ReplaceIgnoreCase("{number}", number)
|
|
|
+ : model.Format + number;
|
|
|
+ //更新当前编号和最后时间
|
|
|
+ model.LastTime = date;
|
|
|
+ model.CurrentNumber = max;
|
|
|
+ _rf_serialnumber.Update(model);
|
|
|
+ return Wildcard.Replace(serialNumber, formData);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 生产排产
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="workOrd"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ /// <exception cref="NotImplementedException"></exception>
|
|
|
+ public async Task<string> ProductionSchedule(string workOrd)
|
|
|
+ {
|
|
|
+ List<string> workOrds = workOrd.Split(",").ToList();
|
|
|
+ if (workOrds.Count() == 0)
|
|
|
+ {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ //获取工单数据
|
|
|
+ var workOrdMasters = _workOrdMaster.Select(p => workOrds.Contains(p.WorkOrd));
|
|
|
+ //获取已排产的工单
|
|
|
+ List<string> dbWorkOrds = _periodSequenceDet.Select(p => workOrds.Contains(p.WorkOrds)).Select(p => p.WorkOrds).Distinct().ToList();
|
|
|
+ //过滤掉已排产的工单
|
|
|
+ workOrdMasters = workOrdMasters.Where(p => !dbWorkOrds.Contains(p.WorkOrd)).ToList();
|
|
|
+ if (workOrdMasters.Count() == 0)
|
|
|
+ {
|
|
|
+ return JsonConvert.SerializeObject("ok");
|
|
|
+ }
|
|
|
+ //排产
|
|
|
+ await _productionScheduleAppService.DoProductShcedule(workOrdMasters);
|
|
|
+ AutoCreatePickBill(workOrdMasters.Select(p => p.WorkOrd).ToList());
|
|
|
+ return JsonConvert.SerializeObject("ok");
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// 同步工单等相关数据
|
|
|
/// </summary>
|
|
|
/// <param name="morders"></param>
|
|
|
- [UnitOfWork]
|
|
|
- public void CreateWorkOrdDates(List<mo_mes_morder> morders)
|
|
|
+ public void CreateWorkOrdDates(List<mes_morder> morders)
|
|
|
{
|
|
|
//获取工艺路线数据:product_code=物料编码
|
|
|
List<RoutingOpDetail> allRoutings = _routingOpDetail.Select(p => morders.Select(m => m.product_code).Contains(p.RoutingCode));
|
|
|
- //获取标准BOM数据
|
|
|
- List<ProductStructureMaster> productStructures = GetProductStructure(morders.Select(p => p.product_code).ToList());
|
|
|
+
|
|
|
//工单主表
|
|
|
List<WorkOrdMaster> workOrds = new List<WorkOrdMaster>();
|
|
|
WorkOrdMaster workOrd;
|
|
|
@@ -2043,19 +2457,18 @@ namespace Business.ResourceExamineManagement
|
|
|
workOrd = new WorkOrdMaster();
|
|
|
workOrd.Domain = "1001";
|
|
|
workOrd.OrdDate = item.moentry_sys_stime;
|
|
|
- workOrd.ReleaseDate =Convert.ToDateTime(item.moentry_sys_stime.GetValueOrDefault().ToString("u"));
|
|
|
+ workOrd.ReleaseDate = Convert.ToDateTime(item.moentry_sys_stime.GetValueOrDefault().ToString("u"));
|
|
|
workOrd.WorkOrd = item.morder_no;
|
|
|
workOrd.ItemNum = item.product_code;//物料编码
|
|
|
workOrd.QtyOrded = item.need_number.GetValueOrDefault();
|
|
|
workOrd.RoutingCode = item.product_code;
|
|
|
workOrd.Period = 1;
|
|
|
workOrd.Priority = item.urgent;
|
|
|
- workOrd.Status = "";
|
|
|
+ workOrd.Status = " ";
|
|
|
workOrd.IsActive = true;
|
|
|
- workOrd.ProdLine = "组装线";
|
|
|
workOrd.IsConfirm = true;
|
|
|
workOrds.Add(workOrd);
|
|
|
-
|
|
|
+
|
|
|
//添加工单工艺路线数据
|
|
|
var curRoutings = allRoutings.Where(p => p.RoutingCode == item.product_code).ToList();
|
|
|
foreach (var dtl in curRoutings)
|
|
|
@@ -2076,8 +2489,7 @@ namespace Business.ResourceExamineManagement
|
|
|
workOrdRoutings.Add(woRouting);
|
|
|
}
|
|
|
|
|
|
- //添加工单物料数据
|
|
|
- var curStructures = productStructures.Where(p => p.ParentItem == item.product_code).ToList();
|
|
|
+ List<ProductStructureMaster> curStructures = GetProductStructure(item.product_code);
|
|
|
foreach (var structure in curStructures)
|
|
|
{
|
|
|
//添加工单的物料信息
|
|
|
@@ -2094,42 +2506,33 @@ namespace Business.ResourceExamineManagement
|
|
|
workOrdDetails.Add(woDetail);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- //await _businessDbContext.BulkInsertAsync(workOrds);
|
|
|
- //await _businessDbContext.BulkInsertAsync(workOrdRoutings);
|
|
|
- //await _businessDbContext.BulkInsertAsync(workOrdDetails);
|
|
|
- _workOrdMaster.Insert(workOrds);
|
|
|
- _workOrdRouting.Insert(workOrdRoutings);
|
|
|
- _workOrdDetail.Insert(workOrdDetails);
|
|
|
-
|
|
|
- //排产
|
|
|
- _productionScheduleAppService.DoProductShcedule(workOrds);
|
|
|
- AutoCreatePickBill(workOrds.Select(a => a.WorkOrd).ToList());
|
|
|
+ _workOrdMaster.Insert(workOrds);
|
|
|
+ _workOrdRouting.Insert(workOrdRoutings);
|
|
|
+ _workOrdDetail.Insert(workOrdDetails);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 获取标准Bom数据--TODO:存在循环查询数据库问题,后续调整
|
|
|
/// </summary>
|
|
|
- /// <param name="itenNums">产品物料编码</param>
|
|
|
+ /// <param name="itenNum">产品物料编码</param>
|
|
|
/// <returns></returns>
|
|
|
- public List<ProductStructureMaster> GetProductStructure(List<string> itenNums)
|
|
|
+ public List<ProductStructureMaster> GetProductStructure(string itenNum)
|
|
|
{
|
|
|
List<ProductStructureMaster> rtnStructures = new List<ProductStructureMaster>();
|
|
|
//根据itemNum获取bom数据
|
|
|
- var productStructures = _productStructureMaster.Select(p => itenNums.Contains(p.ParentItem) && p.Domain == "1001" && p.IsActive);
|
|
|
+ var productStructures = _productStructureMaster.Select(p => itenNum == p.ParentItem && p.Domain == "1001" && p.IsActive);
|
|
|
//添加非虚拟件
|
|
|
rtnStructures.AddRange(productStructures.Where(p => p.StructureType.ToUpper() != "X").ToList());
|
|
|
- foreach (var item in itenNums)
|
|
|
+
|
|
|
+ //获取当前产品的虚拟件
|
|
|
+ var curPhantoms = productStructures.Where(p => p.StructureType.ToUpper() == "X").ToList();
|
|
|
+ if (curPhantoms.Count() == 0)
|
|
|
{
|
|
|
- //获取当前产品的虚拟件
|
|
|
- var curPhantoms = productStructures.Where(p => p.ParentItem == item && p.StructureType.ToUpper() == "X").ToList();
|
|
|
- if (curPhantoms.Count() == 0)
|
|
|
- {
|
|
|
- continue;
|
|
|
- }
|
|
|
- //递归获取所有虚拟件对应的子物料
|
|
|
- RecursionProductStructure(item, curPhantoms, rtnStructures);
|
|
|
+ return rtnStructures;
|
|
|
}
|
|
|
+ //递归获取所有虚拟件对应的子物料
|
|
|
+ RecursionProductStructure(itenNum, curPhantoms, rtnStructures);
|
|
|
+
|
|
|
return rtnStructures;
|
|
|
}
|
|
|
|
|
|
@@ -2142,18 +2545,16 @@ namespace Business.ResourceExamineManagement
|
|
|
public void RecursionProductStructure(string parentItem, List<ProductStructureMaster> structures, List<ProductStructureMaster> rtnStructures)
|
|
|
{
|
|
|
//获取虚拟件的子物料
|
|
|
- var chdStructures = _productStructureMaster.Select(p => structures.Select(m => m.ComponentItem).Contains(p.ParentItem) && p.Domain == "1001" && p.IsActive);
|
|
|
+ List<ProductStructureMaster> chdStructures = _productStructureMaster.Select(p => structures.Select(m => m.ComponentItem).Contains(p.ParentItem) && p.Domain == "1001" && p.IsActive);
|
|
|
//非虚拟件
|
|
|
var notPhantoms = chdStructures.Where(p => p.StructureType.ToUpper() != "X").ToList();
|
|
|
//存在非虚拟件
|
|
|
- if (notPhantoms.Count() > 0)
|
|
|
+ foreach (var item in notPhantoms)
|
|
|
{
|
|
|
- notPhantoms.ForEach(p =>
|
|
|
- {
|
|
|
- p.ParentItem = parentItem;
|
|
|
- });
|
|
|
- rtnStructures.AddRange(notPhantoms);
|
|
|
+ item.ParentItem = parentItem;
|
|
|
}
|
|
|
+ rtnStructures.AddRange(notPhantoms);
|
|
|
+
|
|
|
//虚拟件
|
|
|
var phantoms = chdStructures.Where(p => p.StructureType.ToUpper() == "X").ToList();
|
|
|
if (phantoms.Count() > 0)
|
|
|
@@ -2163,145 +2564,31 @@ namespace Business.ResourceExamineManagement
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- public void AutoCreatePickBill(List<string> workOrds)
|
|
|
- {
|
|
|
- //获取生产周期数据
|
|
|
- List<PeriodSequenceDet> dbPeriodSequences = _periodSequenceDet.Select(p => workOrds.Contains(p.WorkOrds) && p.Domain == "1001" && p.IsActive);
|
|
|
- List<LineMaster> lineMasters = new List<LineMaster>();
|
|
|
- List<string> lines = new List<string>();//产线列表,
|
|
|
- List<NbrMaster> nbrMasterList = new List<NbrMaster>();//需要生成领料单列表
|
|
|
- List<NbrDetail> nbrDetailList = new List<NbrDetail>();//需要生成领料单明细列表
|
|
|
- Dictionary<string, decimal> dictItemQty = new Dictionary<string, decimal>();
|
|
|
- if (dbPeriodSequences.Any())
|
|
|
- {
|
|
|
- lines = dbPeriodSequences.Select(a => a.Line).Distinct().ToList();
|
|
|
- lineMasters = _lineMaster.Select(p => lines.Contains(p.Line) && p.Domain == "1001" && p.IsActive);
|
|
|
- List<ProductStructureMaster> itemList=GetProductStructure(dbPeriodSequences.Select(a=>a.ItemNum).Distinct().ToList());
|
|
|
- var childrenList= itemList.Select(a=>a.ComponentItem).Distinct().ToList();
|
|
|
- List<ItemMaster> itemLocList = _itemMaster.Select(p => childrenList.Contains(p.ItemNum) && p.Domain == "1001" && p.IsActive).Distinct().ToList();
|
|
|
- foreach (var item in dbPeriodSequences)
|
|
|
- {
|
|
|
- var Nbr = GetMaxSerialNumber(417416915624005);
|
|
|
- nbrMasterList.Add(new NbrMaster
|
|
|
- {
|
|
|
- Domain = "1001",
|
|
|
- Type = "SM",
|
|
|
- Nbr = Nbr,
|
|
|
- Remark = "",
|
|
|
- Date = item.PlanDate,
|
|
|
- ProdLine = item.Line,
|
|
|
- Status = "",
|
|
|
- WorkOrd = item.WorkOrds,
|
|
|
- QtyOrd = item.OrdQty.HasValue ? item.OrdQty.Value : 0,
|
|
|
- IsActive = true,
|
|
|
- IsChanged = false
|
|
|
- });
|
|
|
- int i = 1;
|
|
|
- itemList.Where(a => a.ParentItem == item.ItemNum).ToList()?.ForEach(a =>
|
|
|
- {
|
|
|
- string LocationTo = "";
|
|
|
- if (itemLocList.Where(c => c.ItemNum == a.ComponentItem).ToList().Any())
|
|
|
- {
|
|
|
- LocationTo = itemLocList?.Where(c => c.ItemNum == a.ComponentItem).First().Location;
|
|
|
- }
|
|
|
- nbrDetailList.Add(new NbrDetail
|
|
|
- {
|
|
|
- Domain = "1001",
|
|
|
- Type = "SM",
|
|
|
- Nbr = Nbr,
|
|
|
- ItemNum = a.ComponentItem,
|
|
|
- QtyFrom = 0,
|
|
|
- QtyTo = 0,
|
|
|
- LocationFrom = LocationTo,
|
|
|
- LocationTo = "",
|
|
|
- WorkOrd = item.WorkOrds,
|
|
|
- QtyOrd = item.OrdQty * a.Qty,
|
|
|
- Line = i,
|
|
|
- IsActive = true,
|
|
|
- });
|
|
|
- if(dictItemQty.ContainsKey(a.ComponentItem))
|
|
|
- {
|
|
|
- dictItemQty[a.ComponentItem] = dictItemQty[a.ComponentItem] + item.OrdQty.Value * a.Qty;
|
|
|
- }else
|
|
|
- {
|
|
|
- dictItemQty.Add(a.ComponentItem, item.OrdQty.Value * a.Qty);
|
|
|
- }
|
|
|
- i++;
|
|
|
- });
|
|
|
- }
|
|
|
- _nbrMaster.Insert(nbrMasterList);
|
|
|
- //快开平台用自增列RecId关联,所以需要插入后再查给明细表赋相应的值
|
|
|
- List<string> nbrs= nbrMasterList.Select(a=>a.Nbr).ToList();
|
|
|
- var nbrList= _nbrMaster.Select(a => a.Domain == "1001" && a.Type == "SM" && nbrs.Contains(a.Nbr));
|
|
|
- nbrDetailList.ForEach(c =>
|
|
|
- {
|
|
|
- c.NbrRecID= nbrList.Where(a=>a.Nbr==c.Nbr).First().RecID;
|
|
|
- });
|
|
|
- _nbrDetail.Insert(nbrDetailList);
|
|
|
- //TODO:
|
|
|
- //因为我们并没有模拟发料的过程,在自动生成领料单的时候就要扣减库存,实际业务不能这么做。
|
|
|
- //在有上料和追溯的系统,可以在扫码上料或报工时(从线边仓)扣减。或者在实际发料出库时扣减。
|
|
|
- List<string> itemKeys= dictItemQty.Keys.ToList();
|
|
|
- var items=_mysql_ic_item.GetListAsync(a => itemKeys.Contains(a.number) && a.factory_id == 1001 && a.tenant_id == 1000).Result;
|
|
|
- var itemIds=items.Select(b => b.Id).ToList();
|
|
|
- var stockList=_mysql_ic_item_stock.GetListAsync(a => itemIds.Contains(a.Id) && a.factory_id == 1001 && a.tenant_id == 1000).Result;
|
|
|
- stockList?.ForEach(a =>
|
|
|
- {
|
|
|
- a.sqty = a.sqty - dictItemQty[items.First(b => b.Id == a.Id).number];
|
|
|
- });
|
|
|
- //_mysql_ic_item_stock.UpdateManyAsync(stockList);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
/// <summary>
|
|
|
- /// 得到一个流水号的最大流水号
|
|
|
+ /// 计算订单行的系统建议交期
|
|
|
/// </summary>
|
|
|
- /// <param name="id">流水号id</param>
|
|
|
- /// <param name="formData">json数据,可以用json中的某个字段值作为通配符字替换流水号格式。</param>
|
|
|
- /// <returns></returns>
|
|
|
- public string GetMaxSerialNumber(long id, JObject? formData = null)
|
|
|
+ /// <param name="sentrys"></param>
|
|
|
+ /// <param name="kittingTimes"></param>
|
|
|
+ public async void CalcSuggestDate(List<crm_seorderentry> sentrys, List<KittingTimeDto> kittingTimes)
|
|
|
{
|
|
|
- var modelList = _rf_serialnumber.Select(s => s.Id == id);
|
|
|
- if (modelList == null && modelList.Count < 1)
|
|
|
+ //获取排产记录
|
|
|
+ List<string> itemNums = sentrys.Select(p=>p.item_number).Distinct().ToList();
|
|
|
+ DateTime eralist = kittingTimes.Min(p => p.kitting_time).Date;
|
|
|
+ List<PeriodSequenceDet> periodSequences = _periodSequenceDet.Select(p => itemNums.Contains(p.ItemNum) && p.PlanDate >= eralist).ToList();
|
|
|
+
|
|
|
+ //资源检查添加产线工序等数据
|
|
|
+ _productExamineAppService.prodLines = prodLines;
|
|
|
+ _productExamineAppService.routingOps = routingOps;
|
|
|
+ _productExamineAppService.calendarWorks = calendarWorks;
|
|
|
+ _productExamineAppService.qualityLineWorks = qualityLineWorks;
|
|
|
+ _productExamineAppService.holidays = holidays;
|
|
|
+ _productExamineAppService.periodSequences = periodSequences;
|
|
|
+ if (sentrys.Count() == 0)
|
|
|
{
|
|
|
- return string.Empty;
|
|
|
- }
|
|
|
- var model = modelList[0];
|
|
|
- int max = model.CurrentNumber + 1;
|
|
|
- var date = DateTime.Now;
|
|
|
- var lastDate = model.LastTime;
|
|
|
- switch (model.NumberType)
|
|
|
- {
|
|
|
- case 1: //年流水
|
|
|
- if (date.Year > lastDate.Year)
|
|
|
- {
|
|
|
- max = 1;
|
|
|
- }
|
|
|
- break;
|
|
|
- case 2: //月流水
|
|
|
- if (date.Year > lastDate.Year || date.Month > lastDate.Month)
|
|
|
- {
|
|
|
- max = 1;
|
|
|
- }
|
|
|
- break;
|
|
|
- case 3: //日流水
|
|
|
- if (date.Year > lastDate.Year || date.Month > lastDate.Month || date.Day > lastDate.Day)
|
|
|
- {
|
|
|
- max = 1;
|
|
|
- }
|
|
|
- break;
|
|
|
+ return;
|
|
|
}
|
|
|
- string number = max.ToString().PadLeft(model.NumberSize, '0');
|
|
|
- string serialNumber = string.IsNullOrWhiteSpace(model.Format) ? number
|
|
|
- : model.Format.ContainsIgnoreCase("{number}")
|
|
|
- ? model.Format.ReplaceIgnoreCase("{number}", number)
|
|
|
- : model.Format + number;
|
|
|
- //更新当前编号和最后时间
|
|
|
- model.LastTime = date;
|
|
|
- model.CurrentNumber = max;
|
|
|
- _rf_serialnumber.Update(model);
|
|
|
- return Wildcard.Replace(serialNumber, formData);
|
|
|
+ sentrys = _productExamineAppService.CalcSuggestTime(sentrys, kittingTimes);
|
|
|
+ await _mysql_crm_seorderentry.UpdateManyAsync(sentrys);
|
|
|
}
|
|
|
}
|
|
|
}
|