替代料
那么好的日子不写代码不肝博客岂不是浪费生命。关于bom做过erp的小伙伴应该都清楚,那么关于替代料应该也都知道,就是当某一个物料供应方没货源后我们的生产不至于因为没原料而停滞不前。于是我们做的erp也是增加了替代料的功能。
有不理解的小朋友先看一下效果图吧:
这张图片就是我们的bom列表,点击编辑之后显示的就是这条bom的信息和它的组成物料表,如下图:
这张图片上面展示的就是这条bom的信息,下面展示的就是组成这个产品的原料表,点击替代后效果和这张图是一奶同胞的效果,只不过上面展示的是这条物料的信息,下面展示的是它的可替代料表。
有图片作参考是不是就清晰很多了,那么接下来我们来说一下原理。
功能实现及原理
因为这是半成品的bom,在定义上还不属于成熟的成品,所以是和物料同放进物料表的,我们要做的就是在数据库里面新增一张关系表,里面要有bom的id,物料的id,替代料的id这三个id是必不可少的。
那么接下来说一下功能的实现,首先是第一张图片的实现,无外乎是一个查询,连表查询一下bom的关系表和物料表,代码粘一下就不具体解释了。
public async Task<Result<PageApi<ProductionDto>>> GetProductionData(BOMSearchDto model){RefAsync<int> totalCount = 0;var key = model.Key?.Trim();try{// SQL invar dbResult = await Db.Queryable<MaterialModel, PublicUnits>((f, a) => new JoinQueryInfos(JoinType.Left, f.PublicUnitsId == a.Id)).Where(f => SqlFunc.Subqueryable<SemiProductionBom>().Where(s => s.ProductionId == f.Id).Any()).WhereIF(!string.IsNullOrWhiteSpace(key), f => f.Encode.Contains(key) || f.Name.Contains(key) || f.Description.Contains(key)).Select((f, a) => new ProductionDto{ProductionId = f.Id,ProductionCode = f.Encode,ProductionName = f.Name,ProductionDesc = f.Description,ProductionUintSymbol = a.Symbol}).ToPageListAsync(model.Page, model.Limit, totalCount);return Result<PageApi<ProductionDto>>.IsSuccess(new PageApi<ProductionDto>{Items = dbResult,Total = totalCount});}catch (Exception ex){return Result<PageApi<ProductionDto>>.IsError(ex);}}
只粘了一个service里的实现代码,控制器的代码就不粘了,比较简单。主要是通过连表查询来显示出来bom的信息。加下来是点击编辑进入这条bom下物料的信息。
public async Task<Result<ProductionDto>> GetProductionDataById(int productionId = 0){if (productionId <= 0){return Result<ProductionDto>.IsFailed(message: "请输入有效id!");}var dbResult = await Db.Queryable<MaterialModel, PublicUnits>((f, a) => new JoinQueryInfos(JoinType.Left, f.PublicUnitsId == a.Id)).Where(f => f.Id.Equals(productionId)).Select((f, a) => new ProductionDto{ProductionId = f.Id,ProductionCode = f.Encode,ProductionName = f.Name,ProductionDesc = f.Description,ProductionUintSymbol = a.Symbol}).FirstAsync();if (dbResult == null){return Result<ProductionDto>.IsFailed(message: "未查询到数据!");}return Result<ProductionDto>.IsSuccess(dbResult);}
通过传递过来的id进行查询来实现上半部分的功能,这点应该是比较简单的。
在视图里面我们获取这条物料的id,然后作为条件传递给红圈选中的方法。
public async Task<Result<PageApi<ProductionBOMDto>>> GetProductionBOMData(BOMSearchDto model){RefAsync<int> totalCount = 0;try{// SQL invar dbResult = await Db.Queryable<SemiProductionBom, MaterialModel, PublicUnits>((f, a, b) => new JoinQueryInfos(JoinType.Left, f.MaterialId == a.Id,JoinType.Left, a.PublicUnitsId == b.Id)).Where(f => f.ProductionId == model.ProductionId).Select((f, a, b) => new ProductionBOMDto{Id = f.Id,MaterialId=a.Id,MaterialCode = a.Encode,MaterialName = a.Name,MaterialDesc = a.Description,MaterialUintSymbol = b.Symbol,MaterialUsage = f.MaterialUsage,Base = f.Base,MaterialType = f.MaterialType}).ToPageListAsync(model.Page, model.Limit, totalCount);return Result<PageApi<ProductionBOMDto>>.IsSuccess(new PageApi<ProductionBOMDto>{Items = dbResult,Total = totalCount});}catch (Exception ex){return Result<PageApi<ProductionBOMDto>>.IsError(ex);}}
这样做我们可以查到他下面的组成原料的所有信息,点击替代的时候有一点需要注意的是上面部分既要显示所选的这条物料的信息,还要显示出来它的上一级bom名字。
[HttpGet][Display(Name = "视图_半成品BOM物料替代")]public async Task<IActionResult> SemiProductionBOMEditMaterial2(int Id = 0){var dbResult = await _productionBOMService.GetProductionMaterialDataById(Id);Id = dbResult.Data.ProductionId;ViewBag.IsName = await _productionBOMService.GetProductionMaterialDataById2(Id);if (!dbResult.Success){return Json(ResultApi<ProductionBOMDto>.Result(dbResult));}return View(dbResult.Data);}
这样的话我们可以得到bom的id,那么我们需要在service里面在写一个通过bom的id来查询名字的方法,这样就实现了页面上即有原料的信息也有bom的名字。
接下来是查询下面的替代料信息。
public async Task<Result<PageApi<ProductionSubstituteDto>>> GetProductionBOMData2(SearchDto model,int materialId = 0,int productionId = 0){RefAsync<int> totalCount = 0;try{// SQL invar dbResult = await Db.Queryable<MaterialModel, PublicUnits, MaterialSubstitute>((f, a, b) => new JoinQueryInfos(JoinType.Left, f.PublicUnitsId == a.Id,JoinType.Left, f.Id==b.TiDaiId)).Where(f => SqlFunc.Subqueryable<MaterialSubstitute>().Where(s => s.BomId == productionId&&s.YuanLiaoId==materialId&&s.TiDaiId==f.Id).Any()).Select((f, a, b) => new ProductionSubstituteDto{Id = b.Id,ProductionSubstituteCode = f.Encode,ProductionSubstituteName = f.Name,ProductionSubstituteDesc = f.Description,ProductionSubstituteSymbol = a.Symbol,ProductionSubstituteXuHao = b.XuHao}).ToPageListAsync(model.Page, model.Limit, totalCount);//var dbResult = await Db.Queryable<MaterialSubstitute, SemiProductionBom, MaterialModel, PublicUnits>((f, a, b, c) => new JoinQueryInfos(// JoinType.Left, f.BomId == a.Id,// JoinType.Left, f.YuanLiaoId == b.Id,// JoinType.Left, b.PublicUnitsId == c.Id// ))// .Where((f, a, b, c) => f.BomId == productionId && f.YuanLiaoId == materialId)// .Select((f, a, b, c) => new ProductionSubstituteDto// {// Id = f.Id,// ProductionSubstituteCode = b.Encode,// ProductionSubstituteName = b.Name,// ProductionSubstituteDesc = b.Description,// ProductionSubstituteSymbol = c.Symbol,// ProductionSubstituteXuHao = f.XuHao// }) //.ToPageListAsync(model.Page, model.Limit, totalCount);//sql in//var dbResult = Db.Queryable<MaterialModel>().Where(it =>SqlFunc.Subqueryable<MaterialSubstitute>().Where(s => s.TiDaiId == it.Id).Any()).ToList();//原生SQL//var dbResult = Db.Ado.GetDataTable("select * from mtt_Material_Model where TypeId in(select TiDaiId from mtt_Material_Substitute where BomId=@bomid and YuanLiaoId=@yuanliaoid)", new { bomid = productionId, yuanliaoid = materialId });//var Sqlmate = "select * from mtt_Material_Model where TypeId in(select TiDaiId from mtt_Material_Substitute where BomId='" + productionId + "'and YuanLiaoId='" + materialId + "')";//var dbResult = Db.Ado.GetDataTable(Sqlmate);//List<ProductionSubstituteDto> ps = new List<ProductionSubstituteDto>();//ps = ConvertReToList(dbResult);return Result<PageApi<ProductionSubstituteDto>>.IsSuccess(new PageApi<ProductionSubstituteDto>{Items = dbResult,Total = totalCount});}catch (Exception ex){return Result<PageApi<ProductionSubstituteDto>>.IsError(ex);}}
这就用到了SQLSugar中的SQL in用法。代码中也有原生SQL语句,所以我们可以清晰的看出,我们是通过传过来的bom的id和原料的id来去关系表中查替代料的id,然后在拿我们查询到的id去物料表中查询相对应的信息。
这样页面上能看到的功能就可以实现了,还有增加修改就不细说了,但是需要注意一点的就是当你的替代料进行增加和修改的时候,一定不要忘了传bom的id还有物料的id。
切记!!!
兄弟们切记写代码一定要养成一个良好的代码习惯。
第一,一定要写注释;
第二,一定要规范命名。
如果两者都没遵循的话,你会发现你的代码不光乱到别人看不懂,你自己也看不懂。
一定要写注释,写注释,写注释!!!