예제 #1
0
        /// <summary>
        /// Получить отфильтрованный список товаров, которые есть в расширенном наличии для указанных склада и организации.
        /// В список попадут только те товары, у которых [количество_доступное_для_резерва] > 0.
        /// </summary>
        /// <param name="storage">Место хранения.</param>
        /// <param name="organization">Собственная организация.</param>
        /// <param name="date">Дата.</param>
        /// <param name="state">Параметры фильтра и грида, в который будут выводится товары. После работы сюда будет записано новое состояние грида для возвращаемого списка товаров.</param>
        /// <returns>Отфильтрованный список товаров, имеющихся в расширенном наличии для указанных склада и организации.</returns>
        public IList <Article> GetExtendedAvailableArticles(Storage storage, AccountOrganization organization, DateTime date, object state)
        {
            var articleIdList = articleAvailabilityService.GetExtendedArticleAvailability(storage.Id, organization.Id, date).Where(x => x.Count > 0).Select(x => x.ArticleId).Distinct().ToList();

            var articleList = articleRepository.GetList(articleIdList);

            return(articleRepository.GetFilteredListByCollection(state, articleList));
        }
        /// <summary>
        /// Подготовить объект правила расчета учетной цены по умолчанию к работе (заполнить поля нужными списками)
        /// </summary>
        /// <returns>Готовое к работе правило расчета учетной цены по умолчанию</returns>
        public AccountingPriceCalcRule GetReadyAccountingPriceCalcRule(AccountingPriceCalcRule rule, IEnumerable <int> articleIdList, User user)
        {
            switch (rule.Type)
            {
            case AccountingPriceCalcRuleType.ByPurchaseCost:
                if (user.HasPermission(Permission.PurchaseCost_View_ForEverywhere))
                {
                    rule.CalcByPurchaseCost.AvailabilityList = articleAvailabilityService
                                                               .GetExactArticleAvailability(storageRepository.GetStorageSubQueryByAllPermission(), articleIdList, DateTime.Now).GroupBy(x => x.ArticleId)
                                                               .ToDynamicDictionary(x => x.Key, i => i.GroupBy(x => new Tuple <Guid, decimal>(x.BatchId, x.PurchaseCost))
                                                                                    .ToDictionary(x => x.Key, x => x.GroupBy(y => y.StorageId).ToDictionary(y => y.Key, y => y.Sum(z => z.Count))));

                    if (rule.CalcByPurchaseCost.PurchaseCostDeterminationRuleType == PurchaseCostDeterminationRuleType.ByLastPurchaseCost)
                    {
                        rule.CalcByPurchaseCost.LastPurchaseCostList = articlePriceService.GetLastPurchaseCost(articleIdList);
                    }
                }

                break;

            case AccountingPriceCalcRuleType.ByCurrentAccountingPrice:
                IEnumerable <Storage> storageList = new List <Storage>();

                if (rule.CalcByCurrentAccountingPrice.AccountingPriceDeterminationRule.Type == AccountingPriceDeterminationRuleType.ByAccountingPriceOnStorage)
                {
                    var storage = rule.CalcByCurrentAccountingPrice.AccountingPriceDeterminationRule.Storage;

                    if (user.HasPermissionToViewStorageAccountingPrices(storage))
                    {
                        storageList = new List <Storage> {
                            storage
                        };
                    }
                }
                else
                {
                    switch (rule.CalcByCurrentAccountingPrice.AccountingPriceDeterminationRule.StorageType)
                    {
                    case AccountingPriceListStorageTypeGroup.All:
                        storageList = storageRepository.GetAll();
                        break;

                    case AccountingPriceListStorageTypeGroup.DistributionCenters:
                        storageList = storageRepository.GetStoragesByType(StorageType.DistributionCenter);
                        break;

                    case AccountingPriceListStorageTypeGroup.ExtraStorages:
                        storageList = storageRepository.GetStoragesByType(StorageType.ExtraStorage);
                        break;

                    case AccountingPriceListStorageTypeGroup.TradePoints:
                        storageList = storageRepository.GetStoragesByType(StorageType.TradePoint);
                        break;
                    }

                    storageList = storageList.Where(s => user.HasPermissionToViewStorageAccountingPrices(s));
                }

                rule.CalcByCurrentAccountingPrice.AccountingPriceDeterminationRule.StorageList = storageList;

                rule.CalcByCurrentAccountingPrice.AccountingPrices = articlePriceService.GetAccountingPrice(storageList.Select(x => x.Id), articleIdList, DateTime.Now).Transpose();

                rule.CalcByCurrentAccountingPrice.AvailabilityList = articleAvailabilityService.GetExtendedArticleAvailability(articleIdList.Distinct(), storageList.Select(x => x.Id).Distinct(), DateTime.Now);
                break;

            default:
                throw new Exception("Неизвестный тип правила определения учетной цены.");
            }

            return(rule);
        }
