示例#1
0
        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();
            }
        }
示例#2
0
        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)}");
            }
        }
示例#3
0
        public Amount GetAvailableAmount(BatchKey batchKey)
        {
            var batches = m_batchRepository.GetBatches(batchKey);

            return(m_amountProcessor.Sum(batches.Select(b => GetAvailableAmount(b.Id))));
        }
示例#4
0
        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));
        }
示例#5
0
        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");
            }
        }