public void ApplyComponents(MaterialBatchComponent sourceSegment, ProductionRequestContext context) { var recipeComponents = m_recipeRepository.GetRecipe(sourceSegment.Batch.RecipeId.Ensure("Segment nevznikl z existující receptury, nelze změnit")).Components.OrderBy(c => c.SortOrder); var requestComponents = context.Request.Components; foreach (var recipeComponent in recipeComponents) { var compo = new ProductionComponent { MaterialId = recipeComponent.MaterialId, MaterialName = m_materialRepository.GetMaterialById(recipeComponent.MaterialId).Ensure().Name, SortOrder = recipeComponent.SortOrder }; requestComponents.Add(compo); var resolutions = sourceSegment.Components.Where(c => c.Batch.MaterialId == recipeComponent.MaterialId); var resIndex = new Dictionary <string, ProductionComponentResolution>(); var componentUnit = m_unitRepository.GetUnit(recipeComponent.UnitId); foreach (var r in resolutions) { var resolutionAmount = m_amountProcessor.Convert(new Amount(r.ComponentAmount, r.ComponentUnit), componentUnit); var batchAvailability = m_amountProcessor.Convert(m_batchFacade.GetAvailableAmount(r.Batch.Id), componentUnit); if (!resIndex.TryGetValue(r.Batch.BatchNumber, out var resolution)) { resolution = new ProductionComponentResolution { Amount = resolutionAmount.Value, BatchAvailableAmount = batchAvailability.Value, BatchAvailableAmountText = batchAvailability.ToString(), BatchCreationDt = StringUtil.FormatDate(r.Batch.Created), BatchNumber = r.Batch.BatchNumber, Key = Guid.NewGuid().ToString(), Sorter = r.Batch.Created.Ticks, UnitSymbol = componentUnit.Symbol }; compo.Resolutions.Add(resolution); resIndex.Add(r.Batch.BatchNumber, resolution); } else { resolution.Amount += resolutionAmount.Value; } } compo.LastClientAmount = m_amountProcessor .Sum(compo.Resolutions.Select(r => r.GetAmount(m_unitRepository)))?.ToString(); } }
private void ProcessResolutions(ProductionRequest request, IRecipeComponent recipeComponent, ProductionComponent requestComponent, decimal multiplier, DateTime sourceBatchesMadeBefore) { if (TryProcessTransformationInput(request, recipeComponent, requestComponent) && (!requestComponent.IsValid)) { return; } var requiredAmount = new Amount(recipeComponent.Amount * multiplier, m_unitRepository.GetUnit(recipeComponent.UnitId)); ClearUserAllocationsIfQuantityChanged(requestComponent, requiredAmount); var requiredBatchNr = recipeComponent.IsTransformationInput ? request.ProducingBatchNumber : null; var resolutions = m_batchFacade.ResolveMaterialDemand( recipeComponent.MaterialId, requiredAmount, requiredBatchNr, false, true, sourceBatchesMadeBefore, request.SourceSegmentId); RemoveComponentsNotProposedBySystem(requestComponent, resolutions, requiredAmount); AddMissingComponents(requestComponent, resolutions, requiredAmount, request.SourceSegmentId != null && request.IsFirstRound); var userAllocatedAmount = m_amountProcessor.Sum(requestComponent.Resolutions.Where(r => r.GetAmount(m_unitRepository) != null) .Select(r => r.GetAmount(m_unitRepository))) ?? new Amount(0, requiredAmount.Unit); var remaining = m_amountProcessor.Subtract(requiredAmount, userAllocatedAmount); if (!resolutions.CompletelyAllocated) { requestComponent.Invalidate("Potřebné množství není dostupné"); } if (remaining.IsPositive) { //seems we allocated the requested amount requestComponent.Invalidate($"Zbývá vložit {remaining}"); } else if (remaining.IsNegative) { requestComponent.Invalidate($"Přebývá {m_amountProcessor.Neg(remaining)}"); } }
public Amount GetAvailableAmount(BatchKey batchKey) { var batches = m_batchRepository.GetBatches(batchKey); return(m_amountProcessor.Sum(batches.Select(b => GetAvailableAmount(b.Id)))); }
public IEnumerable <MaterialLevelEntryModel> Load(int inventoryId) { var result = new List <MaterialLevelEntryModel>(); m_database.Sql().Call("GetMaterialLevelsReport").WithParam("@inventoryId", inventoryId).WithParam("@projectId", m_session.Project.Id) .ReadRows <int, string, string, int, decimal, string, string, string>((materialId, materialName, batchNumber, unitId, available, supName, supMail, supPhone) => { var entry = result.FirstOrDefault(r => r.MaterialId == materialId); if (entry == null) { entry = new MaterialLevelEntryModel(); result.Add(entry); entry.MaterialId = materialId; entry.MaterialName = materialName; entry.SupplierName = supName; entry.SupplierEmail = supMail; entry.SupplierPhone = supPhone; } if (available == 0) { return; } var batchModel = entry.Batches.FirstOrDefault(b => b.BatchNumber.Equals(batchNumber, StringComparison.InvariantCultureIgnoreCase) && b.UnitId == unitId); if (!string.IsNullOrWhiteSpace(batchNumber)) { if (batchModel == null) { batchModel = new BatchAmountModel { BatchNumber = batchNumber, UnitId = unitId }; entry.Batches.Add(batchModel); } batchModel.Value += available; } }); foreach (var r in result) { var threshold = m_thresholdRepository.GetThreshold(r.MaterialId); if (threshold != null) { r.Threshold = new Amount(threshold.ThresholdQuantity, m_unitRepository.GetUnit(threshold.UnitId)); } foreach (var batch in r.Batches) { batch.Amount = new Amount(batch.Value, m_unitRepository.GetUnit(batch.UnitId)); } r.Total = m_amountProcessor.Sum(r.Batches.Select(b => b.Amount)); if (string.IsNullOrWhiteSpace(r.UnitSymbol)) { var material = m_materialRepository.GetMaterialById(r.MaterialId); r.DefaultUnitSymbol = material.NominalUnit.Symbol; } r.HasWarning = r.Threshold != null && m_amountProcessor.GreaterThan(r.Threshold, r.Total ?? r.Threshold.ToZeroAmount()); } return(result.OrderBy(r => r.HasWarning ? 0 : 1).ThenBy(r => r.MaterialName)); }
private void SaveAllocation(int eventId, List <ISaleEventAllocation> existing, SaleEventAllocationDto dto) { var existingAllocations = existing .Where(a => a.Batch.MaterialId == dto.MaterialId && a.Batch.BatchNumber == dto.BatchNumber).ToList(); if (existing.Any() && !existingAllocations.Any()) { throw new InvalidOperationException("Pri zmene existujici prodejni akce nesmi byt zmeneny polozky, jen vracene mnozstvi"); } if (dto.ReturnedQuantity != null && m_amountProcessor.GreaterThan(dto.ReturnedQuantity, dto.AllocatedQuantity)) { throw new InvalidOperationException("Nelze vracet vetsi nez blokovane mnozstvi"); } if (!existingAllocations.Any()) { var batches = m_batchFacade.ProposeAllocations(dto.MaterialId, dto.BatchNumber, dto.AllocatedQuantity) .ToList(); if (batches.Any(b => b.Item1 == null)) { throw new InvalidOperationException($"Pozadovane mnozstvi {dto.AllocatedQuantity} {m_materialRepository.GetMaterialById(dto.MaterialId)?.Name} neni v sarzi {dto.BatchNumber} k dispozici"); } foreach (var batch in batches) { m_database.Save(m_database.New <ISaleEventAllocation>(a => { a.AllocationDt = DateTime.Now; a.AllocatedQuantity = batch.Item2.Value; a.UnitId = batch.Item2.Unit.Id; a.BatchId = batch.Item1.Value; a.AllocationUserId = m_session.User.Id; a.SaleEventId = eventId; if (dto.ReturnedQuantity != null) { a.ReturnedQuantity = dto.ReturnedQuantity.Value; a.ReturnDt = DateTime.Now; a.ReturnUserId = m_session.User.Id; } })); } return; } var totalAllocatedInDb = m_amountProcessor.Sum(existingAllocations.Select(a => new Amount(a.AllocatedQuantity, a.Unit))); if (!m_amountProcessor.AreEqual(totalAllocatedInDb, dto.AllocatedQuantity)) { throw new InvalidOperationException("Nelze zmenit alokovane mnozstvi pro existujici akci"); } var totalReturnedInDb = m_amountProcessor.Sum(existingAllocations.Where(a => a.ReturnedQuantity != null) .Select(a => new Amount(a.ReturnedQuantity.Value, a.Unit))); var returnedAmount = dto.ReturnedQuantity == null ? new Amount(0, dto.AllocatedQuantity.Unit) : dto.ReturnedQuantity; if (m_amountProcessor.AreEqual(totalReturnedInDb, returnedAmount)) { return; } if (m_amountProcessor.GreaterThan(totalReturnedInDb, returnedAmount)) { throw new InvalidOperationException("Nelze snizovat vracene mnozstvi"); } var newReturn = m_amountProcessor.Subtract(returnedAmount, totalReturnedInDb); foreach (var existingAloc in existingAllocations) { if (!newReturn.IsPositive) { break; } var alreadyReturnedHere = existingAloc.ReturnedQuantity == null ? new Amount(0, existingAloc.Unit) : new Amount(existingAloc.ReturnedQuantity.Value, existingAloc.Unit); var toReturnHere = m_amountProcessor.Subtract(new Amount(existingAloc.AllocatedQuantity, existingAloc.Unit), alreadyReturnedHere); if (!toReturnHere.IsPositive) { continue; } var actuallyReturningHere = m_amountProcessor.Min(toReturnHere, newReturn); existingAloc.ReturnedQuantity = actuallyReturningHere.Value; existingAloc.UnitId = actuallyReturningHere.Unit.Id; m_database.Save(existingAloc); newReturn = m_amountProcessor.Subtract(newReturn, actuallyReturningHere); } if (newReturn.IsPositive) { throw new InvalidOperationException("Nebylo mozne vratit vsechno pozadovane mnozstvi"); } }