Exemplo n.º 1
0
        public void Process(ProductionRequestContext context)
        {
            if (context.Request.SourceSegmentId == null)
            {
                return;
            }

            var request = context.Request;

            var sourceSegment = m_batchRepository.GetBatchById(context.Request.SourceSegmentId.Value).Ensure();

            request.OriginalBatchNumber = sourceSegment.Batch.BatchNumber;

            request.RecipeId             = sourceSegment.Batch.RecipeId.Ensure("Šarže nevznikla z existující receptury");
            request.ProducingBatchNumber = request.ProducingBatchNumber ?? sourceSegment.Batch.BatchNumber;

            if (request.ProducingAmount == null)
            {
                request.ProducingAmount = sourceSegment.Batch.Volume;
            }

            request.ProducingPrice = sourceSegment.Batch.ProductionWorkPrice;

            var batchAmount = new Amount(sourceSegment.Batch.Volume, sourceSegment.Batch.Unit);
            var available   = m_batchFacade.GetAvailableAmount(sourceSegment.Batch.Id);

            context.MinimalAmount = m_amountProcessor.Subtract(batchAmount, available);

            if (!context.Request.Components.Any())
            {
                ApplyComponents(sourceSegment, context);
            }
        }
Exemplo n.º 2
0
        public bool Populate(ISaleEventAllocation entity, AmountProcessor amountProcessor)
        {
            if (SaleEventId != 0 && SaleEventId != entity.SaleEventId)
            {
                return(false);
            }

            SaleEventId = entity.SaleEventId;

            if (string.IsNullOrWhiteSpace(EventName))
            {
                EventName = entity.SaleEvent.Name;
                SortDt    = entity.ReturnDt ?? entity.AllocationDt;
                Author    = entity.AllocationUser?.EMail;
            }

            m_blockedAmount  = amountProcessor.Add(m_blockedAmount, new Amount(entity.AllocatedQuantity, entity.Unit));
            m_returnedAmount = amountProcessor.Add(m_returnedAmount, new Amount(entity.ReturnedQuantity ?? 0m, entity.Unit));

            if (m_returnedAmount == null)
            {
                m_usedAmount = m_blockedAmount;
            }

            m_usedAmount = amountProcessor.Subtract(m_blockedAmount, m_returnedAmount);

            return(true);
        }
Exemplo n.º 3
0
        public void AssignOrderItemToBatch(int batchId, IPurchaseOrder order, long orderItemId, decimal assignmentQuantity)
        {
            var orderItem = GetAllOrderItems(order).FirstOrDefault(i => i.Id == orderItemId);

            if (orderItem == null)
            {
                throw new InvalidOperationException("Invalid OrderItemId");
            }

            var material = m_virtualProductFacade.GetOrderItemMaterialForSingleUnit(order, orderItem);

            var batch = m_batchRepository.GetBatchById(batchId);

            if (batch == null)
            {
                throw new InvalidOperationException("Invalid batch reference");
            }

            if (material.MaterialId != batch.Batch.MaterialId)
            {
                throw new InvalidOperationException("Batch material mismatch");
            }

            if (batch.IsLocked)
            {
                throw new InvalidOperationException($"Šarže '{batch.Batch?.BatchNumber}' je zamčená");
            }

            if (batch.IsClosed)
            {
                throw new InvalidOperationException($"Šarže '{batch.Batch?.BatchNumber}' je uzavřená");
            }

            ReleaseBatchAmountCache(batchId);

            using (var tx = m_database.OpenTransaction())
            {
                var available = GetAvailableAmount(batchId);

                var subtracted = m_amountProcessor.Subtract(
                    available,
                    new Amount(assignmentQuantity, material.Amount.Unit));

                if (subtracted.Value < 0m)
                {
                    throw new InvalidOperationException($"Požadované množství {new Amount(assignmentQuantity, material.Amount.Unit)} již není k dispozici v šarži {batch.Batch.BatchNumber}");
                }

                m_orderRepository.UpdateOrderItemBatch(orderItem, batchId, assignmentQuantity);

                tx.Commit();

                ReleaseBatchAmountCache(batchId);
            }
        }
Exemplo n.º 4
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)}");
            }
        }
Exemplo n.º 5
0
        public void SaveEvent(int eventTypeId, int materialId, string batchNumber, decimal quantity, string reason,
                              string unitSymbol, long?sourceOrderId = null)
        {
            var eventType = GetAllEventTypes().FirstOrDefault(et => et.Id == eventTypeId).Ensure();

            if (!eventType.IsSubtracting)
            {
                throw new NotSupportedException("Toto jeste neni");
            }

            if (eventType.RequiresNote && ((reason?.Trim() ?? string.Empty).Length < 5))
            {
                throw new InvalidOperationException("Důvod musí mít alespoň 5 znaků");
            }

            var material = m_materialRepository.GetMaterialById(materialId).Ensure();

            if (!material.AutomaticBatches && string.IsNullOrWhiteSpace(batchNumber?.Trim()))
            {
                throw new InvalidOperationException("Je třeba zadat číslo šarže");
            }

            var unit = material.NominalUnit;

            if (!string.IsNullOrWhiteSpace(unitSymbol))
            {
                unit = m_unitRepository.GetUnitBySymbol(unitSymbol);
                if (unit == null || (!m_conversionHelper.AreCompatible(material.NominalUnit.Id, unit.Id)))
                {
                    throw new InvalidOperationException($"Pro materiál \"{material.Name}\" nelze použít jednotku \"{unitSymbol}\"");
                }
            }

            var batches = new List <IMaterialBatch>();

            if (!string.IsNullOrWhiteSpace(batchNumber))
            {
                batches.AddRange(m_batchRepository.GetBatches(new BatchKey(material.Id, batchNumber)).OrderBy(b => b.Created));
            }
            else
            {
                batches.AddRange(m_batchRepository
                                 .GetMaterialBatches(DateTime.Now.AddYears(-2), DateTime.Now.AddYears(99), true, materialId, false,
                                                     false, false).Select(b => b.Batch).OrderBy(b => b.Created));
            }

            var eventAmount = new Amount(quantity, unit);
            var groupingKey = Guid.NewGuid().ToString("N");
            var eventDt     = DateTime.Now;

            using (var tx = m_cache.OpenTransaction())
            {
                foreach (var batch in batches)
                {
                    var available = m_batchFacade.Value.GetAvailableAmount(batch.Id);

                    if (available.IsNotPositive)
                    {
                        continue;
                    }

                    var toProcess = m_amountProcessor.Min(available, eventAmount);

                    var evt = m_cache.New <IMaterialStockEvent>();
                    evt.EventGroupingKey      = groupingKey;
                    evt.BatchId               = batch.Id;
                    evt.Delta                 = toProcess.Value;
                    evt.UnitId                = toProcess.Unit.Id;
                    evt.Note                  = reason;
                    evt.TypeId                = eventTypeId;
                    evt.UserId                = m_session.User.Id;
                    evt.EventDt               = eventDt;
                    evt.SourcePurchaseOrderId = sourceOrderId;
                    m_cache.Save(evt);

                    m_batchFacade.Value.ReleaseBatchAmountCache(batch.Id);

                    eventAmount = m_amountProcessor.Subtract(eventAmount, toProcess);

                    if (!eventAmount.IsPositive)
                    {
                        break;
                    }
                }

                tx.Commit();
            }
        }
Exemplo n.º 6
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");
            }
        }