示例#1
0
        public IEnumerable <Tuple <IMaterialBatch, Amount> > AutoResolve(int materialId, Amount requiredAmount, bool unresolvedAsNullBatch = false, int?batchId = null)
        {
            var batches = new List <MaterialBatchComponent>();

            if (batchId == null)
            {
                batches.AddRange(m_batchRepository.GetMaterialBatches(
                                     DateTime.Now.AddYears(-1),
                                     DateTime.Now.AddYears(1),
                                     false,
                                     materialId).OrderBy(b => b.Batch.Created));
            }
            else
            {
                var batch = m_batchRepository.GetBatchById(batchId.Value).Ensure();
                if (batch.Batch.MaterialId != materialId)
                {
                    throw new InvalidOperationException("Invalid entity reference");
                }

                batches.Add(batch);
            }

            foreach (var batch in batches)
            {
                if (!requiredAmount.IsPositive)
                {
                    yield break;
                }

                var batchAvailableAmount = GetAvailableAmount(batch.Batch.Id);
                if (!batchAvailableAmount.IsPositive)
                {
                    continue;
                }

                var amountToAllocate = m_amountProcessor.Min(requiredAmount, batchAvailableAmount);

                yield return(new Tuple <IMaterialBatch, Amount>(batch.Batch, amountToAllocate));

                requiredAmount = m_amountProcessor.Subtract(requiredAmount, amountToAllocate);
            }

            if (requiredAmount.IsPositive && unresolvedAsNullBatch)
            {
                yield return(new Tuple <IMaterialBatch, Amount>(null, requiredAmount));
            }
        }
示例#2
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();
            }
        }
示例#3
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");
            }
        }