示例#1
0
        private IEnumerable <MaterialComponent> ProcessMaterialEntries(string[] materialEntries)
        {
            foreach (var textEntry in materialEntries.Where(s => !string.IsNullOrWhiteSpace(s)))
            {
                var entry = MaterialEntry.Parse(textEntry);

                if (!(entry.Amount > 0m))
                {
                    throw new ArgumentException($"Chybné množství {entry.Amount} - musí být větší než 0");
                }

                var material = m_materialRepository.GetMaterialByName(entry.MaterialName);
                if (material == null)
                {
                    throw new ArgumentException($"Materiál \"{entry.MaterialName}\" neexistuje");
                }

                var entryUnit = m_unitRepository.GetUnitBySymbol(entry.UnitName);
                if (entryUnit == null)
                {
                    throw new ArgumentException($"Neznámá jednotka \"{entry.UnitName}\"");
                }

                if (!m_unitConversionHelper.AreCompatible(material.NominalUnit.Id, entryUnit.Id))
                {
                    throw new ArgumentException($"Pro materiál \"{entry.MaterialName}\" nelze použít jednotku \"{entry.UnitName}\", protože není převoditelná na nominální jednotku materiálu \"{material.NominalUnit.Symbol}\"");
                }

                yield return(new MaterialComponent(entryUnit, material, entry.Amount, null));
            }
        }
示例#2
0
        public IMaterialThreshold SaveThreshold(int materialId, decimal value, int unitId)
        {
            var material = m_materialRepository.GetMaterialById(materialId);

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

            if (!m_unitConvertor.AreCompatible(material.NominalUnit.Id, unitId))
            {
                throw new InvalidOperationException($"Zvolenou jednotku nelze použít pro materiál \"{material.Name}\"");
            }

            var existing = GetThreshold(materialId) ??
                           m_database.New <IMaterialThreshold>(th => th.MaterialId = materialId);

            if ((existing.UnitId == unitId) && (existing.ThresholdQuantity == value))
            {
                return(existing);
            }

            existing.UnitId            = unitId;
            existing.ThresholdQuantity = value;
            existing.ProjectId         = m_session.Project.Id;
            existing.UpdateUserId      = m_session.User.Id;
            existing.UpdateDt          = DateTime.Now;

            m_database.Save(existing);

            m_cache.Remove(c_cacheKey);

            return(existing);
        }
示例#3
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();
            }
        }
示例#4
0
        public MaterialBatchComponent SaveBottomLevelMaterialBatch(int id, IMaterial material, decimal amount, IMaterialUnit unit, string batchNr, DateTime receiveDt, decimal price, string invoiceNr, string supplierName, string currencySymbol, string variableSymbol)
        {
            if ((material.ProjectId != m_session.Project.Id) || (unit.ProjectId != m_session.Project.Id))
            {
                throw new InvalidOperationException("Illegal entity reference");
            }

            int?supplierId = null;

            if (!string.IsNullOrWhiteSpace(supplierName))
            {
                var supplier =
                    m_supplierRepository.GetSuppliers()
                    .FirstOrDefault(s => s.Name.Equals(supplierName, StringComparison.InvariantCultureIgnoreCase));

                if (supplier == null)
                {
                    throw new InvalidOperationException($"Nenalezen dodavatel \"{supplierName}\"");
                }

                supplierId = supplier.Id;
            }

            MaterialBatchComponent result;

            using (var tx = m_database.OpenTransaction())
            {
                IMaterialBatch entity;
                if (id > 0)
                {
                    throw new InvalidOperationException("UPDATE not implemented => Currency conversion");

                    entity =
                        GetBatchQuery()
                        .Where(b => (b.Id == id) && (b.ProjectId == m_session.Project.Id))
                        .Execute()
                        .FirstOrDefault();
                    if (entity == null)
                    {
                        throw new InvalidOperationException("Illegal entity reference");
                    }
                }
                else
                {
                    entity           = m_database.New <IMaterialBatch>();
                    entity.AuthorId  = m_session.User.Id;
                    entity.ProjectId = m_session.Project.Id;

                    var materialId = material.Id;

                    var existingBatchNr =
                        m_database.SelectFrom <IMaterialBatch>()
                        .Where(
                            b =>
                            (b.ProjectId == m_session.Project.Id) && (b.MaterialId == materialId) &&
                            (b.BatchNumber == batchNr))
                        .Execute()
                        .FirstOrDefault();

                    if (existingBatchNr != null)
                    {
                        throw new InvalidOperationException("Již existuje šarže se zadaným číslem");
                    }
                }

                if (!m_conversionHelper.AreCompatible(material.NominalUnitId, unit.Id))
                {
                    throw new InvalidOperationException(
                              $"Nelze použít jednotku '{unit.Symbol}' pro materiál '{material.Name}' protože není převoditelná na nominální jednotku materiálu '{material.NominalUnit}'");
                }

                if ((material.RequiresPrice == true) && (Math.Abs(price) < 0.000001m))
                {
                    throw new InvalidOperationException("Cena je povinný údaj");
                }

                if ((material.RequiresInvoiceNr == true) && string.IsNullOrWhiteSpace(invoiceNr))
                {
                    throw new InvalidOperationException("Číslo faktury je povinný údaj");
                }

                if ((material.RequiresInvoiceNr == true) && string.IsNullOrWhiteSpace(variableSymbol))
                {
                    throw new InvalidOperationException("Var. symbol je povinný údaj");
                }

                if ((material.RequiresSupplierReference == true) && (supplierId == null))
                {
                    throw new InvalidOperationException("Dodavatel je povinný údaj");
                }

                entity.BatchNumber = batchNr;
                entity.Created     = receiveDt;
                entity.MaterialId  = material.Id;
                entity.Volume      = amount;
                entity.UnitId      = unit.Id;

                entity.Price = m_currencyConversionHelper.TryConvertToPrimaryCurrency(currencySymbol,
                                                                                      price,
                                                                                      c => entity.PriceConversionId = c.Id);

                entity.Note             = string.Empty;
                entity.IsAvailable      = true;
                entity.InvoiceNr        = invoiceNr;
                entity.InvoiceVarSymbol = variableSymbol;
                entity.SupplierId       = supplierId;

                m_database.Save(entity);

                result = GetBatchById(entity.Id);

                if (result.Components.Any())
                {
                    throw new InvalidOperationException($"Materiál '{material.Name}' nelze naskladnit, protože se skládá z jiných materiálů. Použijte prosím funkci Výroba");
                }

                m_materialBatchFacade.Value.ReleaseBatchAmountCache(result.Batch);

                tx.Commit();
            }

            return(result);
        }
