using AutoMapper; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Moq; using MyOffice.Data.Models.Accounts; using MyOffice.Data.Models.Items; using MyOffice.Data.Repositories.Account; using MyOffice.Data.Repositories.Currency; using MyOffice.Data.Repositories.Item; using MyOffice.Services.Account; using MyOffice.Services.Account.Domain; using MyOffice.Services.Identity; using MyOffice.Services.Item; using AccountEntity = MyOffice.Data.Models.Accounts.Account; namespace MyOffice.Tests.Accounts; public class MotionAddAclTests { [Fact] public async Task MotionAddAsync_returns_forbidden_without_write_access() { var userId = Guid.NewGuid(); var accountId = Guid.NewGuid(); var account = new AccountEntity { Id = accountId, Name = "Cash", AccessRights = [ new AccountAccess { UserId = userId, IsAllowRead = true, IsAllowWrite = false, IsAllowManage = false, } ] }; var accountRepo = new Mock(); accountRepo .Setup(x => x.GetAsync(userId, accountId, It.IsAny())) .ReturnsAsync(account); var service = CreateService(accountRepo.Object); var exec = await service.MotionAddAsync( userId, accountId, new MotionAddUpdate { Date = DateTime.UtcNow, Item = "Coffee", Plus = 0, Minus = 10, }); Assert.Equal(MotionAddStatus.forbidden, exec.Status); } [Fact] public async Task MotionAddAsync_skips_balancing_when_counterparty_not_writable() { var userId = Guid.NewGuid(); var primaryId = Guid.NewGuid(); var balancingId = Guid.NewGuid(); var primary = new AccountEntity { Id = primaryId, Name = "Cash", AccessRights = [ new AccountAccess { UserId = userId, IsAllowRead = true, IsAllowWrite = true } ] }; var balancing = new AccountEntity { Id = balancingId, Name = "Bank", AccessRights = [ new AccountAccess { UserId = userId, IsAllowRead = true, IsAllowWrite = false } ] }; var accountRepo = new Mock(); accountRepo .Setup(x => x.GetAsync(userId, primaryId, It.IsAny())) .ReturnsAsync(primary); accountRepo .Setup(x => x.GetAsync(userId, balancingId, It.IsAny())) .ReturnsAsync(balancing); var motionRepo = new Mock(); motionRepo .Setup(x => x.AddAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(true); var service = CreateService(accountRepo.Object, motionRepo.Object); var exec = await service.MotionAddAsync( userId, primaryId, new MotionAddUpdate { Date = DateTime.UtcNow, Item = "Transfer", Plus = 0, Minus = 25, AccountId = balancingId.ToString("N"), AmountBalancing = 25, }); Assert.Equal(MotionAddStatus.success, exec.Status); Assert.NotNull(exec.Result); Assert.Single(exec.Result!); motionRepo.Verify(x => x.AddAsync(It.IsAny(), It.IsAny()), Times.Once); } private static ItemService CreateItemServiceStub() { var nextId = 1; var itemRepo = new Mock(); var itemGlobalRepo = new Mock(); itemGlobalRepo .Setup(x => x.GetByNameAsync(It.IsAny(), It.IsAny())) .ReturnsAsync((ItemGlobal?)null); itemGlobalRepo .Setup(x => x.AddAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(true); itemRepo .Setup(x => x.GetByGlobalAsync(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync((Item?)null); itemRepo .Setup(x => x.AddAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(true) .Callback((i, _) => i.Id = nextId++); return new ItemService( Mock.Of(), itemRepo.Object, itemGlobalRepo.Object, new MapperConfiguration(_ => { }, NullLoggerFactory.Instance).CreateMapper()); } private static AccountService CreateService( IAccountRepository accountRepository, IMotionRepository? motionRepository = null) { var mapper = new MapperConfiguration( cfg => cfg.AddProfile(), NullLoggerFactory.Instance).CreateMapper(); return new AccountService( Mock.Of>(), mapper, Mock.Of(), Mock.Of(), Mock.Of(), accountRepository, Mock.Of(), Mock.Of(), motionRepository ?? Mock.Of(), Mock.Of(), Mock.Of(), CreateItemServiceStub(), Mock.Of()); } }