/// <summary> /// Пересчет показателей возвратов от клиентов при отмене приемки накладной возврата от клиента /// </summary> public void ReturnFromClientWaybillFinalizationCancelled(ReturnFromClientWaybill waybill) { var receiptedIndicators = new List <ReceiptedReturnFromClientIndicator>(); foreach (var row in waybill.Rows) { ValidationUtils.Assert(row.SaleWaybillRow.SaleWaybill.Is <ExpenditureWaybill>(), "Расчет показателя для данного типа накладной реализации еще не реализован."); var saleWaybillRow = row.SaleWaybillRow.As <ExpenditureWaybillRow>(); ValidationUtils.Assert(saleWaybillRow.ReceiptedReturnCount >= row.ReturnCount, String.Format("Недостаточно возвращенного товара «{0}» для отмены приемки возврата.", row.Article.FullName)); saleWaybillRow.SetReturnCounts(saleWaybillRow.AcceptedReturnCount + row.ReturnCount, saleWaybillRow.ReceiptedReturnCount - row.ReturnCount); // уменьшаем точное возвращенное от клиента кол-во var receiptedIndicator = CreateReceiptedReturnFromClientIndicator(waybill.ReceiptDate.Value, row, -1); receiptedIndicators.Add(receiptedIndicator); } receiptedReturnFromClientIndicatorService.Update(waybill.ReceiptDate.Value, waybill.Deal.Id, waybill.Curator.Id, returnFromClientWaybillRepository.GetArticleBatchesSubquery(waybill.Id), receiptedIndicators); }
private void UpdateIndicatorsForReturnFromClientWaybill(ReturnFromClientWaybill waybill, short sign) { articleMovementFactualFinancialIndicatorService.Update(waybill.ReceiptDate.Value, null, null, waybill.Recipient.Id, waybill.RecipientStorage.Id /* берем МХ, на которое оформлен возврат */, ArticleMovementOperationType.ReturnFromClient, waybill.Id, sign * waybill.PurchaseCostSum, sign * waybill.RecipientAccountingPriceSum, sign * waybill.SalePriceSum); }
public void ReturnFromClientWaybill_Must_Throw_Exception_If_Curator_Is_Null() { try { returnFromClientWaybill = new ReturnFromClientWaybill("142", DateTime.Today, accountOrganization, deal, team, storage, returnFromClientReason, null, curator, DateTime.Now); Assert.Fail("Исключение не вызвано."); } catch (Exception ex) { Assert.AreEqual("Не указан куратор.", ex.Message); } }
public void ReturnFromClientWaybill_Must_Throw_Exception_If_Storage_Is_Null() { try { var rfcwb = new ReturnFromClientWaybill("142", DateTime.Today, accountOrganization, deal, team, null, returnFromClientReason, curator, curator, DateTime.Now); Assert.Fail("Исключение не вызвано."); } catch (Exception ex) { Assert.AreEqual("Не указано место хранения-приемщик.", ex.Message); } }
// TODO: провести рефакторинг расчета показателей (убрать дублирование) /// <summary> /// Пересчет показателей возвратов от клиентов при проводке накладной возврата от клиента /// </summary> public void ReturnFromClientWaybillAccepted(ReturnFromClientWaybill waybill) { // проведенные возвраты var acceptedIndicators = new List <AcceptedReturnFromClientIndicator>(); // возвраты на дату проводки накладной реализации var bySaleAcceptanceDateIndicators = new List <ReturnFromClientBySaleAcceptanceDateIndicator>(); // возвраты на дату отгрузки накладной реализации var bySaleShippingDateIndicators = new List <ReturnFromClientBySaleShippingDateIndicator>(); foreach (var row in waybill.Rows) { ValidationUtils.Assert(row.SaleWaybillRow.SaleWaybill.Is <ExpenditureWaybill>(), "Расчет показателя для данного типа накладной реализации еще не реализован."); var saleWaybillRow = row.SaleWaybillRow.As <ExpenditureWaybillRow>(); ValidationUtils.Assert(saleWaybillRow.AvailableToReturnCount >= row.ReturnCount, String.Format("Недостаточно реализованного товара «{0}» для возврата.", row.Article.FullName)); saleWaybillRow.SetReturnCounts(saleWaybillRow.AcceptedReturnCount + row.ReturnCount, saleWaybillRow.ReceiptedReturnCount); // увеличиваем проведенное возвращенное от клиента кол-во var acceptedIndicator = CreateAcceptedReturnFromClientIndicator(waybill.AcceptanceDate.Value, row, 1); acceptedIndicators.Add(acceptedIndicator); // увеличиваем возвраты на дату проводки накладной реализации // TODO: не самый оптимальный вариант расчета. В итоге тянет из БД данные для каждой позиции накладной возврата var bySaleAcceptanceDateIndicator = CreateReturnFromClientBySaleAcceptanceDateIndicator(row, 1); returnFromClientBySaleAcceptanceDateIndicatorService.Update(row.SaleWaybillRow.SaleWaybill.AcceptanceDate.Value, waybill.Deal.Id, waybill.Curator.Id, receiptWaybillRepository.GetRowSubQuery(row.ReceiptWaybillRow.Id), new List <ReturnFromClientBySaleAcceptanceDateIndicator>() { bySaleAcceptanceDateIndicator }); // увеличиваем возвраты на дату отгрузки накладной реализации // TODO: не самый оптимальный вариант расчета. В итоге тянет из БД данные для каждой позиции накладной возврата var bySaleShippingDateIndicator = CreateReturnFromClientBySaleShippingDateIndicator(row, 1); returnFromClientBySaleShippingDateIndicatorService.Update(row.SaleWaybillRow.SaleWaybill.As <ExpenditureWaybill>().ShippingDate.Value, waybill.Deal.Id, waybill.Curator.Id, receiptWaybillRepository.GetRowSubQuery(row.ReceiptWaybillRow.Id), new List <ReturnFromClientBySaleShippingDateIndicator>() { bySaleShippingDateIndicator }); } acceptedReturnFromClientIndicatorService.Update(waybill.AcceptanceDate.Value, waybill.Deal.Id, waybill.Curator.Id, returnFromClientWaybillRepository.GetArticleBatchesSubquery(waybill.Id), acceptedIndicators); }
public void ReturnFromClientWaybill_Attempt_To_Read_RecipientAccountingPriceSum_Before_Acceptance_Must_Throw_Exception() { try { var rfcwb = new ReturnFromClientWaybill("142", DateTime.Today, accountOrganization, deal, team, storage, returnFromClientReason, curator, curator, DateTime.Now); rfcwb.RecipientAccountingPriceSum = 100.5M; // пытаемся получить сумму в учетных ценах для непроведенной накладной var sum = rfcwb.RecipientAccountingPriceSum; Assert.Fail("Исключение не вызвано."); } catch (Exception ex) { Assert.AreEqual("Невозможно получить значение суммы товаров в учетных ценах для непроведенной накладной.", ex.Message); } }
public void ReturnFromClientWaybill_Must_Throw_Exception_If_RecipientAccountingPriceSum_Try_Set_AfterAccept() { try { var waybill = new ReturnFromClientWaybill("142", DateTime.Today, accountOrganization, deal, team, storage, returnFromClientReason, curator, curator, DateTime.Now); var row = new ReturnFromClientWaybillRow(saleRow1, 1); waybill.AddRow(row); waybill.RecipientAccountingPriceSum = 100.5M; waybill.Accept(Prices, false, curator, DateTime.Now); waybill.RecipientAccountingPriceSum = 101.5M; Assert.Fail("Исключение не вызвано."); } catch (Exception ex) { Assert.AreEqual("Невозможно установить значение суммы в учетных ценах, т.к. накладная уже проведена.", ex.Message); } }
/// <summary> /// Отмена возврата оплаты по возвращенным позициям /// </summary> /// <param name="returnFromClientWaybill">Накладная возврата товаров от клиента</param> /// <param name="receiptDate">Дата приемки накладной реализации товаров</param> public void CancelPaymentReturnToSales(ReturnFromClientWaybill returnFromClientWaybill, DateTime receiptDate) { // Получаем все возвраты оплаты по данной накладной возврата var returnedDistributions = dealPaymentDocumentRepository.GetDistributionsToReturnFromClientWaybillsForDestinationReturnFromClientWaybills(returnFromClientWaybill.Id); foreach (var distribution in returnedDistributions) { // Проверяем возможность отмены разнесения ValidationUtils.Assert(-distribution.Sum <= distribution.SourceDealPaymentDocument.UndistributedSum, "Невозможно отменить приемку накладной возврата, так как недостаточно средств для оплаты накладной реализации."); distribution.SourceDealPaymentDocument.RemoveDealPaymentDocumentDistribution(distribution); // Удаляем разнесение из оплаты } //---------- Проверяем наличие полной оплаты накладных реализации и устанавливаем им признак полной оплаты ------------ // Получаем идентификаторы всех накладных реализации, по которым отменен возврат var SQSalesIQueryable = saleWaybillRepository.GetRowsWithReturnsIQueryable(returnFromClientWaybill.Id); // Получаем все расшифровки распределения оплаты по данной накладной реализации var paymentDistributions = dealPaymentDocumentRepository.GetDealPaymentDocumentDistributionsForDestinationSaleWaybills(SQSalesIQueryable); var saleWaybillList = saleWaybillRepository.GetSaleWaybillsByReturnFromClientWaybill(returnFromClientWaybill.Id); // Проверяем платежные документы по всем накладным реализации foreach (var saleWaybill in saleWaybillList) { // Стоимость накладной реализации с учетом накладных возврата товаров, но без отменяемой накладной возврата товаров var saleWaybillCost = returnFromClientService.CalculateSaleWaybillCostWithReturns(saleWaybill, returnFromClientWaybill); // Вычисляем сумму платежей по данной накладной реализации var paymentSum = paymentDistributions.Where(x => x.SaleWaybill.Id == saleWaybill.Id).Sum(x => x.Sum); // Вычисляем сумму возвращенной оплаты по возвратам по данной накладной реализации (хранится отрицательной величиной) без отменяемого возврата var returnedSum = returnedDistributions.Where(x => x.SaleWaybill.Id == saleWaybill.Id && x.ReturnFromClientWaybill.Id != returnFromClientWaybill.Id).Sum(x => - x.Sum); // Оплачена ли накладная полностью? Устанавливаем признак полной оплаты saleWaybill.IsFullyPaid = (paymentSum - returnedSum - saleWaybillCost == 0M); // Обновляем индикатор по оплатам накладной реализации var returnSumPerSale = returnFromClientWaybill.Rows.Where(x => x.SaleWaybillRow.SaleWaybill == saleWaybill).Sum(x => x.SalePrice * x.ReturnCount).Value; var returnedPaid = -returnedDistributions.Where(x => x.SaleWaybill == saleWaybill).Sum(x => x.Sum); } }
/// <summary> /// Расчет основных показателей накладной /// </summary> public decimal CalculateAccountingPriceSum(ReturnFromClientWaybill waybill) { decimal?accountingPriceSum = 0M; if (waybill.IsAccepted) { accountingPriceSum = waybill.RecipientAccountingPriceSum; } else { var articleSubQuery = returnFromClientWaybillRepository.GetArticlesSubquery(waybill.Id); var accountingPrices = articlePriceService.GetAccountingPrice(waybill.RecipientStorage.Id, articleSubQuery); foreach (var row in waybill.Rows) { accountingPriceSum += (accountingPrices[row.Article.Id] ?? 0) * row.ReturnCount; } } return(Math.Round(accountingPriceSum.HasValue ? accountingPriceSum.Value : 0M, 2)); }
/// <summary> /// Расчет суммы накладной реализации с учетом всех сделанных по ней возвратов /// </summary> /// <param name="sale"></param> /// <returns></returns> public decimal CalculateSaleWaybillCostWithReturns(SaleWaybill sale, ReturnFromClientWaybill returnFromClientWaybillToExclude = null) { // Сумма всех возвратов по накладной реализации var returnedRow = returnFromClientWaybillRepository.Query <ReturnFromClientWaybillRow>(); // TODO рефакторить, ну кто так через OneOf пишет? Надо выбрать в RetWaybillRow SaleWaybillRow, а в нем - SaleWaybill.Id !!! - Олег returnedRow.OneOf(x => x.SaleWaybillRow.Id, sale.Rows.Select(x => x.Id)) .Restriction <ReturnFromClientWaybill>(x => x.ReturnFromClientWaybill) .Where(x => x.State == ReturnFromClientWaybillState.Receipted); if (returnFromClientWaybillToExclude != null) { returnedRow.Where(x => x.ReturnFromClientWaybill.Id != returnFromClientWaybillToExclude.Id); } var returnedSum = returnedRow.ToList <ReturnFromClientWaybillRow>() .Sum(x => x.SalePrice.Value * x.ReturnCount); // Отпускная цена уже должна быть установлена (иметь Value) // Вычисляем сумму накладной реализации decimal saleSum = sale.As <ExpenditureWaybill>().SalePriceSum; return(saleSum - returnedSum); }
/// <summary> /// Расчет процента отгрузки по накладной /// </summary> /// <param name="returnFromClientWaybill"></param> /// <returns></returns> public decimal CalculateShippingPercent(ReturnFromClientWaybill returnFromClientWaybill) { var articleSubQuery = returnFromClientWaybillRepository.GetArticlesSubquery(returnFromClientWaybill.Id); var accountingPrices = articlePriceService.GetAccountingPrice(returnFromClientWaybill.RecipientStorage.Id, articleSubQuery); bool areAccountingPricesSet = false; decimal totalInSum = 0M, totalOutSum = 0M, totalInCount = 0M, totalOutCount = 0M; foreach (var item in returnFromClientWaybill.Rows) { decimal?price = accountingPrices[item.Article.Id]; if (price != null && price != 0M) { areAccountingPricesSet = true; } decimal inCount = item.ReturnCount; totalInCount += inCount; totalInSum += inCount * (price ?? 0M); decimal outCount = item.TotallyReservedCount; totalOutCount += outCount; totalOutSum += outCount * (price ?? 0M); } if (areAccountingPricesSet) { return(totalInSum != 0M ? Math.Round((totalOutSum / totalInSum) * 100M, 2) : 0M); } else { return(totalInCount != 0M ? Math.Round((totalOutCount / totalInCount) * 100M, 2) : 0M); } }
public void Init() { // инициализация IoC IoCInitializer.Init(); setting = new Setting() { UseReadyToAcceptStateForReturnFromClientWaybill = false }; settingRepository = Mock.Get(IoCContainer.Resolve <ISettingRepository>()); settingRepository.Setup(x => x.Get()).Returns(setting); storage = new Storage("qwe", StorageType.ExtraStorage) { Id = 42 }; accOrgSender = new Mock <AccountOrganization>(); accOrgSender.Setup(x => x.Id).Returns(1); accOrgRecipient = new Mock <AccountOrganization>(); accOrgRecipient.Setup(x => x.Id).Returns(2); valueAddedTax = new ValueAddedTax(); user = new Mock <User>(); user.Setup(x => x.GetPermissionDistributionType(It.IsAny <Permission>())).Returns(PermissionDistributionType.All); createdBy = new Mock <User>(); createdBy.Setup(x => x.GetPermissionDistributionType(It.IsAny <Permission>())).Returns(PermissionDistributionType.All); acceptedBy = new Mock <User>(); acceptedBy.Setup(x => x.GetPermissionDistributionType(It.IsAny <Permission>())).Returns(PermissionDistributionType.All); receiptedBy = new Mock <User>(); receiptedBy.Setup(x => x.GetPermissionDistributionType(It.IsAny <Permission>())).Returns(PermissionDistributionType.All); var articleGroup = new ArticleGroup("Тестовая группа", "Тестовая группа"); var measureUnit = new MeasureUnit("шт.", "Штука", "123", 0) { Id = 1 }; articleA = new Article("Тестовый товар A", articleGroup, measureUnit, true) { Id = 1 }; articleB = new Article("Тестовый товар Б", articleGroup, measureUnit, true) { Id = 2 }; receiptWaybillRow1 = new Mock <ReceiptWaybillRow>(); receiptWaybillRow1.Setup(x => x.Article).Returns(articleA); receiptWaybillRow2 = new Mock <ReceiptWaybillRow>(); receiptWaybillRow2.Setup(x => x.Article).Returns(articleB); articleAccountingPrice = new List <ArticleAccountingPrice>() { new ArticleAccountingPrice(articleA, 100) }; returnFromClientWaybillRepository = Mock.Get(IoCContainer.Resolve <IReturnFromClientWaybillRepository>()); articlePriceService = Mock.Get(IoCContainer.Resolve <IArticlePriceService>()); articlePriceService.Setup(x => x.GetArticleAccountingPrices(It.Is <short>(y => y == storage.Id), It.IsAny <IEnumerable <int> >())).Returns(articleAccountingPrice); articlePriceService.Setup(x => x.GetArticleAccountingPrices(It.Is <short>(y => y == storage.Id), It.IsAny <ISubQuery>(), It.IsAny <DateTime>())).Returns(articleAccountingPrice); returnFromClientWaybillRepository = Mock.Get(IoCContainer.Resolve <IReturnFromClientWaybillRepository>()); expenditureWaybillIndicatorService = Mock.Get(IoCContainer.Resolve <IExpenditureWaybillIndicatorService>()); articleAvailabilityService = Mock.Get(IoCContainer.Resolve <IArticleAvailabilityService>()); returnFromClientWaybillService = new ReturnFromClientWaybillService( IoCContainer.Resolve <ISettingRepository>(), returnFromClientWaybillRepository.Object, IoCContainer.Resolve <ITeamRepository>(), IoCContainer.Resolve <IDealRepository>(), IoCContainer.Resolve <IStorageRepository>(), IoCContainer.Resolve <IUserRepository>(), IoCContainer.Resolve <IArticlePriceService>(), IoCContainer.Resolve <IAcceptedSaleIndicatorService>(), IoCContainer.Resolve <IReturnFromClientService>(), IoCContainer.Resolve <IFactualFinancialArticleMovementService>(), IoCContainer.Resolve <IArticleMovementOperationCountService>(), IoCContainer.Resolve <IArticleMovementService>(), IoCContainer.Resolve <IDealPaymentDocumentDistributionService>(), IoCContainer.Resolve <IDealIndicatorService>(), IoCContainer.Resolve <IArticleRevaluationService>(), expenditureWaybillIndicatorService.Object, articleAvailabilityService.Object ); deal = new Mock <Deal>(); quota = new DealQuota("asd", 10, 45, 15000); team = new Team("Тестовая команда", It.IsAny <User>()) { Id = 1 }; contract = new Mock <ClientContract>(); var economicAgent = new Mock <EconomicAgent>(); accountOrganization = new AccountOrganization("asd", "asd", economicAgent.Object); deal.Setup(x => x.IsActive).Returns(true); deal.Setup(x => x.IsClosed).Returns(false); deal.Setup(x => x.Quotas).Returns(new List <DealQuota> { quota }); deal.Setup(x => x.Contract).Returns(contract.Object); accountOrganization.AddStorage(storage); contract.Setup(x => x.AccountOrganization).Returns(accountOrganization); returnFromClientWaybill = new ReturnFromClientWaybill("123", DateTime.Now, accountOrganization, deal.Object, team, storage, new ReturnFromClientReason(), user.Object, createdBy.Object, DateTime.Now); sale = new Mock <ExpenditureWaybill>(); sale.Setup(x => x.Sender).Returns(accountOrganization); sale.Setup(x => x.Team).Returns(team); sale.Setup(x => x.Is <ExpenditureWaybill>()).Returns(true); sale.Setup(x => x.As <ExpenditureWaybill>()).Returns(sale.Object); #region Создание позиции 1 saleRow1 = new Mock <ExpenditureWaybillRow>(); saleRow1.Setup(x => x.ExpenditureWaybill).Returns(sale.Object); saleRow1.Setup(x => x.SaleWaybill).Returns(sale.Object); saleRow1.Setup(x => x.Id).Returns(Guid.NewGuid()); saleRow1.Setup(x => x.SellingCount).Returns(100); saleRow1.Setup(x => x.As <ExpenditureWaybillRow>()).Returns(saleRow1.Object); saleRow1.Setup(x => x.Is <ExpenditureWaybillRow>()).Returns(true); saleRow1.Setup(x => x.Article).Returns(articleA); saleRow1.Setup(x => x.SalePrice).Returns(128); saleRow1.Setup(x => x.ReceiptWaybillRow).Returns(receiptWaybillRow1.Object); #endregion #region Создание позиции 2 saleRow2 = new Mock <ExpenditureWaybillRow>(); saleRow2.Setup(x => x.ExpenditureWaybill).Returns(sale.Object); saleRow2.Setup(x => x.SaleWaybill).Returns(sale.Object); saleRow2.Setup(x => x.Id).Returns(Guid.NewGuid()); saleRow2.Setup(x => x.SellingCount).Returns(100); saleRow2.Setup(x => x.As <ExpenditureWaybillRow>()).Returns(saleRow2.Object); saleRow2.Setup(x => x.Is <ExpenditureWaybillRow>()).Returns(true); saleRow2.Setup(x => x.Article).Returns(articleA); saleRow2.Setup(x => x.SalePrice).Returns(128); saleRow2.Setup(x => x.ReceiptWaybillRow).Returns(receiptWaybillRow2.Object); #endregion ReturnFromClientWaybillRow row = new ReturnFromClientWaybillRow(saleRow1.Object, 1); returnFromClientWaybill.AddRow(row); articleMovementService = new Mock <IArticleMovementService>(); articleMovementService.Setup(x => x.CancelArticleAcceptance(It.IsAny <WriteoffWaybill>())) .Returns(new List <OutgoingWaybillRowSourceReservationInfo>() { new OutgoingWaybillRowSourceReservationInfo(row.Id, 1, 1) }); articleMovementService.Setup(x => x.AcceptArticles(It.IsAny <WriteoffWaybill>())) .Returns(new List <OutgoingWaybillRowSourceReservationInfo>() { new OutgoingWaybillRowSourceReservationInfo(row.Id, 1, 1) }); }
public void WaybillFinalizationCancelled(ReturnFromClientWaybill waybill) { articleMovementOperationCountIndicatorService.DecrementIndicator(waybill.ReceiptDate.Value, ArticleMovementOperationType.ReturnFromClient, waybill.RecipientStorage.Id); }
/// <summary> /// Пересчет финансовых показателей после отмены приемки товара по накладной возврата от клиента /// </summary> /// <param name="waybill">Накладная возврата от клиента</param> public void ReturnFromClientWaybillReceiptCancelled(ReturnFromClientWaybill waybill) { UpdateIndicatorsForReturnFromClientWaybill(waybill, -1); }
public void Init() { employee1 = new Employee("Работник 1 имя", "Работник 1 фамилия", "Работник 1 отчество", new EmployeePost("Работник 1 пост"), null); curator = new User(employee1, "Куратор", "log", "pas", new Team("Тестовая команда", null), null); team = new Team("123", curator); economicAgent = new PhysicalPerson(new LegalForm("Легал форм", EconomicAgentType.PhysicalPerson)); accountOrganization = new AccountOrganization("Орг1 кор имя", "орг1 длин имя", economicAgent) { Id = 1 }; accountOrganizationAnother = new AccountOrganization("Орг2 кор имя", "орг2 длин имя", economicAgent) { Id = 2 }; clientOrganization = new ClientOrganization("client org", "cllll", economicAgent) { Id = 3 }; client = new Client("клиент1", new ClientType("основной тип клиента"), ClientLoyalty.Follower, new ClientServiceProgram("программа 1"), new ClientRegion("Регион 1"), 10); deal = new Deal("Тестовая сделка", curator); client.AddDeal(deal); storage = new Storage("Склад 1", StorageType.ExtraStorage); storage.AddAccountOrganization(accountOrganization); storage.AddAccountOrganization(accountOrganizationAnother); storage2 = new Storage("Склад 2", StorageType.ExtraStorage); returnFromClientReason = new ReturnFromClientReason("Брак"); returnFromClientWaybill = new ReturnFromClientWaybill("142", DateTime.Today, accountOrganization, deal, team, storage, returnFromClientReason, curator, curator, DateTime.Now); valueAddedTax = new ValueAddedTax("18%", 18); ag = new ArticleGroup("Группа товаров", "Группа товаров"); art1 = new Article("Товар 1", ag, new MeasureUnit("шт.", "штуки", "123", 1), false); art2 = new Article("Товар 2", ag, new MeasureUnit("шт.", "штуки", "123", 1), false); art3 = new Article("Товар 3", ag, new MeasureUnit("шт.", "штуки", "123", 1), false); Prices = new List <ArticleAccountingPrice>(); Prices.Add(new ArticleAccountingPrice(art1, 10M)); Prices.Add(new ArticleAccountingPrice(art2, 13M)); Prices.Add(new ArticleAccountingPrice(art3, 15M)); deal1 = new Deal("Deal1", curator); deal2 = new Deal("Deal2", curator); quota1 = new DealQuota("qq", 1); quota2 = new DealQuota("qq", 2); deal1.AddQuota(quota1); deal2.AddQuota(quota2); deal1.Contract = new ClientContract(accountOrganization, clientOrganization, "Договор", "1", DateTime.Now, DateTime.Now); deal2.Contract = new ClientContract(accountOrganizationAnother, clientOrganization, "kk", "22", DateTime.Today, DateTime.Now); recRow1 = new ReceiptWaybillRow(art1, 5, 50, new ValueAddedTax("18%", 18)) { Id = Guid.NewGuid() }; recRow1_1 = new ReceiptWaybillRow(art1, 2, 30, new ValueAddedTax("18%", 18)) { Id = Guid.NewGuid() }; recRow2 = new ReceiptWaybillRow(art2, 7, 35, new ValueAddedTax("18%", 18)) { Id = Guid.NewGuid() }; recRow3 = new ReceiptWaybillRow(art3, 9, 90, new ValueAddedTax("18%", 18)) { Id = Guid.NewGuid() }; recRow1.PurchaseCost = 50 / 5; recRow1.PurchaseCost = 35 / 7; recRow1.PurchaseCost = 90 / 9; saleRow1 = new ExpenditureWaybillRow(recRow1, 3, valueAddedTax) { Id = Guid.NewGuid() }; saleRow1_1 = new ExpenditureWaybillRow(recRow1_1, 1, valueAddedTax) { Id = Guid.NewGuid() }; saleRow2 = new ExpenditureWaybillRow(recRow2, 4, valueAddedTax) { Id = Guid.NewGuid() }; saleRow3 = new ExpenditureWaybillRow(recRow3, 5, valueAddedTax) { Id = Guid.NewGuid() }; saleRowAnother1 = new ExpenditureWaybillRow(recRow1, 3, valueAddedTax) { Id = Guid.NewGuid() }; saleRowAnother2 = new ExpenditureWaybillRow(recRow2, 4, valueAddedTax) { Id = Guid.NewGuid() }; saleRowAnother3 = new ExpenditureWaybillRow(recRow3, 5, valueAddedTax) { Id = Guid.NewGuid() }; sale = new ExpenditureWaybill("1", DateTime.Today, storage, deal1, team, quota1, true, curator, DeliveryAddressType.ClientAddress, "", DateTime.Now, curator) { Id = Guid.NewGuid() }; saleAnother = new ExpenditureWaybill("1", DateTime.Today, storage, deal2, team, quota2, true, curator, DeliveryAddressType.ClientAddress, "", DateTime.Now, curator) { Id = Guid.NewGuid() }; sale.As <ExpenditureWaybill>().AddRow((ExpenditureWaybillRow)saleRow1); sale.As <ExpenditureWaybill>().AddRow((ExpenditureWaybillRow)saleRow2); sale.As <ExpenditureWaybill>().AddRow((ExpenditureWaybillRow)saleRow3); saleAnother.As <ExpenditureWaybill>().AddRow((ExpenditureWaybillRow)saleRowAnother1); saleAnother.As <ExpenditureWaybill>().AddRow((ExpenditureWaybillRow)saleRowAnother2); saleAnother.As <ExpenditureWaybill>().AddRow((ExpenditureWaybillRow)saleRowAnother3); sale.As <ExpenditureWaybill>().Accept(Prices, false, curator, DateTime.Now); saleAnother.As <ExpenditureWaybill>().Accept(Prices, false, curator, DateTime.Now); }
/// <summary> /// Возврат оплаты по возвращенным позициям /// </summary> /// <param name="returnFromClientWaybill">Накладная возврата товаров от клиента</param> /// <param name="currentDate">Дата операции</param> public void ReturnPaymentToSales(ReturnFromClientWaybill returnFromClientWaybill, DateTime currentDate) { // Получаем идентификаторы всех накладных реализации, по которым сделан возврат var SQSalesIQueryable = saleWaybillRepository.GetRowsWithReturnsIQueryable(returnFromClientWaybill.Id); // Получаем все расшифровки распределения оплаты по данной накладной реализации и кэшируем все их платежные документы и их коллекции расшифровок var paymentDistributions = dealPaymentDocumentRepository.GetDealPaymentDocumentDistributionsForDestinationSaleWaybills(SQSalesIQueryable); dealPaymentDocumentRepository.LoadSourceDealPaymentDocumentDistributions(paymentDistributions); var saleWaybillList = saleWaybillRepository.GetSaleWaybillsByReturnFromClientWaybill(returnFromClientWaybill.Id); var returnedPaymentDistributions = dealPaymentDocumentRepository.GetDistributionsToReturnsFromClientWaybillsForDestinationSaleWaybills(SQSalesIQueryable); // Возвращаем оплаты по всем накладным реализации, создавая разнесения этих оплат с отрицательными суммами foreach (var saleWaybill in saleWaybillList) { // разнесения на текущую накладную реализации var paymentDistributionListBySale = paymentDistributions.Where(x => x.SaleWaybill == saleWaybill); // возвраты оплаты по возвратам товаров var returnedPaymentDistributionsBySale = returnedPaymentDistributions.Where(x => x.SaleWaybill == saleWaybill); // Получаем оплаты по накладной реализации var dealPaymentDocumentList = paymentDistributionListBySale.Where(x => x.SaleWaybill == saleWaybill).Select(x => x.SourceDealPaymentDocument).Distinct(); // Стоимость накладной с учетом возвратов var saleWaybillCost = returnFromClientService.CalculateSaleWaybillCostWithReturns(saleWaybill); // Вычисляем сумму платежей по данной накладной реализации var paymentSum = paymentDistributionListBySale.Sum(x => x.Sum); // Вычисляем сумму ранее возвращенной оплаты по возвратам по данной накладной реализации (хранится отрицательной величиной) var returnedSum = returnedPaymentDistributionsBySale.Sum(x => - x.Sum); // Возвращаемая сумма оплат по накладной реализации. Она не может быть больше имеющейся оплаты var returnedPaid = (paymentSum - returnedSum > saleWaybillCost) ? paymentSum - returnedSum - saleWaybillCost : 0M; // Обновляем индикатор по оплатам накладной реализации var returnSumPerSale = returnFromClientWaybill.Rows.Where(x => x.SaleWaybillRow.SaleWaybill == saleWaybill).Sum(x => x.SalePrice * x.ReturnCount).Value; // Возвращаем средства начиная с последней оплаты (по времени создания) foreach (var dealPaymentDocument in dealPaymentDocumentList .OrderByDescending(x => x.Date) .OrderByDescending(x => x.CreationDate)) { if (returnedPaid == 0M) // Если вся сумма возвращена (или изначально равна нулю), то { break; // Завершаем цикл } // Вычисляем сумму, разнесенную на накладную реализации с данной оплаты var paidSum = paymentDistributionListBySale .Where(x => x.SourceDealPaymentDocument == dealPaymentDocument) .Sum(x => x.Sum); // Вычисляем уже возвращенную сумму по данной оплате (сумма возврата хранится отрицательной величиной) var returnedPaidSum = returnedPaymentDistributionsBySale .Where(x => x.SourceDealPaymentDocument == dealPaymentDocument) .Sum(x => - x.Sum); var rSum = Math.Min(paidSum - returnedPaidSum, returnedPaid); //вычисляем сумму, которая должна быть возвращена по данной оплате // Создаем возвратное разнесение оплаты. Возвращаемая сумма должна быть отрицательной. var pd = new DealPaymentDocumentDistributionToReturnFromClientWaybill(dealPaymentDocument, returnFromClientWaybill, saleWaybill, -rSum, returnFromClientWaybill.ReceiptDate.Value, currentDate); // Добавляем разнесение в оплату dealPaymentDocument.AddDealPaymentDocumentDistribution(pd); returnedPaid -= rSum; // Уменьшаем возвращаемую сумму на размер возвращенной оплаты (Вычисляем остаток возврата) } //---------- Проверяем наличие полной оплаты накладных реализации и устанавливаем им признак полной оплаты ------------ // Оплачена ли накладная полностью? Устанавливаем признак полной оплаты (Имеющийся излишек оплаты был уже возвращен) saleWaybill.IsFullyPaid = (paymentSum - returnedSum - saleWaybillCost >= 0M); } }