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)); } }
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); }
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(); } }
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); }
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"); } }
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)); } }