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