示例#5
0
        public void Process(ProductionRequestContext context)
        {
            var material = m_materialFacade.GetMaterialInfo(context.Recipe.ProducedMaterialId);

            context.Request.MaterialName = material.MaterialName;

            // Batch number
            if (string.IsNullOrWhiteSpace(context.Request.ProducingBatchNumber))
            {
                if (material.AutomaticBatches)
                {
                    context.Request.ProducingBatchNumber = material.AutoBatchNr;
                }
                else
                {
                    context.InvalidateRequest("Nutno vyplnit číslo šarže");
                }
            }

            // Unit
            while (true)
            {
                if (string.IsNullOrWhiteSpace(context.Request.ProducingUnitSymbol))
                {
                    context.Request.ProducingUnitSymbol = material.PreferredUnitSymbol;
                    break;
                }

                if (!context.Request.ProducingUnitSymbol.Equals(material.PreferredUnitSymbol, StringComparison.InvariantCultureIgnoreCase))
                {
                    var usedUnit = m_unitRepository.GetUnitBySymbol(context.Request.ProducingUnitSymbol.Trim());
                    if (usedUnit == null)
                    {
                        context.Request.ProducingUnitSymbol = null;
                        continue;
                    }

                    var mainUnit = m_unitRepository.GetUnitBySymbol(material.PreferredUnitSymbol);
                    if (!m_conversionHelper.AreCompatible(usedUnit.Id, mainUnit.Id))
                    {
                        context.Request.ProducingUnitSymbol = null;
                        continue;
                    }
                }

                break;
            }

            context.RequestedAmount     = new Amount(context.Request.ProducingAmount ?? 0m, m_unitRepository.GetUnitBySymbol(context.Request.ProducingUnitSymbol));
            context.NominalRecipeAmount = new Amount(context.Recipe.RecipeProducedAmount, m_unitRepository.GetUnit(context.Recipe.ProducedAmountUnitId));

            var commonUnit = m_conversionHelper.GetSmallestCompatibleUnit(context.RequestedAmount.Unit);

            var convertedRequestedAmount = m_conversionHelper.ConvertAmount(context.RequestedAmount, commonUnit.Id);
            var convertedNominalAmount   = m_conversionHelper.ConvertAmount(context.NominalRecipeAmount, commonUnit.Id);

            context.ComponentMultiplier = convertedRequestedAmount.Value / convertedNominalAmount.Value;

            if (context.MinimalAmount != null && m_amountProcessor.GreaterThan(context.MinimalAmount, context.RequestedAmount))
            {
                context.InvalidateRequest($"Nové množství nesmí být méně než {context.MinimalAmount}, protože tolik již bylo spotřebováno");
            }
        }
