namespace MyOffice.Web.Controllers; using AutoMapper; using Core; using Core.Extensions; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Models.Account; using Models.Item; using Models.Motion; using MyOffice.Web.Infrastructure.Attributes; using Services.Account; using Services.Account.Domain; using Services.Item; [Authorize] [ApiController] [Route("api/accounts")] [DefaultFromBody] public class AccountController : BaseApiController { private readonly ILogger _logger; private readonly IMapper _mapper; private readonly AccountService _accountService; private readonly ItemService _itemService; public AccountController( ILogger logger, IMapper mapper, AccountService accountService, ItemService itemService ) { _logger = logger; _mapper = mapper; _accountService = accountService; _itemService = itemService; } [HttpGet] public async Task AccountsGet([FromQuery] string category) { var list = await _accountService.GetByCategoryDetailedAsync(UserId, category!.AsGuid()); return OkResponse(_mapper.Map>(list.OrderBy(x => x.Account.Name).ToList())); } [HttpGet("{id}")] public async Task AccountGet(string id) { var exec = await _accountService.GetByIdDetailedAsync(UserId, id!.AsGuid()); return MapGeneralExec( exec, result => OkResponse(_mapper.Map(result)), notFoundDetail: "Account not found.", failureDetail: "Failed to load account."); } [HttpGet("{id}/motions")] public async Task MotionsGet(string id, [FromQuery] MotionsGetRequest request) { var exec = await _accountService.GetMotionsAsync( UserId, id!.AsGuid(), request.From.StartOfDay(), request.To.EndOfDay()); return MapGeneralExec( exec, result => OkResponse(_mapper.Map>(result)), notFoundDetail: "Account not found.", failureDetail: "Failed to load motions."); } [HttpPost("{id}/motions")] public async Task MotionsPost(string id, MotionRequest motion) { var exec = await _accountService.MotionAddAsync( UserId, id.AsGuid(), _mapper.Map(motion)); switch (exec.Status) { case MotionAddStatus.account_not_found: return ProblemNotFoundResponse("Account not found."); case MotionAddStatus.forbidden: return ProblemForbiddenResponse("Write access required."); case MotionAddStatus.failure: return ProblemBadResponse("Adding motion failed."); case MotionAddStatus.success: return Ok(_mapper.Map(exec.Result!)); default: throw new NotSupportedException(exec.Status.ToString()); } } [HttpPut("{id}/motions/{motionId}")] public async Task MotionsPut(string id, string motionId, MotionRequest motion) { var exec = await _accountService.MotionUpdateAsync( UserId, id.AsGuid(), motionId.AsGuid(), _mapper.Map(motion)); switch (exec.Status) { case MotionUpdateStatus.not_found: return ProblemNotFoundResponse("Motion not found."); case MotionUpdateStatus.forbidden: return ProblemForbiddenResponse("Write access required."); case MotionUpdateStatus.failure: return ProblemBadResponse("Updating motion failed."); case MotionUpdateStatus.success: return OkResponse(_mapper.Map>(exec.Result!)); default: throw new NotSupportedException(exec.Status.ToString()); } } [HttpDelete("{id}/motions/{motionId}")] public async Task MotionsDelete(string id, string motionId) { var exec = await _accountService.MotionRemoveAsync( UserId, id.AsGuid(), motionId.AsGuid()); switch (exec.Status) { case MotionDeleteStatus.not_found: return ProblemNotFoundResponse("Motion not found."); case MotionDeleteStatus.forbidden: return ProblemForbiddenResponse("Write access required."); case MotionDeleteStatus.failure: return ProblemBadResponse("Deliting motion failed."); case MotionDeleteStatus.success: return OkResponse(_mapper.Map(exec.Result!)); default: throw new NotSupportedException(exec.Status.ToString()); } } [HttpGet("~/api/items")] public async Task FindItems([FromQuery] string term, CancellationToken cancellationToken) { var itemsDto = await _itemService.FindItemsAsync(UserId, term, cancellationToken: cancellationToken); var items = _mapper.Map>(itemsDto); if (term.StartsWith("+") && term.Length > 1) { var foundAccounts = await _accountService.FindAccountsAsync(UserId, term.Substring(1), cancellationToken); var accounts = foundAccounts.OrderByDescending(x => x.Name); foreach (var account in accounts) { var accountName = $"+{account.Name}"; var item = items.FirstOrDefault(x => x.Name.IsPresent() && x.Name!.Length > 1 && x.Name.Substring(1) == accountName); if (item == null) { items.Add(new ItemViewModel { Name = accountName, AccountId = account.Id.ToShort(), }); } else { item.AccountId = account.Id.ToShort(); } } } return OkResponse(_mapper .Map>(items) .OrderBy(x => x.AccountId) .ThenBy(x => x.Name) ); } }