Example #1
0
        /// <summary>
        /// Попытаться оплатить накладную реализации из аванса (т.е. неразнесенных остатков платежных документов по сделке и команде).
        /// После разнесения может оставаться неоплаченный остаток у накладной или неразнесенные остатки платежных документов.
        /// Если накладная не имеет положительного остатка, расшифровки распределения оплаты не будут созданы.
        /// При полной оплате накладной реализации происходит установка признака того, что накладная полностью оплачена
        /// </summary>
        /// <param name="saleWaybill">Накладная реализации, на которую выполняется разнесение платежных документов</param>
        public void PaySaleWaybillOnAccept(SaleWaybill saleWaybill, DateTime currentDate)
        {
            // если сумма в ОЦ по накладной реализации = 0, выставляем признак полной оплаты и выходим
            if (saleWaybill.Is <ExpenditureWaybill>() && saleWaybill.As <ExpenditureWaybill>().SalePriceSum == 0)
            {
                saleWaybill.IsFullyPaid = true;
                return;
            }

            // При проводке данной накладной неоплаченный остаток равен сумме накладной в ОЦ
            var debtRemainder = saleWaybill.As <ExpenditureWaybill>().SalePriceSum;

            // получение информации о неразнесенных частях платежных документов
            var dealPaymentUndistributedPartsInfo = GetTotalDealPaymentUndistributedPartsInfo(saleWaybill.Deal, saleWaybill.Team);

            // разносим неоплаченные остатки на накладную
            PaySaleWaybill(dealPaymentUndistributedPartsInfo, saleWaybill, debtRemainder, debtRemainder, currentDate);
        }
Example #2
0
        /// <summary>
        /// Общая сумма всех возвратов по накладной реализации
        /// </summary>
        /// <param name="saleWaybill">Накладная реализации</param>
        /// <returns>Сумма</returns>
        public decimal GetTotalReservedByReturnSumForSaleWaybill(SaleWaybill saleWaybill)
        {
            if (saleWaybill.Is <ExpenditureWaybill>())
            {
                ExpenditureWaybill expenditureWaybill = saleWaybill.As <ExpenditureWaybill>();

                return(expenditureWaybillIndicatorService.GetTotalReservedByReturnSumForSaleWaybill(expenditureWaybill));
            }

            throw new Exception("Неизвестный тип накладной реализации.");
        }
Example #3
0
        /// <summary>
        /// Расчет неоплаченного остатка по накладной реализации
        /// </summary>
        /// <param name="saleWaybill">Накладная реализации</param>
        /// <returns>Неоплаченный остаток</returns>
        public decimal CalculateDebtRemainder(SaleWaybill saleWaybill)
        {
            if (saleWaybill.Is <ExpenditureWaybill>())
            {
                ExpenditureWaybill expenditureWaybill = saleWaybill.As <ExpenditureWaybill>();

                return(expenditureWaybillIndicatorService.CalculateDebtRemainder(expenditureWaybill));
            }

            throw new Exception("Неизвестный тип накладной реализации.");
        }
        /// <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);
        }
Example #5
0
        /// <summary>
        /// Разнести неразнесенные части платежных документов на накладную реализации.
        /// После разнесения у накладной реализации может оставаться неоплаченный остаток.
        /// Если до разнесения накладная реализации не имеет положительного неоплаченного остатка, разнесение платежного документа не будет создано.
        /// При полной оплате накладной реализации происходит установка признака того, что накладная реализации полностью оплачена.
        /// </summary>
        /// <param name="dealPaymentUndistributedPartsInfo">Список неразнесенных частей платежных документов</param>
        /// <param name="saleWaybill">Накладная реализации (единственная), на которую выполняется разнесение платежных документов</param>
        /// <param name="debtRemainder">Текущий неоплаченный остаток по накладной</param>
        /// <param name="sumToDistribute">Сумма к разнесению</param>
        /// <param name="currentDate">Дата операции</param>
        private void PaySaleWaybill(List <DealPaymentUndistributedPartInfo> dealPaymentUndistributedPartsInfo, SaleWaybill saleWaybill, decimal debtRemainder, decimal sumToDistribute, DateTime currentDate)
        {
            // разносим неразнесенные части оплат
            foreach (var distributionPartInfo in dealPaymentUndistributedPartsInfo.OrderBy(x => x.AppearenceDate))
            {
                var dealPaymentDocument = distributionPartInfo.DealPaymentDocument;

                // cумма создаваемого разнесения платежного документа
                decimal sum = Math.Min(distributionPartInfo.Sum, sumToDistribute);
                // вычитаем разносимую сумму
                distributionPartInfo.Sum -= sum;
                sumToDistribute          -= sum;

                // дата создаваемого разнесения
                var distributionDate = DateTimeUtils.GetMaxDate(distributionPartInfo.AppearenceDate, saleWaybill.AcceptanceDate.Value);

                ValidationUtils.Assert(dealPaymentDocument.Is <DealPaymentFromClient>() || dealPaymentDocument.Is <DealCreditInitialBalanceCorrection>(),
                                       "Платежный документ имеет недопустимый тип.");

                ValidationUtils.Assert(sum > 0, "Сумма для разнесения должна быть положительной.");

                if (saleWaybill.Is <ExpenditureWaybill>()) // Если появятся еще типы накладных реализации, вместо "накладная реализации товаров" выводить их названия
                {
                    ExpenditureWaybill expenditureWaybill = saleWaybill.As <ExpenditureWaybill>();

                    ValidationUtils.Assert(expenditureWaybill.IsAccepted, String.Format("Невозможно разнести платежный документ на накладную реализации товаров {0} со статусом «{1}».",
                                                                                        expenditureWaybill.Name, expenditureWaybill.State.GetDisplayName()));

                    ValidationUtils.Assert(sum <= debtRemainder, String.Format("Сумма для разнесения ({0} р.) превышает неоплаченный остаток накладной реализации товаров {1} ({2} р.)",
                                                                               sum.ForDisplay(ValueDisplayType.Money), expenditureWaybill.Name, debtRemainder.ForDisplay(ValueDisplayType.Money)));

                    ValidationUtils.Assert(dealPaymentDocument.Team == saleWaybill.Team,
                                           String.Format("Невозможно оплатить накладную реализации «{0}», т.к. она относится к другой команде.", saleWaybill.Name));

                    // формируем разнесение
                    var dealPaymentDocumentDistributionToSaleWaybill = new DealPaymentDocumentDistributionToSaleWaybill(dealPaymentDocument, expenditureWaybill, sum,
                                                                                                                        distributionDate, currentDate)
                    {
                        SourceDistributionToReturnFromClientWaybill = distributionPartInfo.DealPaymentDocumentDistributionToReturnFromClientWaybill
                    };

                    dealPaymentDocument.AddDealPaymentDocumentDistribution(dealPaymentDocumentDistributionToSaleWaybill);

                    debtRemainder -= sum;

                    // Если накладная реализации товаров полностью оплачена, ставим ей признак полной оплаты
                    expenditureWaybill.IsFullyPaid = debtRemainder <= 0M;
                }

                // и выходим
                if (saleWaybill.IsFullyPaid)
                {
                    break;
                }
            }

            // удаляем полностью разнесенные части
            var undistributedPartsToDelete = dealPaymentUndistributedPartsInfo.Where(x => x.Sum == 0).ToList();

            foreach (var item in undistributedPartsToDelete)
            {
                dealPaymentUndistributedPartsInfo.Remove(item);
            }
        }