public void AccountingPriceList_CantAcceptWithZeroArticles() { try { var accountingPriceList = new AccountingPriceList("234", DateTime.Today.AddYears(1), DateTime.Today.AddYears(2), new List <Storage>() { storage1 }, user); accountingPriceList.Accept(DateTime.Now); Assert.Fail("Исключения не было."); } catch (Exception ex) { Assert.AreEqual("Невозможно провести реестр цен без товаров.", ex.Message); } }
public void AccountingPriceList_AcceptAndCancellationMustWork() { var accountingPriceList = new AccountingPriceList("234", DateTime.Today.AddYears(1), DateTime.Today.AddYears(2), storage1, articleAccountingPriceCorrectList1, user); var dateBeforeAccept = DateTime.Now; accountingPriceList.Accept(DateTime.Now); var dateAfterAccept = DateTime.Now; Assert.AreEqual(AccountingPriceListState.Accepted, accountingPriceList.State); Assert.IsNotNull(accountingPriceList.AcceptanceDate); Assert.IsTrue(dateBeforeAccept <= accountingPriceList.AcceptanceDate && accountingPriceList.AcceptanceDate <= dateAfterAccept); accountingPriceList.CancelAcceptance(); Assert.AreEqual(AccountingPriceListState.New, accountingPriceList.State); Assert.IsNull(accountingPriceList.AcceptanceDate); }
public void AccountingPriceList_StartDateTimeMustBeSet() { bool changed; DateTime startDate; // т.к. дата начала действяи РЦ меньше текущей даты, то дата начало должна стать равной текущей startDate = DateTime.Now.AddDays(-1); changed = AccountingPriceList.SetTimeForStartDateAndCheck(ref startDate, DateTime.Now); Assert.AreEqual(0, (startDate - DateTime.Now).Minutes); // разница должна быть меньше минуты Assert.IsTrue(changed); // т.к. дата начала действия больше текущей, то она не должна измениться startDate = DateTime.Now.AddDays(1); var oldStartDate = startDate; changed = AccountingPriceList.SetTimeForStartDateAndCheck(ref startDate, DateTime.Now); Assert.AreEqual(oldStartDate, startDate); Assert.IsFalse(changed); }
/// <summary> /// Получение списка необходимых РЦ при отмене проводки РЦ /// </summary> /// <param name="priceList">Отменяемый РЦ</param> public IEnumerable <AccountingPriceList> GetIntersectingPriceLists(AccountingPriceList priceList, DateTime currentDateTime) { // TODO: не самый оптимальный вариант реализации // По идее нужно для каждой пары МХ-товар найти РЦ, у которого StartDate < StartDate данного РЦ, а EndDate > EndDate данного РЦ, взять StartDate этого РЦ. // Затем для каждой пары МХ-товар нужно выбрать все РЦ, у которых StartDate больше определенного ранее StartDate. var endDate = (priceList.EndDate == null ? currentDateTime : priceList.EndDate.Value); var articleSubQuery = GetArticlesSubquery(priceList.Id); var storageSubQuery = GetStoragesSubquery(priceList.Id); var query = Query <AccountingPriceList>() .Where(x => x.AcceptanceDate != null && x.StartDate < endDate && (x.EndDate > priceList.StartDate || x.EndDate == null)) .PropertyIn(x => x.Storages, storageSubQuery); return(query.Restriction <ArticleAccountingPrice>(x => x.ArticlePrices) .PropertyIn(x => x.Article, articleSubQuery) .ToList <AccountingPriceList>()); }
private bool IsPermissionForTeamDistribution(AccountingPriceList priceList, User user, Permission permission) { switch (permission) { case Permission.AccountingPriceList_List_Details: case Permission.AccountingPriceList_Storage_Add: case Permission.AccountingPriceList_Storage_Remove: { return(user.Teams.Any(x => x.Storages.Any(y => priceList.Storages.Contains(y)))); //реестр распространяется хотя бы на одно МХ из команд пользователя } default: { var userStorages = user.Teams.SelectMany(x => x.Storages); return(priceList.Storages.All(x => userStorages.Contains(x))); //все МХ, на которые распространяется реестр входят в команды пользователя } } }
public void AccountingPriceList_ReceiptWaybill_Initial_Parameters_Must_Be_Set() { DateTime date1 = DateTime.Today.AddYears(1), date2 = DateTime.Today.AddYears(2).SetHoursMinutesAndSeconds(23, 59, 59); var accountingPriceList = new AccountingPriceList("234", date1, date2, receiptWaybill, storageList1, articleAccountingPriceCorrectList1, user, priceRule, digitRule); Assert.AreEqual(Guid.Empty, accountingPriceList.Id); Assert.AreEqual("234", accountingPriceList.Number); Assert.AreEqual(date1, accountingPriceList.StartDate); Assert.AreEqual(date2, accountingPriceList.EndDate); Assert.AreEqual(AccountingPriceListState.New, accountingPriceList.State); Assert.AreEqual(AccountingPriceListReason.ReceiptWaybill, accountingPriceList.Reason); Assert.AreEqual("Приход №123АБВ от " + DateTime.Today.ToShortDateString(), accountingPriceList.ReasonDescription); Assert.AreEqual(3, accountingPriceList.Storages.Count()); Assert.AreEqual(articleAccountingPriceWrongListOnlyA.Count(), accountingPriceList.ArticlePrices.Count()); }
public void AccountingPriceList_Autogeneration_Initial_Parameters_Must_Be_Set() { DateTime date1 = DateTime.Today.AddYears(1), date2 = DateTime.Today.AddYears(2).SetHoursMinutesAndSeconds(23, 59, 59); var accountingPriceList = new AccountingPriceList("234", date1, date2, storage1, articleAccountingPriceCorrectList1, user, priceRule, digitRule); Assert.AreEqual(Guid.Empty, accountingPriceList.Id); Assert.AreEqual("234", accountingPriceList.Number); Assert.AreEqual(date1.SetHoursMinutesAndSeconds(0, 0, 0), accountingPriceList.StartDate); Assert.AreEqual(date2.SetHoursMinutesAndSeconds(23, 59, 59), accountingPriceList.EndDate); Assert.AreEqual(AccountingPriceListState.New, accountingPriceList.State); Assert.AreEqual(AccountingPriceListReason.Storage, accountingPriceList.Reason); Assert.AreEqual("По месту хранения", accountingPriceList.ReasonDescription); Assert.AreEqual(1, accountingPriceList.Storages.Count()); Assert.AreEqual(articleAccountingPriceWrongListOnlyA.Count(), accountingPriceList.ArticlePrices.Count()); }
public void AccountingPriceList_Revaluation_Initial_Parameters_Must_Be_Set() { DateTime date1 = DateTime.Today.AddYears(1), date2 = DateTime.Today.AddYears(2).SetHoursMinutesAndSeconds(23, 59, 59); var accountingPriceList = new AccountingPriceList("123", date1, date2, storageList1, user, priceRule, digitRule); Assert.AreEqual(Guid.Empty, accountingPriceList.Id); Assert.AreEqual("123", accountingPriceList.Number); Assert.AreEqual(date1, accountingPriceList.StartDate); Assert.AreEqual(date2, accountingPriceList.EndDate); Assert.AreEqual(AccountingPriceListState.New, accountingPriceList.State); Assert.AreEqual(AccountingPriceListReason.Revaluation, accountingPriceList.Reason); Assert.AreEqual("Переоценка", accountingPriceList.ReasonDescription); Assert.AreEqual(3, accountingPriceList.Storages.Count()); Assert.AreEqual(0, accountingPriceList.ArticlePrices.Count()); }
public AccountingPriceListServiceTest() { articleGroup = new ArticleGroup("Бытовая техника", "Бытовая техника"); articleGroup.SalaryPercent = 15; articleGroup.Id = 8; measureUnit = new MeasureUnit("шт.", "Штука", "123", 0); measureUnit.Id = 17; article1 = new Article("Пылесос", articleGroup, measureUnit, true); article1.Id = 9; article2 = new Article("Фен", articleGroup, measureUnit, true); article2.Id = 29; article3 = new Article("Утюг", articleGroup, measureUnit, true); article3.Id = 421; storage1 = new Storage("Склад 1", StorageType.DistributionCenter); storage2 = new Storage("Склад 2", StorageType.DistributionCenter); articleAccountingPrice1_1 = new ArticleAccountingPrice(article1, 1M); articleAccountingPrice1_2 = new ArticleAccountingPrice(article2, 1001M); articleAccountingPrice1_3 = new ArticleAccountingPrice(article3, 1192.45M); user = new User(new Employee("Иван", "Иванов", "Иванович", new EmployeePost("Менеджер"), null), "Иванов Иван", "ivanov", "pa$$w0rd", new Team("Тестовая команда", null), null); accountingPriceList1 = new AccountingPriceList("27", DateTime.Now, null, new List <Storage> { storage1 }, user); accountingPriceList1.AddArticleAccountingPrice(articleAccountingPrice1_1); accountingPriceList1.AddArticleAccountingPrice(articleAccountingPrice1_2); accountingPriceList1.AddArticleAccountingPrice(articleAccountingPrice1_3); articleAccountingPrice2_1 = new ArticleAccountingPrice(article1, 34M); articleAccountingPrice2_2 = new ArticleAccountingPrice(article3, 56M); accountingPriceList2 = new AccountingPriceList("39", DateTime.Now, null, new List <Storage> { storage1, storage2 }, user); accountingPriceList2.AddArticleAccountingPrice(articleAccountingPrice2_1); accountingPriceList2.AddArticleAccountingPrice(articleAccountingPrice2_2); }
public void AccountingPriceList_ReDeletion_Must_Not_Work() { var accountingPriceList = new AccountingPriceList("123", DateTime.Today.AddYears(1), DateTime.Today.AddYears(2), new List <Storage>() { storage1 }, user); var curDate = DateTime.Now; var nextDate = curDate + new TimeSpan(1, 0, 0, 0); Assert.IsNull(accountingPriceList.DeletionDate); accountingPriceList.DeletionDate = curDate; Assert.AreEqual(curDate, accountingPriceList.DeletionDate); accountingPriceList.DeletionDate = nextDate; Assert.AreEqual(curDate, accountingPriceList.DeletionDate); Assert.AreNotEqual(nextDate, accountingPriceList.DeletionDate); }
public void AccountingPriceList_Revaluation_Must_Throw_Exception_On_NonUnique_Storages() { var storage = new Storage("Склад", StorageType.DistributionCenter) { Id = 1 }; try { var list = new AccountingPriceList("123", DateTime.Now, null, new List <Storage>() { storage, storage }, user, priceRule, digitRule); Assert.Fail("Исключения не было."); } catch (Exception ex) { Assert.AreEqual("Список мест хранения содержит повторяющиеся элементы.", ex.Message); } }
public void DeleteArticleAccountingPrice(AccountingPriceList accountingPriceList, ArticleAccountingPrice articleAccountingPrice) { accountingPriceList.DeleteArticleAccountingPrice(articleAccountingPrice); }
/// <summary> /// Создание связей между позициями РЦ и позициями входящих принятых с расхождениями накладных /// </summary> /// <param name="incomingRows">Список позиций входящих принятых с расхождениями накладных</param> /// <param name="priceList">РЦ</param> /// <param name="isOnAccountingPriceListStart">Признак: создается ли связь на начало периода действия РЦ</param> /// <param name="takingDate">Дата и время связи</param> public void CreateTakingFromIncomingDivergenceArticleAvailability(IEnumerable <IncomingWaybillRow> incomingRows, AccountingPriceList priceList, bool isOnAccountingPriceListStart, DateTime takingDate) { // если создаем связь на конец периода действия РЦ, но дата завершения действия РЦ не установлена - ошибка ValidationUtils.Assert(priceList.EndDate != null || isOnAccountingPriceListStart, "Не установлена дата окончания действия реестра цен."); foreach (var incomingRow in incomingRows) { var articleId = incomingRow.Batch.Article.Id; var articleAccountingPrice = priceList.ArticlePrices.Where(x => x.Article.Id == articleId).FirstOrDefault(); if (articleAccountingPrice != null) { var taking = new AccountingPriceListWaybillTaking(takingDate, true, articleAccountingPrice.Id, incomingRow.Type, incomingRow.Id, articleId, incomingRow.RecipientStorage.Id, incomingRow.Recipient.Id, articleAccountingPrice.AccountingPrice, isOnAccountingPriceListStart, 0); // для позиций, принятых с расхождениями, в связи указываем 0 accountingPriceListWaybillTakingRepository.Save(taking); } } }
/// <summary> /// Создание связей между позициями РЦ и позициями входящих принятых накладных по точному наличию (Дельта 0) /// </summary> /// <param name="incomingRows">Список позиций входящих принятых накладных</param> /// <param name="priceList">РЦ</param> /// <param name="isOnAccountingPriceListStart">Признак: создается ли связь на начало периода действия РЦ</param> /// <param name="takingDate">Дата и время связи</param> public void CreateTakingFromExactArticleAvailability(IEnumerable <IncomingWaybillRow> incomingRows, AccountingPriceList priceList, bool isOnAccountingPriceListStart, DateTime takingDate) { // если создаем связь на конец периода действия РЦ, но дата завершения действия РЦ не установлена - ошибка ValidationUtils.Assert(priceList.EndDate != null || isOnAccountingPriceListStart, "Не установлена дата окончания действия реестра цен."); foreach (var incomingRow in incomingRows) { var articleId = incomingRow.Batch.Article.Id; var articleAccountingPrice = priceList.ArticlePrices.Where(x => x.Article.Id == articleId).FirstOrDefault(); if (articleAccountingPrice != null) { var taking = new AccountingPriceListWaybillTaking(takingDate, true, articleAccountingPrice.Id, incomingRow.Type, incomingRow.Id, articleId, incomingRow.RecipientStorage.Id, incomingRow.Recipient.Id, articleAccountingPrice.AccountingPrice, isOnAccountingPriceListStart, incomingRow.AvailableInStorageCount); // для связи типа Дельта_0 можно сразу установить дату осуществления переоценки taking.RevaluationDate = isOnAccountingPriceListStart ? priceList.StartDate : priceList.EndDate.Value; accountingPriceListWaybillTakingRepository.Save(taking); } } }
/// <summary> /// Создание связей между позициями РЦ и позициями исходящих проведенных, но не отгруженных/не принятых получателем накладных (Дельта 1-) /// </summary> /// <param name="outgoingRows">Список позиций исходящих проведенных, но не отгруженных/не принятых получателем накладных</param> /// <param name="priceList">РЦ</param> /// <param name="isOnAccountingPriceListStart">Признак: создается ли связь на начало периода действия РЦ</param> /// <param name="takingDate">Дата и время связи</param> public void CreateTakingFromOutgoingAcceptedArticleAvailability(IEnumerable <OutgoingWaybillRow> outgoingRows, AccountingPriceList priceList, bool isOnAccountingPriceListStart, DateTime takingDate) { // если создаем связь на конец периода действия РЦ, но дата завершения действия РЦ не установлена - ошибка ValidationUtils.Assert(priceList.EndDate != null || isOnAccountingPriceListStart, "Не установлена дата окончания действия реестра цен."); foreach (var outgoingRow in outgoingRows) { var articleId = outgoingRow.Batch.Article.Id; var articleAccountingPrice = priceList.ArticlePrices.Where(x => x.Article.Id == articleId).FirstOrDefault(); if (articleAccountingPrice != null) { var taking = new AccountingPriceListWaybillTaking(takingDate, false, articleAccountingPrice.Id, outgoingRow.Type, outgoingRow.Id, articleId, outgoingRow.SenderStorage.Id, outgoingRow.Sender.Id, articleAccountingPrice.AccountingPrice, isOnAccountingPriceListStart, outgoingRow.Count); accountingPriceListWaybillTakingRepository.Save(taking); } } }
public void Delete(AccountingPriceList entity) { entity.DeletionDate = DateTime.Now; CurrentSession.SaveOrUpdate(entity); }
public void Save(AccountingPriceList entity) { CurrentSession.SaveOrUpdate(entity); CurrentSession.Flush(); }
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); }
/// <summary> /// Получить учетные цены по списку товаров и списку мест хранения из РЦ, действующие за 1 секунду перед наступлением указанного момента времени /// </summary> /// <remarks>Возвращает двумерный динамический массив "код МХ - код товара"</remarks> public DynamicDictionary <short, DynamicDictionary <int, decimal?> > GetAccountingPrice(AccountingPriceList accountingPriceList, DateTime?date) { date = date ?? DateTime.Now; date = date.Value.AddSeconds(-1); var indicators = articleAccountingPriceIndicatorService.GetList(accountingPriceList, date.Value); var result = new DynamicDictionary <short, DynamicDictionary <int, decimal?> >(); foreach (var item in indicators) { result[item.StorageId][item.ArticleId] = item.AccountingPrice; } return(result); }
public void CheckPossibilityToViewDetails(AccountingPriceList priceList, User user) { CheckPermissionToPerformOperation(priceList, user, Permission.AccountingPriceList_List_Details); }
public void AddStorage(AccountingPriceList accPriceList, Storage storage, IEnumerable <Storage> storageList, User user) { CheckPossibilityToAddStorage(accPriceList, user); accPriceList.AddStorage(storage); }
public void Delete(AccountingPriceList accountingPriceList, User user) { CheckPossibilityToDelete(accountingPriceList, user); accountingPriceListRepository.Delete(accountingPriceList); }
public void Save(AccountingPriceList accountingPriceList) { accountingPriceListRepository.Save(accountingPriceList); }
public void DeleteStorage(AccountingPriceList accPriceList, Storage storage, IEnumerable <Storage> storageList, User user) { CheckPossibilityToRemoveStorage(accPriceList, user); accPriceList.RemoveStorage(storage); }