示例#6
0
        public RecipeInfo SaveRecipe(int materialId, int recipeId, string recipeName, decimal productionPrice,
                                     Amount producedAmount,
                                     string note, IEnumerable <RecipeComponentModel> components)
        {
            using (var tx = m_database.OpenTransaction())
            {
                var recipeMaterial = m_materialRepository.GetMaterialById(materialId).Ensure();
                if (!recipeMaterial.IsManufactured)
                {
                    throw new InvalidOperationException(
                              $"Material {recipeMaterial.Name} není nastaven jako vyráběný (podle skladu {recipeMaterial.InventoryName}, do kterého patří)");
                }

                var allMaterialRecipes = m_database.SelectFrom <IRecipe>().Join(r => r.Components)
                                         .Where(r => r.ProjectId == m_session.Project.Id)
                                         .Where(r => r.ProducedMaterialId == materialId).Execute().ToList();

                if (allMaterialRecipes.Any(r =>
                                           r.Id != recipeId && r.RecipeName.Equals(recipeName, StringComparison.InvariantCultureIgnoreCase)))
                {
                    throw new InvalidOperationException(
                              $"Pro \"{recipeMaterial.Name}\" již existuje receptura s názvem \"{recipeName}\"");
                }

                if (!m_conversionHelper.AreCompatible(recipeMaterial.NominalUnit.Id, producedAmount.Unit.Id))
                {
                    throw new InvalidOperationException(
                              $"Pro \"{recipeMaterial.Name}\" nelze použít jednotku \"{producedAmount.Unit.Symbol}\"");
                }

                if (producedAmount.IsNotPositive)
                {
                    throw new InvalidOperationException("Výsledné množství musí být kladné číslo");
                }

                var entity = allMaterialRecipes.FirstOrDefault(r => r.Id == recipeId);

                if ((entity == null) && (recipeId > 0))
                {
                    throw new InvalidOperationException("!");
                }

                entity = entity ?? m_database.New <IRecipe>(r =>
                {
                    r.ValidFrom    = DateTime.Now;
                    r.CreateUserId = m_session.User.Id;
                    r.ProjectId    = m_session.Project.Id;
                });

                entity.RecipeName             = recipeName;
                entity.ProducedMaterialId     = recipeMaterial.Id;
                entity.RecipeProducedAmount   = producedAmount.Value;
                entity.ProducedAmountUnitId   = producedAmount.Unit.Id;
                entity.ProductionPricePerUnit = productionPrice > 0 ? (decimal?)productionPrice : null;
                entity.Note = note;

                m_database.Save(entity);

                var transfSrcFound = false;
                var usedMaterials  = new HashSet <int>();

                foreach (var srcComponent in components)
                {
                    if (srcComponent.IsTransformationSource)
                    {
                        if (transfSrcFound)
                        {
                            throw new InvalidOperationException($"Pouze jedna slozka muze byt hlavni");
                        }

                        transfSrcFound = true;
                    }

                    var componetMaterial = m_materialRepository.GetMaterialById(srcComponent.MaterialId).Ensure();

                    if (!srcComponent.Amount.IsPositive)
                    {
                        throw new InvalidOperationException($"Množství složky {componetMaterial.Name} musí být kladné číslo");
                    }

                    if (!m_conversionHelper.AreCompatible(componetMaterial.NominalUnit.Id, srcComponent.Amount.Unit.Id))
                    {
                        throw new InvalidOperationException(
                                  $"Pro \"{componetMaterial.Name}\" nelze použít jednotku \"{srcComponent.Amount.Unit.Symbol}\"");
                    }

                    if (!usedMaterials.Add(srcComponent.MaterialId))
                    {
                        throw new InvalidOperationException($"Materiál {componetMaterial.Name} je ve složení více než jednou");
                    }


                    var componentEntity =
                        entity.Components.FirstOrDefault(c => c.MaterialId == srcComponent.MaterialId) ??
                        m_database.New <IRecipeComponent>(
                            c =>
                    {
                        c.MaterialId = srcComponent.MaterialId;
                        c.RecipeId   = entity.Id;
                    });

                    componentEntity.IsTransformationInput = srcComponent.IsTransformationSource;
                    componentEntity.MaterialId            = componetMaterial.Id;
                    componentEntity.SortOrder             = srcComponent.SortOrder;
                    componentEntity.Amount = srcComponent.Amount.Value;
                    componentEntity.UnitId = srcComponent.Amount.Unit.Id;

                    m_database.Save(componentEntity);
                }

                if (!usedMaterials.Any())
                {
                    throw new InvalidOperationException("Receptura musí mít alespoň jednu složku!");
                }

                foreach (var removedComponent in entity.Components.Where(rc => !usedMaterials.Contains(rc.MaterialId)))
                {
                    m_database.Delete(removedComponent);
                }

                tx.Commit();

                m_cache.Remove($"recipes{m_session.User.Id}");

                return(LoadRecipe(entity.Id));
            }
        }