|
|
@@ -0,0 +1,313 @@
|
|
|
+using SqlSugar;
|
|
|
+using WMS.BZModels;
|
|
|
+using WMS.Info;
|
|
|
+using WMS.BZSqlSugar;
|
|
|
+using WMS.BZModels.Models.KLHC;
|
|
|
+using System.Diagnostics;
|
|
|
+using Mapster;
|
|
|
+using System;
|
|
|
+using WMS.BZModels.Dto.KLHC.BillInvDtos;
|
|
|
+
|
|
|
+namespace WMS.BZServices.KLHC
|
|
|
+{
|
|
|
+ public class BaseInvService
|
|
|
+ {
|
|
|
+ private readonly Repository<BillInvnow> _billInvnowrepository;
|
|
|
+ private readonly Repository<BillInvflow> _billInvflowrepository;
|
|
|
+ private readonly BillLogService _billLogService;
|
|
|
+
|
|
|
+ public BaseInvService(Repository<BillInvnow> billInvnowrepository, BillLogService billLogService, Repository<BillInvflow> billInvflowrepository)
|
|
|
+ {
|
|
|
+ _billInvnowrepository = billInvnowrepository;
|
|
|
+ _billLogService = billLogService;
|
|
|
+ _billInvflowrepository = billInvflowrepository;
|
|
|
+ }
|
|
|
+
|
|
|
+ public PagedInfo<BillInvNowDto> GetPageList(Pagination pagination, BillInvNowQueryDto billInvNowQueryDto)
|
|
|
+ {
|
|
|
+ ISugarQueryable<BillInvNowDto> sugarQueryable = GetQueryable(billInvNowQueryDto);
|
|
|
+ var list = sugarQueryable.ToPage(pagination);
|
|
|
+
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+
|
|
|
+ public IList<BillInvNowDto> GetList(BillInvNowQueryDto billInvNowQueryDto)
|
|
|
+ {
|
|
|
+ ISugarQueryable<BillInvNowDto> sugarQueryable = GetQueryable(billInvNowQueryDto);
|
|
|
+ var list = sugarQueryable.ToList();
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+
|
|
|
+ private ISugarQueryable<BillInvNowDto> GetQueryable(BillInvNowQueryDto billInvNowQueryDto)
|
|
|
+ {
|
|
|
+ var predicate = Expressionable.Create<BillInvnow, BaseWarecell, BaseWarehouse>();
|
|
|
+
|
|
|
+ predicate = predicate.AndIF(!string.IsNullOrEmpty(billInvNowQueryDto?.KeyWord), (billInvnow, warecell, warehouse) => billInvnow.RFIDBarCode.Contains(billInvNowQueryDto.KeyWord) || billInvnow.ContGrpBarCode.Contains(billInvNowQueryDto.KeyWord) || billInvnow.MatCode.Contains(billInvNowQueryDto.KeyWord) || billInvnow.MatName.Contains(billInvNowQueryDto.KeyWord) || billInvnow.InvBarCode.Contains(billInvNowQueryDto.KeyWord));
|
|
|
+ predicate = predicate.AndIF(!string.IsNullOrEmpty(billInvNowQueryDto?.Id), (billInvnow, warecell, warehouse) => billInvnow.Id.ToString().Contains(billInvNowQueryDto.Id));
|
|
|
+ predicate = predicate.AndIF(!string.IsNullOrEmpty(billInvNowQueryDto?.WarehouseId), (billInvnow, warecell, warehouse) => billInvnow.WarehouseId.ToString().Contains(billInvNowQueryDto.WarehouseId));
|
|
|
+
|
|
|
+ predicate = predicate.AndIF(!string.IsNullOrEmpty(billInvNowQueryDto?.ContGrpId), (billInvnow, warecell, warehouse) => billInvnow.ContGrpId.ToString().Contains(billInvNowQueryDto.ContGrpId));
|
|
|
+ predicate = predicate.AndIF(!string.IsNullOrEmpty(billInvNowQueryDto?.EquContGrpId), (billInvnow, warecell, warehouse) => billInvnow.ContGrpId.ToString().Equals(billInvNowQueryDto.EquContGrpId));
|
|
|
+ predicate = predicate.AndIF(!string.IsNullOrEmpty(billInvNowQueryDto?.MatCode), (billInvnow, warecell, warehouse) => billInvnow.MatCode.Equals(billInvNowQueryDto.MatCode));
|
|
|
+ predicate = predicate.AndIF(!string.IsNullOrEmpty(billInvNowQueryDto?.MatName), (billInvnow, warecell, warehouse) => billInvnow.MatName.Equals(billInvNowQueryDto.MatName));
|
|
|
+ predicate = predicate.AndIF(!string.IsNullOrEmpty(billInvNowQueryDto?.RFIDBarCode), (billInvnow, warecell, warehouse) => billInvnow.RFIDBarCode.Contains(billInvNowQueryDto.RFIDBarCode));
|
|
|
+ predicate = predicate.AndIF(!string.IsNullOrEmpty(billInvNowQueryDto?.InvBarCode), (billInvnow, warecell, warehouse) => billInvnow.InvBarCode.Contains(billInvNowQueryDto.InvBarCode));
|
|
|
+
|
|
|
+ predicate = predicate.AndIF(!string.IsNullOrEmpty(billInvNowQueryDto?.PutRow), (billInvnow, warecell, warehouse) => billInvnow.PutRow.Equals(billInvNowQueryDto.PutRow));
|
|
|
+ predicate = predicate.AndIF(!string.IsNullOrEmpty(billInvNowQueryDto?.PutCol), (billInvnow, warecell, warehouse) => billInvnow.PutCol.Equals(billInvNowQueryDto.PutCol));
|
|
|
+ predicate = predicate.AndIF(!string.IsNullOrEmpty(billInvNowQueryDto?.PutLayer), (billInvnow, warecell, warehouse) => billInvnow.PutLayer.Equals(billInvNowQueryDto.PutLayer));
|
|
|
+ predicate = predicate.AndIF(!string.IsNullOrEmpty(billInvNowQueryDto?.Grade), (billInvnow, warecell, warehouse) => billInvnow.Grade.Contains(billInvNowQueryDto.Grade));
|
|
|
+ predicate = predicate.AndIF(billInvNowQueryDto != null && billInvNowQueryDto.OneInTimeBegin.HasValue, (billInvnow, warecell, warehouse) => billInvnow.OneInTime >= billInvNowQueryDto.OneInTimeBegin);
|
|
|
+ predicate = predicate.AndIF(billInvNowQueryDto != null && billInvNowQueryDto.OneInTimeEnd.HasValue, (billInvnow, warecell, warehouse) => billInvnow.OneInTime <= billInvNowQueryDto.OneInTimeEnd);
|
|
|
+ predicate = predicate.AndIF(billInvNowQueryDto != null && billInvNowQueryDto.ProductTimeBegin.HasValue, (billInvnow, warecell, warehouse) => billInvnow.ProductTime >= billInvNowQueryDto.ProductTimeBegin);
|
|
|
+ predicate = predicate.AndIF(billInvNowQueryDto != null && billInvNowQueryDto.ProductTimeEnd.HasValue, (billInvnow, warecell, warehouse) => billInvnow.ProductTime <= billInvNowQueryDto.ProductTimeEnd);
|
|
|
+
|
|
|
+ predicate = predicate.AndIF(!string.IsNullOrEmpty(billInvNowQueryDto?.Tunnel), (billInvnow, warecell, warehouse) => warecell.Tunnel.Equals(billInvNowQueryDto.Tunnel));
|
|
|
+ predicate = predicate.AndIF(!string.IsNullOrEmpty(billInvNowQueryDto?.Code), (billInvnow, warecell, warehouse) => warecell.Code.Contains(billInvNowQueryDto.Code));
|
|
|
+
|
|
|
+ predicate = predicate.AndIF(!string.IsNullOrEmpty(billInvNowQueryDto?.IsSurplus), (billInvnow, warecell, warehouse) => billInvnow.IsSurplus.Equals(billInvNowQueryDto.IsSurplus));
|
|
|
+ predicate = predicate.AndIF(!string.IsNullOrEmpty(billInvNowQueryDto?.IsRework), (billInvnow, warecell, warehouse) => billInvnow.IsRework.Equals(billInvNowQueryDto.IsRework));
|
|
|
+ predicate = predicate.AndIF(!string.IsNullOrEmpty(billInvNowQueryDto?.IsFail), (billInvnow, warecell, warehouse) => billInvnow.IsFail.Equals(billInvNowQueryDto.IsFail));
|
|
|
+ predicate = predicate.AndIF(!string.IsNullOrEmpty(billInvNowQueryDto?.IsFast), (billInvnow, warecell, warehouse) => billInvnow.IsFast.Equals(billInvNowQueryDto.IsFast));
|
|
|
+ predicate = predicate.AndIF(!string.IsNullOrEmpty(billInvNowQueryDto?.IsBack), (billInvnow, warecell, warehouse) => billInvnow.IsBack.Equals(billInvNowQueryDto.IsBack));
|
|
|
+ predicate = predicate.AndIF(!string.IsNullOrEmpty(billInvNowQueryDto?.ExecStateCode), (billInvnow, warecell, warehouse) => billInvnow.ExecStateCode.Equals(billInvNowQueryDto.ExecStateCode));
|
|
|
+ predicate = predicate.AndIF(!string.IsNullOrEmpty(billInvNowQueryDto?.SetGrpCode), (billInvnow, warecell, warehouse) => billInvnow.SetGrpCode.Equals(billInvNowQueryDto.SetGrpCode));
|
|
|
+ predicate = predicate.AndIF(!string.IsNullOrEmpty(billInvNowQueryDto?.ContGrpType), (billInvnow, warecell, warehouse) => billInvnow.ContGrpType.Equals(billInvNowQueryDto.ContGrpType));
|
|
|
+ predicate = predicate.AndIF(!string.IsNullOrEmpty(billInvNowQueryDto?.HWBarCode), (billInvnow, warecell, warehouse) => billInvnow.HWBarCode.Contains(billInvNowQueryDto.HWBarCode));
|
|
|
+ predicate = predicate.AndIF(!string.IsNullOrEmpty(billInvNowQueryDto?.ContGrpBarCode), (billInvnow, warecell, warehouse) => billInvnow.ContGrpBarCode.Contains(billInvNowQueryDto.ContGrpBarCode));
|
|
|
+ predicate = predicate.AndIF(!string.IsNullOrEmpty(billInvNowQueryDto?.BomMatCode), (billInvnow, warecell, warehouse) => billInvnow.BomMatCode.Equals(billInvNowQueryDto.BomMatCode));
|
|
|
+
|
|
|
+ if (!string.IsNullOrEmpty(billInvNowQueryDto?.InvStateCode))
|
|
|
+ {
|
|
|
+ var enums = (InvState)Enum.ToObject(typeof(InvState), Convert.ToInt32(billInvNowQueryDto?.InvStateCode));
|
|
|
+ predicate = predicate.AndIF(!string.IsNullOrEmpty(billInvNowQueryDto?.InvStateCode), (billInvnow, warecell, warehouse) => billInvnow.InvStateCode.Equals(enums.ToString()));
|
|
|
+ }
|
|
|
+ if (!string.IsNullOrEmpty(billInvNowQueryDto.IsManualOut) && billInvNowQueryDto.IsManualOut == "1")
|
|
|
+ {
|
|
|
+ predicate = predicate.AndIF(billInvNowQueryDto != null && billInvNowQueryDto.IsManualOut == "1", (billInvnow, warecell, warehouse) => SqlFunc.Subqueryable<BaseWarehouse>().Where(s => s.Id == billInvnow.WarehouseId && s.TypeNum == 1).Any());
|
|
|
+ }
|
|
|
+ var sugarQueryable = _billInvnowrepository.Context.Queryable<BillInvnow, BaseWarecell, BaseWarehouse>((billInvnow, warecell, warehouse) => new object[] {
|
|
|
+ JoinType.Left,billInvnow.ContGrpId == warecell.ContGrpId && billInvnow.WarehouseId ==warecell.WarehouseId , JoinType.Left, billInvnow.WarehouseId==warehouse.Id
|
|
|
+ , JoinType.Left, warecell.WarehouseId==warehouse.Id}).Where(predicate.ToExpression())
|
|
|
+ .Select((billInvnow, warecell, warehouse) => new BillInvNowDto
|
|
|
+ {
|
|
|
+ Id = billInvnow.Id.ToString(),
|
|
|
+ WarehouseId = billInvnow.WarehouseId.ToString(),
|
|
|
+ WarehouseName = warehouse.Name,
|
|
|
+ WarehouseTypeNum = warehouse.TypeNum,
|
|
|
+ WarehouseCode = warehouse.Code,
|
|
|
+ ContGrpId = billInvnow.ContGrpId.ToString(),
|
|
|
+ ContGrpBarCode = billInvnow.ContGrpBarCode,
|
|
|
+ ContGrpType = (int)billInvnow.ContGrpType,
|
|
|
+ BoxBarCode = billInvnow.BoxBarCode,
|
|
|
+ BomDocsNo = billInvnow.BomDocsNo,
|
|
|
+ BomMatId = billInvnow.BomMatId.ToString(),
|
|
|
+ BomMatCode = billInvnow.BomMatCode,
|
|
|
+ BomMatName = billInvnow.BomMatName,
|
|
|
+ BomSetId = billInvnow.BomSetId.ToString(),
|
|
|
+ ExecStateCode = billInvnow.ExecStateCode,
|
|
|
+ InvStateCode = billInvnow.InvStateCode,
|
|
|
+ ExecDocsNo = billInvnow.ExecDocsNo,
|
|
|
+ ExecDocsRowNo = billInvnow.ExecDocsRowNo,
|
|
|
+ ExecDocsTypeCode = billInvnow.ExecDocsTypeCode,
|
|
|
+ InvInOut = (int)billInvnow.InvInOut,
|
|
|
+ ExecWho = billInvnow.ExecWho,
|
|
|
+ ExecTime = billInvnow.ExecTime,
|
|
|
+ PutRow = billInvnow.PutRow,
|
|
|
+ PutCol = billInvnow.PutCol,
|
|
|
+ PutLayer = billInvnow.PutLayer,
|
|
|
+ InvBarCode = billInvnow.InvBarCode,
|
|
|
+ InDocsNo = billInvnow.InDocsNo,
|
|
|
+ InDocsRowNo = billInvnow.InDocsRowNo,
|
|
|
+ SuppCode = billInvnow.SuppCode,
|
|
|
+ SuppName = billInvnow.SuppName,
|
|
|
+ CustCode = billInvnow.CustCode,
|
|
|
+ CustName = billInvnow.CustName,
|
|
|
+ MatId = billInvnow.MatId.ToString(),
|
|
|
+ MatCode = billInvnow.MatCode,
|
|
|
+ MatName = billInvnow.MatName,
|
|
|
+ TolWQty = billInvnow.TolWQty,
|
|
|
+ NetWQty = billInvnow.NetWQty,
|
|
|
+ TareWQty = billInvnow.TareWQty,
|
|
|
+ LengthQty = billInvnow.LengthQty,
|
|
|
+ CaQty = billInvnow.CaQty,
|
|
|
+ SolderQty = billInvnow.SolderQty,
|
|
|
+ ContUsageQty = billInvnow.ContUsageQty,
|
|
|
+ BatchNo = billInvnow.BatchNo,
|
|
|
+ ProductTime = billInvnow.ProductTime,
|
|
|
+ OneInTime = billInvnow.OneInTime,
|
|
|
+ RodBarCode = billInvnow.RodBarCode,
|
|
|
+ HWBarCode = billInvnow.HWBarCode,
|
|
|
+ RFIDBarCode = billInvnow.RFIDBarCode,
|
|
|
+ CLBarCode = billInvnow.CLBarCode,
|
|
|
+ HWTypeCode = billInvnow.HWTypeCode,
|
|
|
+ BoilerNo = billInvnow.BoilerNo,
|
|
|
+ PackNo = billInvnow.PackNo,
|
|
|
+ BrandNo = billInvnow.BrandNo,
|
|
|
+ ExecStd = billInvnow.ExecStd,
|
|
|
+ LicenceCode = billInvnow.LicenceCode,
|
|
|
+ IsSurplus = billInvnow.IsSurplus,
|
|
|
+ IsRework = billInvnow.IsRework,
|
|
|
+ IsBlack = billInvnow.IsBlack,
|
|
|
+ IsCore = billInvnow.IsCore,
|
|
|
+ IsFast = billInvnow.IsFast,
|
|
|
+ IsFail = billInvnow.IsFail,
|
|
|
+ FailReason = billInvnow.FailReason,
|
|
|
+ SilkTypeCode = billInvnow.SilkTypeCode,
|
|
|
+ Grade = billInvnow.Grade,
|
|
|
+ IsBack = billInvnow.IsBack,
|
|
|
+ BackReason = billInvnow.BackReason,
|
|
|
+ IsTorsChk = billInvnow.IsTorsChk,
|
|
|
+ TorsChkQty = billInvnow.TorsChkQty,
|
|
|
+ TorsChkTime = billInvnow.TorsChkTime,
|
|
|
+ TorsChkValue = billInvnow.TorsChkValue,
|
|
|
+ TorsChkMachCode = billInvnow.TorsChkMachCode,
|
|
|
+ ProcessDocsCode = billInvnow.ProcessDocsCode,
|
|
|
+ ProductMachCode = billInvnow.ProductMachCode,
|
|
|
+ ProductLineNo = billInvnow.ProductLineNo,
|
|
|
+ SetGrpCode = billInvnow.SetGrpCode,
|
|
|
+ SideNum = billInvnow.SideNum,
|
|
|
+ AddWho = billInvnow.AddWho,
|
|
|
+ AddTime = billInvnow.AddTime,
|
|
|
+ EditWho = billInvnow.EditWho,
|
|
|
+ EditTime = billInvnow.EditTime,
|
|
|
+ Size = billInvnow.Size,
|
|
|
+ Memo = billInvnow.Memo,
|
|
|
+ Tunnel = warecell.Tunnel,
|
|
|
+ Code = warecell.Code,
|
|
|
+ CellState = warecell.IsStop,
|
|
|
+ }).MergeTable();
|
|
|
+ return sugarQueryable;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void ChangeSetGrp(LoginUserInfo loginUser, ChangeSetGrpModel entity)
|
|
|
+ {
|
|
|
+ if (string.IsNullOrWhiteSpace(entity.SetGrp))
|
|
|
+ {
|
|
|
+ throw new ArgumentException("跺型编码不能为空");
|
|
|
+ }
|
|
|
+ if (string.IsNullOrWhiteSpace(entity.NewSetGrp))
|
|
|
+ {
|
|
|
+ throw new ArgumentException("修改的跺型编码不能为空");
|
|
|
+ }
|
|
|
+ if (string.IsNullOrWhiteSpace(entity.WarehouseId))
|
|
|
+ {
|
|
|
+ throw new ArgumentException("仓库不能为空");
|
|
|
+ }
|
|
|
+ var predicate = Expressionable.Create<BillInvnow>();
|
|
|
+ predicate.And(it => it.WarehouseId.ToString().ToUpper() == entity.WarehouseId.ToUpper());
|
|
|
+ predicate.And(it => it.InvStateCode == InvState.InvEcecState_In.ToString());
|
|
|
+ predicate.And(it => it.SetGrpCode == entity.SetGrp);
|
|
|
+
|
|
|
+ var lists = _billInvnowrepository.Queryable().Where(predicate.ToExpression());
|
|
|
+ if (lists == null || !lists.Any())
|
|
|
+ {
|
|
|
+ throw new ArgumentException("没有该跺型的数据。");
|
|
|
+ }
|
|
|
+
|
|
|
+ _billLogService.WriteLog(loginUser, entity, $"跺型由:{entity.SetGrp}改为:{entity.NewSetGrp} ", "WMS.BZServices.FJ.BaseInvService", "ChangeSetGrp", new Stopwatch(), ELogType.Work, null);
|
|
|
+
|
|
|
+ _billInvnowrepository.UpdateModelColumns(p => new BillInvnow
|
|
|
+ {
|
|
|
+ SetGrpCode = entity.NewSetGrp
|
|
|
+ }, predicate.ToExpression());
|
|
|
+ }
|
|
|
+
|
|
|
+ public void UpdateStockState(string Code, int Status, string userId)
|
|
|
+ {
|
|
|
+ var stock = _billInvnowrepository.GetFirst(p => p.ContGrpBarCode == Code);
|
|
|
+ if (stock == null)
|
|
|
+ {
|
|
|
+ throw new ArgumentException("组盘信息不存在!");
|
|
|
+ }
|
|
|
+ var invstatus = ((InvState)Status).ToString();
|
|
|
+ var InvStateCode = invstatus + "";
|
|
|
+ var p = _billInvnowrepository.UpdateSetColumnsTrue(p => new BillInvnow()
|
|
|
+ {
|
|
|
+ InvStateCode = InvStateCode,
|
|
|
+ EditTime = DateTime.Now
|
|
|
+ }, p => p.ContGrpBarCode == stock.ContGrpBarCode);
|
|
|
+ if (!p)
|
|
|
+ {
|
|
|
+ throw new ArgumentException(stock.ContGrpBarCode + "更新失败!");
|
|
|
+ }
|
|
|
+ var flow = stock.Adapt<BillInvflow>();
|
|
|
+ flow.Id = IdFactory.NewId();
|
|
|
+ flow.AddTime = DateTime.Now;
|
|
|
+ flow.EditTime = DateTime.Now;
|
|
|
+ flow.InvStateCode = invstatus;
|
|
|
+ _billInvflowrepository.Insert(flow);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void Deletes(string[] ids, string userId)
|
|
|
+ {
|
|
|
+ if (ids == null || ids.Length == 0)
|
|
|
+ {
|
|
|
+ throw BZSysExCore.ThrowFailException("库存Id不能为空!");
|
|
|
+ }
|
|
|
+ var list = _billInvnowrepository.Queryable().Where(o => ids.Contains(o.Id.ToString())).ToList();
|
|
|
+ if (!list.Any())
|
|
|
+ {
|
|
|
+ throw new ArgumentException("没有选择库存数据!");
|
|
|
+ }
|
|
|
+
|
|
|
+ _billInvnowrepository.UseTranAction(() =>
|
|
|
+ {
|
|
|
+ foreach (var item in list)
|
|
|
+ {
|
|
|
+ _billInvnowrepository.Deleteable().Where(it => it.Id == item.Id).ExecuteCommand();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<EnumEntity> InvStateList()
|
|
|
+ {
|
|
|
+ return BZModels.Extensions.EnumToList<InvState>();
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<EnumEntity> TaskStatusList()
|
|
|
+ {
|
|
|
+ return BZModels.Extensions.EnumToList<BZModels.TaskStatus>();
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<EnumEntity> TaskTypeList()
|
|
|
+ {
|
|
|
+ return BZModels.Extensions.EnumToList<TaskType>();
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<EnumEntity2> TaskBusTypeList()
|
|
|
+ {
|
|
|
+ return BZModels.Extensions.EnumToListDesc<TaskBusType>();
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<EnumEntity> FackbeekTypeList()
|
|
|
+ {
|
|
|
+ return BZModels.Extensions.EnumToList<FackbeekType>();
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<EnumEntity> ContGrpTypeList()
|
|
|
+ {
|
|
|
+ return BZModels.Extensions.EnumToList<ContGrpType>();
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<EnumEntity> DocTypeList()
|
|
|
+ {
|
|
|
+ return BZModels.Extensions.EnumToList<DocType>();
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<EnumEntity> DocStateList()
|
|
|
+ {
|
|
|
+ return BZModels.Extensions.EnumToList<DocState>();
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<EnumEntity> LocationStateList()
|
|
|
+ {
|
|
|
+ return BZModels.Extensions.EnumToList<LocationState>();
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<EnumEntity> AutoManualOutTypeList()
|
|
|
+ {
|
|
|
+ return BZModels.Extensions.EnumToList<AutoManualOutType>();
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|