예제 #3
0
        public AccountingPriceListMainIndicators GetMainIndicators(AccountingPriceList accountingPriceList, User user, bool calculateChangesAndMarkups = false)
        {
            var indicators = new AccountingPriceListMainIndicators();

            var allowToViewPurchaseCost = user.HasPermission(Permission.PurchaseCost_View_ForEverywhere);

            decimal purchaseCostSum, oldAccountingPriceSum, newAccountingPriceSum;

            // Находим актуальную дату (дату, на которую требуется получить наличие и учетные цены)
            // Если реестр проведен (a) - берем дату начала его действия (она может быть в будущем или в прошлом)
            // Если реестр не проведен (b), то:
            //  если дата его начала действия еще не наступила - на дату начала действия
            //  иначе - на текущую дату
            DateTime currentDate  = DateTime.Now;                                                                              // теоретически может измениться, пока идет расчет, так что зафиксируем
            DateTime newStateDate = accountingPriceList.StartDate > currentDate ? accountingPriceList.StartDate : currentDate; // актуальная дата для случая (b), если реестр не проведен

            if (accountingPriceList.State == AccountingPriceListState.Accepted && !accountingPriceList.AcceptanceDate.HasValue)
            {
                throw new Exception(String.Format("Реестр цен с номером {0} принят, но не имеет даты принятия. Обратитесь к разработчикам.", accountingPriceList.Number));
            }

            DateTime actualDate = accountingPriceList.State == AccountingPriceListState.Accepted ? accountingPriceList.StartDate : newStateDate;

            purchaseCostSum       = 0M;
            oldAccountingPriceSum = 0M;
            newAccountingPriceSum = 0M;

            var oldAccountingPriceListDictionaryList = articlePriceService.GetAccountingPrice(accountingPriceList, actualDate);
            var quantityListPerBatches     = articleAvailabilityService.GetExtendedArticleAvailability(accountingPriceList, actualDate);
            var accountingPriceListBatches = receiptWaybillService.GetRows(quantityListPerBatches.Select(x => x.BatchId).Distinct());
            var batchPurchaseCosts         = articlePriceService.GetArticlePurchaseCostsForAccountingPriceList(accountingPriceListBatches.Values.AsEnumerable <ReceiptWaybillRow>(), actualDate);

            foreach (var articlePrice in accountingPriceListRepository.GetArticleAccountingPrices(accountingPriceList.Id))
            {
                var articleId            = articlePrice.Article.Id;
                var quantityListPerBatch = quantityListPerBatches.Where(x => x.ArticleId == articleId);

                purchaseCostSum += quantityListPerBatch.Sum(x => x.Count * batchPurchaseCosts.FirstOrDefault(y => y.Key == x.BatchId).Value);

                foreach (var quantityItem in quantityListPerBatch)
                {
                    decimal?oldAccountingPrice = oldAccountingPriceListDictionaryList[quantityItem.StorageId][articleId];

                    if (oldAccountingPrice.HasValue)
                    {
                        oldAccountingPriceSum += quantityItem.Count * oldAccountingPrice.Value;
                    }
                    newAccountingPriceSum += quantityItem.Count * articlePrice.AccountingPrice;
                }
            }

            oldAccountingPriceSum = Math.Round(oldAccountingPriceSum, 2);
            newAccountingPriceSum = Math.Round(newAccountingPriceSum, 2);
            purchaseCostSum       = Math.Round(purchaseCostSum, 2);

            indicators.OldAccountingPriceSum = oldAccountingPriceSum;
            indicators.NewAccountingPriceSum = newAccountingPriceSum;
            indicators.PurchaseCostSum       = allowToViewPurchaseCost ? (decimal?)purchaseCostSum : null;

            if (calculateChangesAndMarkups)
            {
                indicators.AccountingPriceChangePercent = oldAccountingPriceSum != 0M ?
                                                          (decimal?)Math.Round(((newAccountingPriceSum - oldAccountingPriceSum) / oldAccountingPriceSum) * 100M, 2) : null;
                indicators.AccountingPriceChangeSum = Math.Round(newAccountingPriceSum - oldAccountingPriceSum, 2);
                indicators.PurchaseMarkupPercent    = allowToViewPurchaseCost && purchaseCostSum != 0M ?
                                                      (decimal?)Math.Round(((newAccountingPriceSum - purchaseCostSum) / purchaseCostSum) * 100M, 2) : null;
                indicators.PurchaseMarkupSum = allowToViewPurchaseCost ? (decimal?)Math.Round(newAccountingPriceSum - purchaseCostSum, 2) : null;
            }

            return(indicators);
        }