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