Пример #1
0
        /// <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);
        }
Пример #2
0
 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);
            }
        }
Пример #5
0
        // 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);
            }
        }
Пример #8
0
        /// <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);
            }
        }
Пример #9
0
        /// <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));
        }
Пример #10
0
        /// <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);
        }
Пример #11
0
        /// <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);
 }
Пример #14
0
 /// <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);
        }
Пример #16
0
        /// <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);
            }
        }